• 实验: 动态对象年龄判定


    理论

    正常情况下, 年轻代空间里边的对象熬过 MaxTernuringThreshold 才能晋升到老年代;但是如果 survivor 空间中
    年龄1 + 年龄2 +年龄3 +…. + 年龄n (n>1)的这些对象大小的总和大于 survivor 空间的一半, 年龄大于或等于该年龄 n 的对象就会直接进入到老年代,不需要熬过那么多年龄

    实验代码

    public class DynamicAgeTest {
        private static Integer _1MB = 1024 * 1024;
    
        /**
         * jvm参数:
         * -verbose:gc -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 
         * @param args
         */
        public static void main(String[] args) {
            byte[] a1, a2, a3, a4, a5, a6;
    
            a1 = new byte[_1MB / 4];
    	    //先造成一次minorgc,让a1的年龄加一
            a2 = new byte[_1MB * 4];
            a3 = new byte[_1MB * 4];
    
            // a1 + a4 等于 survivor区一半
            a4 = new byte[_1MB / 4];
    	    //第二次minorgc,a1年龄=2,a4年龄=1
            a5 = new byte[_1MB * 4];
        }
    }
    

    gc日志

    第一次gc
    [GC (Allocation Failure) [DefNew:6177K->854K(9216K), 0.0047311 secs] 6177K->4950K(19456K), 0.0047783 secs] [Times: user=0.00 sys=0.01, real=0.01 secs]

    第二次gc
    [GC (Allocation Failure) [DefNew: 5447K->256K(9216K), 0.0041957 secs] 9543K->9299K(19456K), 0.0042255 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
    Heap
    def new generation total 9216K, used 4654K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
    eden space 8192K, 53% used [0x00000000fec00000, 0x00000000ff04b6e0, 0x00000000ff400000)
    from space 1024K, 25% used [0x00000000ff400000, 0x00000000ff440330, 0x00000000ff500000)
    to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
    tenured generation total 10240K,used 9043K[0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
    the space 10240K, 88% used [0x00000000ff600000, 0x00000000ffed4c08, 0x00000000ffed4e00, 0x0000000100000000)
    Metaspace used 3198K, capacity 4496K, committed 4864K, reserved 1056768K
    class space used 346K, capacity 388K, committed 512K, reserved 1048576K

    执行过程分析

    当创建a3=4m 的时候,eden放不下,需要先进行一次 minor gc,a1进入survivor 年龄+1, 但是由于a2=4m > survivor=1m 只能进入老年代,然后才能把 a3放入eden区,minor gc后内存分布如下:
    image

    接着创建对象 a4,内存分布:
    image

    当创建对象 a5=4m的时候, eden空余空间 8m-a3(4m) - a4(0.25m)=3.75m 不够了,需要先进行minor gc,gc后内存分布如下
    image
    这时候年轻代里边应该是有 a1+a4= 0.5m,为survivor的一半,但是gc日志里边雀显示from区只占用了25%,老年代 used 9043K 又大于 a2(4m) + a3(4m)= 8m,说明是a1或者a4跑到老年代了

    结合开头的理论 a1(年龄=2) + a4(年龄=1) 占用的空间等于survivor 的一半了,所以年龄n=2以及大于2的对象即a1需要晋升到老年代,最终内存分布如下
    image

    最终实验结果是和理论匹配的

    本文来自博客园,作者:mushishi,转载请注明原文链接:https://www.cnblogs.com/mushishi/p/14546665.html

  • 相关阅读:
    【马克-to-win】学习笔记—— 第五章 异常Exception
    【马克-to-win】—— 学习笔记
    Eclipse 日文乱码怎么解决Shift_JIS
    DB2设置code page(日文943)
    如何得到一个接口所有的实现类(及子接口)?例如:Eclipse IDE
    【VBA】随机数
    【VBA】利用Range声明Array(一维/二维)
    【VBA】Do While……Loop循环,遍历某列
    【58沈剑架构系列】DB主从一致性架构优化4种方法
    【58沈剑架构系列】主从DB与cache一致性
  • 原文地址:https://www.cnblogs.com/mushishi/p/14546665.html
Copyright © 2020-2023  润新知