JVM 新生代动态年龄判定并晋升老年代

对象的内存分配基本规律有以下几条:

  • 大多数情况下就是在堆上分配(但也可能经过JIT编译后被拆散为标量类型并间接地栈上分配)。
  • 对象主要分配在新生代的Eden区上。
  • 如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配。
  • 少数情况下也可能会直接分配在老年代中。
  • 对象的分配规则不是百分百固定的,其细节取决于当前使用的是哪一种垃圾收集组合,还有虚拟机中与内存相关的参数设置

为了能更好地适应不同程序的内存状况,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须达到MaxTenuringThreshold中要求的年龄。

在执行下面的testMaxTenuredThreshold2()方法时,设置了-XX:MaxTenuringThreshold=15参数,会发现运行结果中Survivor的空间占用仍然为0%,而老年代比预期增加了11%,也就是说,allocation1、allocation2对象都直接进入了老年代,而没有等到15岁的临界年龄。因为这两个对象加起来已经到达了512KB,并且它们是同年的,满足同年对象达到Survivor空间的一半规则。我们只要注释掉其中一个对象new操作,就会发现另外一个就不会晋升到老年代中去了。

-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:TargetSurvivorRatio=95

public static void testMaxTenuredThreshold2() {
        byte[] allocation1;
        byte[] allocation2;
        byte[] allocation3;
        byte[] allocation4;

        allocation1 = new byte[_1MB / 4];
        allocation2 = new byte[_1MB / 4];
        allocation3 = new byte[4 * _1MB];
        allocation4 = new byte[4 * _1MB];
        allocation4 = null;
        allocation4 = new byte[4 * _1MB];
    }

3223edc307c643bb8279f29b0459a9f2.png

# JVM  

评论

公众号:mumuser

企鹅群:932154986

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×