JVM & GC

133 阅读5分钟

JVM

JVM.png

  • 栈:对象的引用,即地址,等号左边的
  • 堆:new出来的对象,等号右边的
  • 方法区:常量,静态变量,类的信息
  • 本地方法栈:native方法使用,C语言相关
  • 程序计数器:程序运行的位置

字符串常量池在1.7之前(不含1.7)是在方法区,1.7之后在堆中 image.png

GC

因为堆和方法区是多线程共享的,某段程序运行结束并不能确定是否有其他线程还在使用该内容,不能自动删除,所以要利用GC来回收这些内存,即GC的目标是堆和方法区。

根搜索

用来判断一个对象是否可以回收,是否没有被引用。
根是搜索的起点,可以作为根的:

  • 上的引用直接或间接引用的对象
  • 本地方法栈上的引用直接或间接引用的对象
  • 方法区的静态变量直接或间接引用的对象

被搜索到的对象都是存活着的,不能回收

标记-清除

先用根搜索算法标记存活的对象,再将没有被标记的对象清除

缺点:会产生很多内存碎片

标记-整理

在标记-清除的基础上,整理内存碎片,将存活的对象整理集中在一起

缺点:需要移动对象,性能较低

复制

将堆分成两个区,每次使用一个区,内存满时,根搜索并标记后,将存活的对象复制到另一个区

缺点:需要更大的内存空间

当今的GC

将堆分为了年轻区和老年区,年轻区又分为伊甸区和两个幸存区。

伊甸区是新对象出生的地方,即刚被new出来时,当伊甸区满时触发minor GC,用根搜索标记存活的对象,将存活的对象复制到幸存区1,清空伊甸区,伊甸区再满时触发下次minor GC,用根搜索标记标伊甸区和幸存区1记存活的对象,将存活的对象复制到幸存区2,清空伊甸区和幸存区1,如此交替。

minor GC达到一定次数时,将幸存区的对象复制到老年区,当老年区满的时候会触发full GC,此时java程序暂停,对整个堆区全力进行垃圾回收,采用标记-清除,或标记-整理

新java版本采用G1算法

JVM参数配置

JVM中参数有3类:

  • - : 标准参数,所有的JVM实现都必须实现这些参数的功能,而且向后兼容
  • -X : 非标准参数,默认JVM实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容
  • -XX : 非稳定参数,各个JVM实现会有所不同,将来可能会随时取消

标准参数

  • -version :查看java版本
java -version
  • -jar: 执行jar包程序
  • -client: 设置JVM使用client模式,启动很快,但性能和内存管理效率并不高。串行GC
  • -server: 使用server模式,启动速度虽然慢(比client模式慢10%左右),但是性能和内存管理效率很高,适用于服务器,生产环境。并行GC
  • -classpath / -cp: JVM加载和搜索文件的目录路径
  • -verbose:class: 输出JVM载入类的相关信息
  • -verbose:gc: 输出每次GC的相关情况
  • -verbose:jni: 输出native方法调用的相关情况

非标准参数

输入java -X命令,能够获得当前JVM支持的所有非标准参数列表

  • -Xmn: 年轻代的内存大小,相当于同时设置了-XX:NewSize-XX:MaxNewSize
  • -Xms: 堆的初始内存大小,也是堆的最小内存值
  • -Xmx: 堆的内存最大值
  • -Xss: 每个线程的栈内存
  • -Xprof: 跟踪正运行的程序,并将跟踪数据在标准输出
  • -Xnoclassgc: 关闭针对class的GC功能
  • -Xincgc: 开启增量gc(默认为关闭),有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力
  • -Xloggc:file: 将每次GC事件的相关情况记录到一个文件中

非稳定参数

非稳定参数有如下格式:

  • -XX:+<option>: 启用选项
  • -XX:-<option>: 不启用选项
  • -XX:<option>=<value>: 给选项设置一个数字类型值,可跟单位,或字符串类型值
参数及其默认值描述
-XX:NewSize=2.125m年轻代初始内存的大小
-XX:MaxNewSize年轻代最大内存的大小
-XX:PermSize=64m方法区分配的初始内存
-XX:MaxPermSize=64m方法区所能占用的最大内存
-XX:ThreadStackSize=512线程栈大小,若为0则使用系统默认值,和-Xss作用一样
-XX:MaxTenuringThreshold=15对象在年轻代幸存区切换的次数,即MinorGC的次数,大于该值会进入老年代(年龄阈值)
-XX:MaxHeapFreeRatio=70GC后java堆中空闲量占的最大比例,大于该值,则堆内存会减少
-XX:MinHeapFreeRatio=40GC后java堆中空闲量占的最小比例,小于该值,则堆内存会增加
-XX:PretenureSizeThreshold大于该值的对象直接晋升入老年代
-XX:NewRatio=2老年代和年轻代内存比例
-XX:SurvivorRatio=8伊甸区和幸存区的比例,即Eden:Survivor1:Survivor2=8:1:1