JVM gc收集机制
#大家好 ,这是我个人的JAVA学习,以及相关知识的一个日记,其中会分享一些我自己的学习心得,以及算是对自己的一个监督,若有不足请大家指正,我们共同学习,共同进步!
这是一篇对于JAVA虚拟机jvm中的gc中的收集机制与算法的我个人一些理解,是我觉得jvm调优里面相当重要的一部分。
gc的类型与区别
我们知道jvm中的对象主要是存在内存堆里面,堆里面又分为年轻代以及老年代 。
- Minor GC (Young GC )
年轻代中又分Eden区以及Survivor区,当Eden区的空间放满了对象以后,虚拟机就会触发一次 Minor GC (Young GC ) ,清理年轻代无效的对象。Minor GC 触发是比较频繁的,但是回收速度相当快。
- Major GC (Full GC)
当老年代空间满了以后则会触发 Major GC(Full GC) 。触发Major GC则会回收老年代,年轻代,方法区的垃圾,所以Major GC的速度是Minor GC 的十倍甚至以上。
调优的方向
尽量减少Major GC的次数,以及减少MaJor GC的时间,因此需要对触发MaJor GC的机制要进一步了解。
对象什么时候进入老年代
1. 大对象直接进入老年代
大对象可通过设置JVM参数 -XX:PretenureSizeThreshold ,设置大对象的大小,超过该大小则会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下有效。
例如设置该参数 :==-XX:PretenureSizeThreshold=1000000 XX:+UseSerialGC == , 一个对象超过10M将会直接进入老年代。
为什么要这样呢? 为了避免为大对象分配内存时的复制操作而降低效率。
2. 长期存活的对象将直接进入老年代
虚拟机采用了分代收集的思想管理内存,在对象的的object头部信息中,会有一个分代年龄,一旦一个对象从Eden出生并且经过一次Minor GC 仍然存活并且能被 Survivor容纳的话,就会被移去Survivor区,并将对象年龄设为1 ,之后该对象在Survivor中每熬过一次Minor GC 则年龄+1.默认到15就就会被移入老年代,可Jvm参数通过==-XX:MaxTenuringThreshold== 来设置。
3.对象动态年龄判断
这个概念比较复杂抽象,就是在年轻代Survivor其中的一块区域(Survivor 分From 以及 To区),有一批对象总大小大于这块内存区域大小的50% ,那么此时大于等于这批对象年龄的最大值就可以直接进入老年代。虚拟机这样设计是希望长期存活的对象,尽早进入老年代,对象动态年龄判断一般是在 minor gc之后出发。
4.老年代空间分担担保机制
年轻代每次minor gc之后JVM都会计算老年代剩下可用空间,如果这个可用空间小于年轻代里先有的对象之和(包括垃圾对象)就会看一个JVM参数 XX:-HandlePromotionFailure ,jdk1.8及之后版本默认设置。 可以称之为担保参数。
如果设置了该参数,minor gc之前就会判断老年代剩余空间是否大于之前每一次 minor gc后进入老年代的对象的平均大小。
如果小于或者没有设置该参数,则会触发一次Full gc,直接将老年代,新生代里的垃圾数据回收。
以上是个人对jvm gc回收机制的几种情况的理解,如有不足或者遗漏,请指正。