045、JVM实战总结:动手实验:自己动手模拟出对象进入老年代的场景体验一下(上)

1、前文回顾

    略..

2、动态年龄判定规则

    进入老年代的4个时机:1、年龄到了 2、动态年龄判断 3、Survivor 放不下 4、大对象(G1例外)

    动态年龄判断:Young GC时,新对象(1岁)进入S区,如果Survivor区域内“年龄1+年龄2+...+年龄n”的对象总和大于Survivor区的50%,此时年龄n以上的对象会进入老年代。 

    新生代分配了10M,Eden 8M,From 1M ,To 1M

3、动态年龄判定规则的部分示例代码

-XX:NewSize=10485760

-XX:MaxNewSize=10485760

-XX:InitialHeapSize=20971520

-XX:MaxHeapSize=20971520

-XX:SurvivorRatio=8

-XX:MaxTenuringThreshold=15

-XX:PretenureSizeThreshold=10485760

-XX:+UseParNewGC

-XX:+UseConcMarkSweepGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:d:/gc.log
public class _44ToOldGC {

    static List<byte[]> longActiveList = new ArrayList<>();//长期存活

    static final int M = 1024 * 1024;

    static final int K = 1024;



    public static void main(String[] args) throws InterruptedException {

        System.gc();//先清除堆中的垃圾对象,否则后面的数值大小令人费解。不过运行过程中还是有额外的小空间多出来

        /**

         * 堆 20M

         * 新生代 10M (Eden 8M,From 1M ,To 1M)

         * 老年代 10M

         */

        allocate(2*M);

        allocate(2*M);

        allocate(2*M);

        addLongActiveObj(128*K);

        allocate(2*M);//此处触发YoungGC



    }

    private static void allocate(int size) {

        byte[] bytes = new byte[size];

    }



    private static void addLongActiveObj(int size){

        longActiveList.add(new byte[size]);

    }

}

 

 

 

4、部分示例代码运行后产生的gc日志

0.133: [Full GC (System.gc()) 0.133: [CMS: 0K->726K(10240K), 0.0033735 secs] 2230K->726K(19456K), [Metaspace: 3361K->3361K(1056768K)], 0.0034877 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.138: [GC (Allocation Failure) 0.138: [ParNew: 6473K->192K(9216K), 0.0006125 secs] 7200K->918K(19456K), 0.0006481 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap

par new generation   total 9216K, used 2404K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

  eden space 8192K,  27% used [0x00000000fec00000, 0x00000000fee29280, 0x00000000ff400000)

  from space 1024K,  18% used [0x00000000ff500000, 0x00000000ff530010, 0x00000000ff600000)

  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)

concurrent mark-sweep generation total 10240K, used 726K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)

Metaspace       used 3438K, capacity 4500K, committed 4864K, reserved 1056768K

  class space    used 374K, capacity 388K, committed 512K, reserved 1048576K

解读:

[CMS: 0K->726K(10240K), 0.0033735 secs] 2230K->726K(19456K) 

    0K->726K :有726K 晋升到老年代

    2230K->726K(19456K):堆中2230K(老年代0,新生代2230),堆中回收后就剩晋升到老年代的726K 

 

ParNew: 6473K->192K(9216K):6473(多个byte数组+未知对象),192K(128K的byte数组+未知存活对象) 

allocate(2*M);

allocate(2*M);

allocate(2*M);

addLongActiveObj(128*K);

allocate(2*M);//此处触发YoungGC

第五行代码触发了Young GC, 前三行代码分配的对象和其他一些未知对象被回收 ,回收后剩余192K

 

5、部分代码的GC日志分析

    见 4

6、动态年龄判断

 

将addLongActiveObj(128*K);改为addLongActiveObj(513*K); 使长期存活的占了From区的一半多一点点

然后在加入四行

allocate(2*M);

allocate(2*M);

allocate(2*M);

allocate(2*M);
0.140: [GC (Allocation Failure) 0.140: [ParNew: 6984K->577K(9216K), 0.0005920 secs] 7703K->1295K(19456K), 0.0006294 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.141: [GC (Allocation Failure) 0.141: [ParNew: 6939K->4K(9216K), 0.0006386 secs] 7658K->1257K(19456K), 0.0006760 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

    执行第四行时,触发YoungGC, 这次Young GC 没有Eden区的对象存活,此时Survivor区的存活对象年龄+1 变为2岁,一批同龄对象,直接超过了Survivor区空间的50%,此时也可能会导致对象进入老年代。

    ??按照文中的动态年龄判断逻辑不是应该“大于2岁”的对象进入老年代么? 如果按照专栏25讲描述的动态年龄判断逻辑倒是可以解释的通(一批同龄对象,直接超过了Survivor区空间的50%,此时也可能会导致对象进入老年代)

    答:对的,他就是同龄对象超过了Survivor的50%,所以进入老年代了  

PS:

    1、如果直接allocate(8*M),真正的大小比8M多一点点,Eden区肯定是放不下的,虽然没满足设置的大对象10M的要求,连YoungGC都不触发,直接进入老年代

    2、如果直接allocate(7*M+1000*K); 会回收两次,第一次放入时判断Eden放不下,触发YoungGC,回收之前allocate(2*M);放入的对象,放入后,可能系统又放了对象进来,有触发了一次 allocate(7*M+1000*K)被回收了

    

7、分析最终版的GC日志

    见6

8、今日思考题

    代码模拟出来对象达到5岁年龄之后自然进入老年代的场景

public static void maxTenuringTest() {

    for(int i=0;i<10;i++){

        allocate(4 * M);

        longActiveList.add(new byte[32*K]);

    }

}

 

GC日志:

0.137: [GC (Allocation Failure) 0.137: [ParNew: 4423K->80K(9216K), 0.0006453 secs] 5141K->797K(19456K), 0.0006869 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]

0.138: [GC (Allocation Failure) 0.138: [ParNew: 4373K->78K(9216K), 0.0003029 secs] 5091K->795K(19456K), 0.0003315 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.139: [GC (Allocation Failure) 0.139: [ParNew: 4371K->108K(9216K), 0.0004725 secs] 5089K->825K(19456K), 0.0005057 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.140: [GC (Allocation Failure) 0.140: [ParNew: 4398K->140K(9216K), 0.0002472 secs] 5116K->858K(19456K), 0.0002849 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.140: [GC (Allocation Failure) 0.140: [ParNew: 4429K->178K(9216K), 0.0003791 secs] 5147K->896K(19456K), 0.0004119 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.141: [GC (Allocation Failure) 0.141: [ParNew: 4466K->176K(9216K), 0.0004767 secs] 5184K->944K(19456K), 0.0005208 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.142: [GC (Allocation Failure) 0.142: [ParNew: 4463K->174K(9216K), 0.0003166 secs] 5232K->975K(19456K), 0.0003466 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.143: [GC (Allocation Failure) 0.143: [ParNew: 4460K->168K(9216K), 0.0004341 secs] 5262K->1002K(19456K), 0.0004739 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.144: [GC (Allocation Failure) 0.144: [ParNew: 4454K->172K(9216K), 0.0003660 secs] 5288K->1038K(19456K), 0.0004041 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

 

maxTenuringTest方法,循环第二次 allocate(4 * M);开始,会不断触发YoungGC,第六次开始,Survivor 区维持在174K左右,但堆的剩余在不断的增长,如下图。主要是因为每次有一个新的进入S区,就有一个年龄大的晋升到老年代。

本文是《从 0 开始带你成为JVM实战高手》内容总结,版权问题,特此声明。详细内容:

 

 

 

 

如果购买,成功后加QQ群找群主返现10元

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值