1. public class SurvivorTenuringTest {
  2. private static final int _1MB = 1024* 1024;
  3. /**
  4. *
  5. -verbose:gc
  6. -Xmx200M
  7. -Xmn50M
  8. -XX:+PrintTenuringDistribution
  9. -XX:+PrintGCDetails
  10. -XX:+PrintHeapAtGC
  11. -XX:+UseConcMarkSweepGC
  12. -XX:+UseParNewGC
  13. -XX:MaxTenuringThreshold=3
  14. Xmn:新生代大小 50M eden=40m s_from=5m s_to=5m
  15. UseParNewGC 年轻代采用parnew垃圾回收器
  16. UseConcMarkSweepGC 采用CMS垃圾回收器
  17. MaxTenuringThreshold 设置survivor的年龄为3,即对象年龄超过3次就进入老年代
  18. PrintTenuringDistribution 打印survivor区的年龄age信息
  19. */
  20. public static void main(String[] args) throws InterruptedException {
  21. // m, 在s0和s1不断来回拷贝增加age直到达到PretenureSizeThreshold晋升到old
  22. byte[] m = new byte[_1MB];
  23. // YoungGC后, m的age为1
  24. youngGc(1,40);
  25. // 再次YoungGC后, m的age为2
  26. youngGc(2,40);
  27. // 第三次YoungGC后, m的age为3
  28. youngGc(3,40);
  29. // 这次再ygc时, 由于m的年龄已经是3,且MaxTenuringThreshold=3, 所以m对象会晋升到Old区域,
  30. // 且ygc后, s0(from)和s1(to)空间中的对象被清空
  31. youngGc(4,40);
  32. }
  33. private static void youngGc(int n,int m) throws InterruptedException {
  34. System.out.println("...................发生第"+n+"次, young gc.............");
  35. for(int i=0; i<m; i++) {
  36. byte[] m_1 = new byte[_1MB];
  37. }
  38. }
  39. }

image.png
结论:
当survivor的对象年龄超过MaxTenuringThreshold阈值的时候,就进入old区。
思考:为什么这样做呢?

剖析survivor的动态年龄算法

image.png
image.png
那么问题来了?如何提前进入old区?
新的动态年龄判断算法:
Survivor区的对象年龄从小到大进行累加,
当累加到X年龄的总和大于50%(-XX:TargetSurvivorRatio=? 默认值是50),只要比 X大的都会晋升到老年代。
例如表格中
Survivor区的对象年龄从小到大进行累加,当累加到3年龄时的总和=70%大于50%,那么比3大的对象都会晋升到老年代。即4岁的15%、5岁的5%晋升到老年代。
image.png

  1. public class SurvivorRatioTest {
  2. private static final int _1MB = 1024* 1024;
  3. /**
  4. *
  5. -verbose:gc
  6. -Xmx200M
  7. -Xmn50M
  8. -XX:TargetSurvivorRatio=60
  9. -XX:+PrintTenuringDistribution
  10. -XX:+PrintGCDetails
  11. -XX:+PrintHeapAtGC
  12. -XX:+UseConcMarkSweepGC
  13. -XX:+UseParNewGC
  14. Xmn:新生代大小 50M eden=40m s_from=5m s_to=5m
  15. TargetSurvivorRatio动态年龄判断大小60
  16. UseParNewGC 年轻代采用parnew垃圾回收器
  17. UseConcMarkSweepGC 采用CMS垃圾回收器
  18. PrintTenuringDistribution 打印survivor区的年龄age信息
  19. */
  20. public static void main(String[] args) throws InterruptedException {
  21. //先计算理论值:survivor为5M,TargetSurvivorRatio=60%,即 当5M*60%=3M时,survivor对象进入old区
  22. byte[] m_1 = new byte[1363148];//1.3m
  23. youngGc(1,40);
  24. byte[] m_2 = new byte[838860];//0.8m
  25. youngGc(2,40);
  26. byte[] m_3 = new byte[_1MB];//1m
  27. youngGc(3,40);
  28. youngGc(4,40);
  29. }
  30. private static void youngGc(int n,int m) throws InterruptedException {
  31. System.out.println("...................发生第"+n+"次, young gc.............");
  32. for(int i=0; i<m; i++) {
  33. byte[] m_1 = new byte[_1MB];
  34. }
  35. }
  36. }