长期存活的对象将进入老年代
HotSpot虚拟机中多数收集器都采用了分代收集来管理堆内存, 那内存回收时就必须能决策哪些存活对象应当放在新生代, 哪些存活对象放在老年代中。 为做到这点, 虚拟机给每个对象定义了一个对象年龄(Age) 计数器, 存储在对象头中 。 对象通常在Eden区里诞生, 如果经过第一次Minor GC后仍然存活, 并且能被Survivor容纳的话, 该对象会被移动到Survivor空间中, 并且将其对象年龄设为1岁。 对象在Survivor区中每熬过一次Minor GC, 年龄就增加1岁, 当它的年龄增加到一定程度(默认为15) , 就会被晋升到老年代中。 对象晋升老年代的年龄阈值, 可以通过参数**-XX:MaxTenuringThreshold**设置。
1.MaxTenuringThreshold=1的情况
当我们以-XX: MaxTenuringThreshold=1 记性参数设置时,来执行以下代码:
/**
* @Des: 长期存活的对象进入老年代的测试
* VM参数: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC
* -XX:MaxTenuringThreshold=1 :当新生代对象的年龄达到1岁即可进入老年代
* -XX:+PrintTenuringDistribution:JVM 在每次新生代GC时,打印出幸存区中对象的年龄分布。
*/
public class TestLongObjToOld {
private static final int _1MB = 1024 * 1024;
public static void testTenuringThreshold() {
byte[] allocation1, allocation2, allocation3;
allocation1 = new byte[_1MB / 4]; //256KB 什么时候进入老年代决定于XX:MaxTenuringThreshold设置
allocation2 = new byte[4 * _1MB]; //4048KB
allocation3 = new byte[4 * _1MB];//4048KB eden共占用了 8352KB
allocation3 = null; //断开引用,成为垃圾对象
allocation3 = new byte[4 * _1MB]; //再申请分配4MB内存,放不下,触发Minor GC
}
public static void main(String[] args) {
testTenuringThreshold();
}
}
输出结果:
[GC (Allocation Failure) [DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age 1: 896768 bytes, 896768 total