Java中什么样的对象有资格进入老年代

当前我们使用的JVM的垃圾收集算法都是采用“分代”算法,将Java堆逻辑划分为年轻代(新生代)和老年代,并将对象按照其生命周期分配到对应的内存区域。那么什么对象会被分配到年轻代,什么对象被分配到老年代?

  1. 一定次数的minor gc后

    常规对象被创建之后是存储在年轻代的Eden区,每一个对象都有年龄,在YGC后,survivor1区还存活的对象的年龄全部+1,当对象年龄达到15时,被移交到老年代,15是系统默认的,我们可以通过JVM参数-XX:MaxTenuringThreshold来设置

  2. minor gc后survivor放不下

    在MinorGC之后存活的对象超过了survivor区的大小,会将这些对象直接转移到老年代

  3. survivor内同年龄对象大小

    如果再survivor区,有某一年龄的对象的总大小超过了survivor区大小的50%,则将这个年龄以上的对象全部转移到老年代

  4. 大对象

    所谓大对象就是指需要比较大的连续内存空间的Java对象,比如很长的字符串或数组,我们可以通过JVM参数-XX:PretenureSizeThreshold指定大对象的容量,单位是字节。

  5. 老年代分配担保规则

    在每一次执行Minor GC前,JVM都会检查一下老年代的剩余内存空间是否大于年轻代所有对象的总大小,目的是为了防止年轻代的对象在GC之后全部满足进入到老年代的条件,然后全部转移到老年代把老年代撑爆。

    1
    2
    3
    # 开启是否允许冒险进行MinorGC,在jdk1.6 update24版本之后取消该参数
    # 只要老年代的连续空间大于年轻代对象总大小或历次晋升到来年代对象的平均大小就进行YGC(MinorGC),否则进行FGC(MajorGC)
    -XX:-HandlePromotionFailure
    image-20200502154756565