public class SurvivorTenuringTest {
private static final int _1MB = 1024* 1024;
/**
*
-verbose:gc
-Xmx200M
-Xmn50M
-XX:+PrintTenuringDistribution
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:MaxTenuringThreshold=3
Xmn:新生代大小 50M eden=40m s_from=5m s_to=5m
UseParNewGC 年轻代采用parnew垃圾回收器
UseConcMarkSweepGC 采用CMS垃圾回收器
MaxTenuringThreshold 设置survivor的年龄为3,即对象年龄超过3次就进入老年代
PrintTenuringDistribution 打印survivor区的年龄age信息
*/
public static void main(String[] args) throws InterruptedException {
// m, 在s0和s1不断来回拷贝增加age直到达到PretenureSizeThreshold晋升到old
byte[] m = new byte[_1MB];
// YoungGC后, m的age为1
youngGc(1,40);
// 再次YoungGC后, m的age为2
youngGc(2,40);
// 第三次YoungGC后, m的age为3
youngGc(3,40);
// 这次再ygc时, 由于m的年龄已经是3,且MaxTenuringThreshold=3, 所以m对象会晋升到Old区域,
// 且ygc后, s0(from)和s1(to)空间中的对象被清空
youngGc(4,40);
}
private static void youngGc(int n,int m) throws InterruptedException {
System.out.println("...................发生第"+n+"次, young gc.............");
for(int i=0; i<m; i++) {
byte[] m_1 = new byte[_1MB];
}
}
}
结论:
当survivor的对象年龄超过MaxTenuringThreshold阈值的时候,就进入old区。
思考:为什么这样做呢?
剖析survivor的动态年龄算法
那么问题来了?如何提前进入old区?
新的动态年龄判断算法:
Survivor区的对象年龄从小到大进行累加,
当累加到X年龄的总和大于50%(-XX:TargetSurvivorRatio=? 默认值是50),只要比 X大的都会晋升到老年代。
例如表格中
Survivor区的对象年龄从小到大进行累加,当累加到3年龄时的总和=70%大于50%,那么比3大的对象都会晋升到老年代。即4岁的15%、5岁的5%晋升到老年代。
public class SurvivorRatioTest {
private static final int _1MB = 1024* 1024;
/**
*
-verbose:gc
-Xmx200M
-Xmn50M
-XX:TargetSurvivorRatio=60
-XX:+PrintTenuringDistribution
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
Xmn:新生代大小 50M eden=40m s_from=5m s_to=5m
TargetSurvivorRatio动态年龄判断大小60
UseParNewGC 年轻代采用parnew垃圾回收器
UseConcMarkSweepGC 采用CMS垃圾回收器
PrintTenuringDistribution 打印survivor区的年龄age信息
*/
public static void main(String[] args) throws InterruptedException {
//先计算理论值:survivor为5M,TargetSurvivorRatio=60%,即 当5M*60%=3M时,survivor对象进入old区
byte[] m_1 = new byte[1363148];//1.3m
youngGc(1,40);
byte[] m_2 = new byte[838860];//0.8m
youngGc(2,40);
byte[] m_3 = new byte[_1MB];//1m
youngGc(3,40);
youngGc(4,40);
}
private static void youngGc(int n,int m) throws InterruptedException {
System.out.println("...................发生第"+n+"次, young gc.............");
for(int i=0; i<m; i++) {
byte[] m_1 = new byte[_1MB];
}
}
}