读《深入理解jvm虚拟机》之长期存活对象进入老年代,有感!!!!

关于这一段代码 有几个不是让人很理解的地方,我一一说来。

1.Desired survivor size 524288 bytes

  关于这个512KB空间是怎么来的,JVM有这样一个参数:

  -XX:TargetSurvivorRatio:目标存活率,默认为50%,表明所有age的survivor space对象的大小如果超过Desired survivor size,则重新计算threshold,以age和MaxTenuringThreshold的最小值为准,否则以MaxTenuringThreshold为准.

  简单的说,如果要分配的Survivor空间是1M那么,desired survivor size 就是512KB,这个大小影响的是Tenuring Threshold参数

  当你试图放入800KB的对象是,Survivor from是运行你放入的,但是Tenuring Threshold大小会变成1(就算你之前是15,这里也会动态改成1),即下次GC发生时,age=1的统统放入老年代

2.Eden,Survivor from,to的关系

  对象分配空间的时候,若Eden仍有区域时,都会将对象放置Eden,持续新增对象一段时间后,Eden无法容纳时,这个时候就会发生一次Minor GC。

  当发生Minor GC时,会将Eden和 Survivor from中的幸存对象存放在Survivor to中,同时这些对象的age+1。

  若Survivor to无法容纳幸存对象,就将无法容纳的对象放置在永久带中。

  当GC时,存在对象的age=Tenuring Threshold时,不管Survivor to是否空间足够,都将他们放入永久代。

发生GC的前提,放入对象时空间不够,放入对象后空间占用完毕。


这段例子中,当XX:MaxTenuringThreshold=1时

a1 = 0.25M,a2=4M;

分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC,此时a1,a2 age=1,

这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2

虚拟机将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)

放入4M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了

a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC(这时,jvm会清理age=1的对象,a1,a2被放在了老年代)

发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。

此时空间分布Eden(4M),Survivor from(0M),Old(4.25M)

/**
     * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution
     * 
     */
    @SuppressWarnings("unused")
    public static void testTenuringThreshold() {
        byte[] allocation1, allocation2, allocation3;
        allocation1 = new byte[_1MB / 4];  //262144 什么时候进入老年代决定于XX:MaxTenuringThreshold设置
        allocation2 = new byte[4 * _1MB]; //4194304
        allocation3 = new byte[4 * _1MB];
        allocation3 = null;
        allocation3 = new byte[4 * _1MB];
    /**
         * 
         * XX:MaxTenuringThreshold=1
         [GC [DefNew
                Desired survivor size 524288 bytes, new threshold 1 (max 1)
                - age   1:     418144 bytes,     418144 total
                : 4695K->408K(9216K), 0.0054252 secs] 4695K->4504K(19456K), 0.0054708 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
                [GC [DefNew
                Desired survivor size 524288 bytes, new threshold 1 (max 1)
                - age   1:        136 bytes,        136 total
                : 4668K->0K(9216K), 0.0013601 secs] 8764K->4504K(19456K), 0.0013867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
                Heap
                 def new generation   total 9216K, used 4260K [0x32750000, 0x33150000, 0x33150000)
                  eden space 8192K,  52% used [0x32750000, 0x32b78fe0, 0x32f50000)
                  from space 1024K,   0% used [0x32f50000, 0x32f50088, 0x33050000)
                  to   space 1024K,   0% used [0x33050000, 0x33050000, 0x33150000)
                 tenured generation   total 10240K, used 4504K [0x33150000, 0x33b50000, 0x33b50000)
                   the space 10240K,  43% used [0x33150000, 0x335b60a0, 0x335b6200, 0x33b50000)
                 compacting perm gen  total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
                   the space 12288K,   3% used [0x33b50000, 0x33bae5c0, 0x33bae600, 0x34750000)
                    ro space 10240K,  55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
                    rw space 12288K,  55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
         */
}

   

这段例子中,当XX:MaxTenuringThreshold=8时

a1 = 0.25M,a2=4M;

分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC

这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2

虚拟将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)

放入3M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了

a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC

发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。

此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

/**
         * 
         * XX:MaxTenuringThreshold =8
         [GC [DefNew
                Desired survivor size 524288 bytes, new threshold 8 (max 8)
                - age   1:     418144 bytes,     418144 total
                : 4695K->408K(9216K), 0.0036693 secs] 4695K->4504K(19456K), 0.0036983 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
                [GC [DefNew
                Desired survivor size 524288 bytes, new threshold 8 (max 8)
                - age   1:        136 bytes,        136 total
                - age   2:     417936 bytes,     418072 total
                : 4668K->408K(9216K), 0.0010034 secs] 8764K->4504K(19456K), 0.0010296 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
                Heap
                 def new generation   total 9216K, used 4668K [0x32750000, 0x33150000, 0x33150000)
                  eden space 8192K,  52% used [0x32750000, 0x32b78fe0, 0x32f50000)
                  from space 1024K,  39% used [0x32f50000, 0x32fb6118, 0x33050000)
                  to   space 1024K,   0% used [0x33050000, 0x33050000, 0x33150000)
                 tenured generation   total 10240K, used 4096K [0x33150000, 0x33b50000, 0x33b50000)
                   the space 10240K,  40% used [0x33150000, 0x33550010, 0x33550200, 0x33b50000)
                 compacting perm gen  total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
                   the space 12288K,   3% used [0x33b50000, 0x33bae5b8, 0x33bae600, 0x34750000)
                    ro space 10240K,  55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
                    rw space 12288K,  55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
         */
原文地址:https://www.cnblogs.com/Yiran583/p/8795415.html