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=3Xmn:新生代大小 50M eden=40m s_from=5m s_to=5mUseParNewGC 年轻代采用parnew垃圾回收器UseConcMarkSweepGC 采用CMS垃圾回收器MaxTenuringThreshold 设置survivor的年龄为3,即对象年龄超过3次就进入老年代PrintTenuringDistribution 打印survivor区的年龄age信息*/public static void main(String[] args) throws InterruptedException {// m, 在s0和s1不断来回拷贝增加age直到达到PretenureSizeThreshold晋升到oldbyte[] m = new byte[_1MB];// YoungGC后, m的age为1youngGc(1,40);// 再次YoungGC后, m的age为2youngGc(2,40);// 第三次YoungGC后, m的age为3youngGc(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:+UseParNewGCXmn:新生代大小 50M eden=40m s_from=5m s_to=5mTargetSurvivorRatio动态年龄判断大小60UseParNewGC 年轻代采用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.3myoungGc(1,40);byte[] m_2 = new byte[838860];//0.8myoungGc(2,40);byte[] m_3 = new byte[_1MB];//1myoungGc(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];}}}
