GC垃圾回收机制

一、GC算法

    1.标记-清除算法(Mark Sweep):    缺:效率低、有内存碎片
            a.标记阶段:遍历所有GC roots,将gc roots引用链可达的对象标记为存活;     
            b.清理阶段:遍历堆中所有对象,清理未被标记的对象。    

    2.复制算法:先根据引用链做可达性分析,把活着的对象复制过去,然后把原区域清空。
            优:解决内碎片问题;存活率低时效率高
            缺:浪费内存;对象存活率高时效率低下

    3.标记-整理算法:移动所有存活对象,按地址排序,把后面的清除。 效率也不高

    4.分代收集:新生代采用复制算法(存活率低)、老年代采用标记整理算法(存活率高)。      
            原因:大部分对象的生命周期很短,极少部分可能会存活很久,这部分对象每次gc反复标记处理,浪费资源。

    5.判断是不是垃圾:    引用记数法(循环引用时内存泄露);
            可达性分析:从gc roots开始通过引用关系遍历对象图,能被引用链遍历到的认为存活(基本都是用这种方式)

    6.GC roots:引用链的最顶级,是一组必须活跃的引用,不是对象! minor gc比full gc的gc roots还要更多,因为要从old gen里面额外拿gc roots.      gc roots有哪些: a.活跃的栈帧中的引用对象;  b.方法区中静态属性指向堆中对象的引用;  c.本地方法栈中JNI(native方法)的引用

    7.stop-the-world:gc的时候,停掉除gc外的java线程。

二、gc收集器

    1. Serial / Serial old:单线程;复制算法 / 标记整理算法;停顿时间长
        ParNew:多线程;新生代的复制算法
        Parallel Scavenge / Parallel old:多线程(paralle:并行),复制算法 / 标记整理算法;注重吞吐量: T运行 / (T运行+Tgc)
        CMS:多线程;老年代标记m清除s算法;   优:停顿时间短;   缺:吃cpu资源,有内存碎片,清理阶段会产生新垃圾(浮动垃圾)
                 cms执行过程: 1.STW标记gc roots引用的对象;  2.和用户线程一起并发标记其他对象; 
                                        3.STW标记第二步新增的对象;  4.和用户线程一起并发清理垃圾。
        G1:区域化、并发、增量式垃圾回收器。  整体看是标记整理,局部(两个region之间)是复制算法。  
                引入分区的思路,弱化了分代的概念。 整个堆内存被分为许多大小相等的连续区域Region,维护一个优先列表,记录每个Region的价值,价值是由之前这个区域GC所获空间大小和GC所需时间来决定的(优先列表类似逻辑上的新生代/老年代?)。
                 工作过程类似CMS,第四步清理有区别(根据优先级控制时间),增加remembered set保存对象引用的调用信息;
                 最后一步的清理阶段基于标记-整理和复制算法实现。
                 优:性能好无碎片G1的gc耗时可控:根据预设的gc耗时,优先回收高价值的region.

    2.G1和CMS的对比: 1.G1无内存碎片,CMS有   2.G1的gc时间可控   3.CMS只回收老年代,G1无物理分代

    3.JDK11中的ZGC:专注于减少暂停时间的同时压缩堆。 优:无分代概念、无碎片、时间可控、停顿时间跟堆大小没关系
           a.并发执行的保证机制,就是Colored Pointer(着色指针:将信息存储在指针/引用上) 和 Load Barrier(读屏障)
           b.像G1一样划分Region,但更加灵活:g1的region大小固定,ZGC 可以有2MB,32MB,N× 2MB,大对象放大region

           c. STW标记gcRoots(此操作不标记堆中的对象,所以停顿时间跟堆大小没关系,但是跟线程数量和线程内对象数量有关);  并发标记;  复制到另一个region(老区域可以成为新的复制to区);    Remap修正指针:将指针都指向新地址(上一阶段的Remap和下一阶段的Mark是同时操作的,节省遍历图的开销);
           d. 没有g1的RememberSet和写屏障的开销:划分Region并不是为了增量回收,每次都会对所有Region进行回收,所以也就不需要这个占内存的RememberSet了;又因为它暂时没有分代,所以完全没有Write Barrier。

三、为什么要关注gc?

    知道垃圾是怎么回收的,写代码的时候减少长生命周期对象的使用、减少大对象的创建;监控如果频繁gc则要快速定位原因balabala..

四、线上频繁full gc怎么办?

    查看gc日志判断gc原因;合理调参分配各个区域的大小;增加Survivor区来防止更多的对象进入老年代

五、线上用的:

G1:   堆总内存:12G
        Eden区:0~8G;
        OldGen:1~6G;
        survivor区:平均100多M;
        元空间metaSpace: 平均100多M;

频率:   youngGC:每分钟0~2次,每次100ms左右.(在做youngGC时,OldGen区域也会相应减少,因为G1没有物理分区新生代老年代)      没有fullGC

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值