• 《深入理解java虚拟机》读书笔记——垃圾收集与内存分配策略


    可回收判定两种算法
    引用计数法(Reference Counting):引用为0时可回收。
    可达性分析法(Reachability Analysis): 从GCRoots对象到这个对象不可达。
    GCRoots:
    • 本地变量表引用的对象;
    • 方法区中静态属性引用的对象
    • 方法区中常量引用的对象
    • Native方法栈引用的对象。
    个人理解,即在生命周期内不会变得不可达的对象。
     
    垃圾收集算法
    复制算法,一般用于新生代的minor gc,效率较高;
    标记-整理算法,用于老年代的full gc,效率较低。
     
    内存分配回收策略
    1、在新生代 Eden区分配内存(大对象可能直接分配到老年代)。新生代内存不够用,则触发minor gc到步骤2;
    2、标记可回收对象;
    3、将存活对象复制到Survivor区(to survivor),年龄计数器+1,年龄超过阈值的对象复制到老年代,或按动态年龄判定复制到老年代;
    4、清空Eden区和from survivor区。存活下来的对象(年龄>=1)留在了survivor区;
    5、触发minor gc之前检查,发现分配担保有风险(老年代剩余空间小于所有对象总空间),且HandlePromotionFailure=false,则触发一次full gc。
    6、触发minor gc之前检查,虽然HandlePromotionFailure=true,但分配担保失败概率较高,则触发一次full gc。
    7、如果在写老年代时,发现老年代不够用(担保失败),则触发一次full gc; 
     
    测试代码
    public class TestGC{
            public static void main(String[] argv){
                    BigObj obj1 = new BigObj();
                    BigObj obj2 = new BigObj();
                    obj1 = new BigObj();
                    obj2 = new BigObj();
                    BigObj obj3 = new BigObj();
                    BigObj obj4 = new BigObj();
            }
            static class BigObj{
                    private byte[] arr = new byte[3145728];
            }
    }
    执行命令:java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -classpath .  TestGC
    运行结果
     
    [GC [PSYoungGen: 6831K->432K(9216K)] 6831K->6576K(19456K), 0.0033010 secs] [Times: user=0.02 sys=0.01, real=0.00 secs]
    [Full GC [PSYoungGen: 432K->0K(9216K)] [ParOldGen: 6144K->6373K(10240K)] 6576K->6373K(19456K) [PSPermGen: 2586K->2585K(21504K)], 0.0069120 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
    [Full GC [PSYoungGen: 6315K->0K(9216K)] [ParOldGen: 6373K->6371K(10240K)] 12689K->6371K(19456K) [PSPermGen: 2585K->2585K(21504K)], 0.0044660 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
    Heap
     PSYoungGen      total 9216K, used 6339K [0x00000007ff600000, 0x0000000800000000, 0x0000000800000000)
      eden space 8192K, 77% used [0x00000007ff600000,0x00000007ffc30cf0,0x00000007ffe00000)
      from space 1024K, 0% used [0x00000007ffe00000,0x00000007ffe00000,0x00000007fff00000)
      to   space 1024K, 0% used [0x00000007fff00000,0x00000007fff00000,0x0000000800000000)
     ParOldGen       total 10240K, used 6371K [0x00000007fec00000, 0x00000007ff600000, 0x00000007ff600000)
      object space 10240K, 62% used [0x00000007fec00000,0x00000007ff238fc0,0x00000007ff600000)
     PSPermGen       total 21504K, used 2592K [0x00000007f9a00000, 0x00000007faf00000, 0x00000007fec00000)
      object space 21504K, 12% used [0x00000007f9a00000,0x00000007f9c88310,0x00000007faf00000)
    这段代码一共生成了6个对象,分别叫做 obj1,obj2,obj1_,obj2_,obj3,obj4;
    预想的结果是:
    1. obj1和obj2分配到新生代Eden区,约6M;
    2. 分配obj1_时,eden区空间不足,触发一次minor gc。由于survivor区大小只有1M,将obj1和obj2复制到老年代,eden区清空(日志中还有432k不知道是什么内容)
    3. obj1_和obj2_分配到新生代Eden区,约6M;此时obj1和obj2都变成了可回收对象;
    4. 分配obj3时,eden区空间不足,触发一次minor gc。由于空间担保失败,触发full gc,老年代的obj1和obj2清空,新生代的obj1_和obj2_复制到老年代,eden区清空。此时老年代占用6M,新生代0M;
    5. obj3和obj4分配到eden区。最终老年代占用6M,新生代占用6M。
    日志和预想的结果有出入,好像是在第2步后额外触发了一次full gc。可能和Parallel Scavenge的悲观策略有关
    另外,从日志可以看出,虚拟机使用的收集器组合是Parallel Scavenge+Parallel Old。
  • 相关阅读:
    vue-router基础使用
    Vue插槽
    Vue组件通信
    小程序自定义头部导航栏
    css日常积累
    移动端的无缝轮播图片
    vue的h5开发中,将页面保存为图片
    vue-webpack打包问题
    洛谷P1341 最受欢迎的奶牛
    Tarjan 算法详解
  • 原文地址:https://www.cnblogs.com/night1989/p/jvm.html
Copyright © 2020-2023  润新知