JVM六种常见的垃圾回收器-重点含CMS过程详解

一、jdk 1.8 及其之前的分代模型: 

 堆内存结构必须熟悉:(垃圾回收,性能调优常用)

过程简单分析:

①年轻代和老年代在堆内存中的占比默认 1 :2
②年轻代又分为两个区,伊甸园区(Eden)和幸存区(S0和S1),分别占8:1:1
③新对象会先放到伊甸园区,当伊甸园区被对象占满时,会有执行引擎开启一个GC垃圾收集线程(利用根可达性分析算法判断是否是非垃圾对象),没有被引用的对象就是需要被回收的,然后非垃圾对象就会被移动到幸存区S0,并且寿命+1(说明经历了一次垃圾回收)。
继续重复刚刚,新对象又会放到伊甸园区,当伊甸园区再次被对象占满时,又会有执行引擎开启一 个GC垃圾收集线程,将 非垃圾对象移动到S1,同时 年龄+1,S0中的对象,如果是垃圾对象会直接被 回收,若不是垃圾对象,会被放到S1,寿命再+1,(移动用到的是标记复制算法)。
④当寿命到达15时,(经历了15次Minor GC),就将该对象移动到老年代中去。
⑤当老年代也被堆满时,就会产生老年代 GC,即Full GC。(老年代满了清理时,大部分垃圾回收器用到的是标记整理算法)。

二、常见的垃圾回收器:

(左边分代模型,用于jdk1.8及之前; 右边的分区模型,1.9及之后)

(1)串行垃圾回收器(Serial  +  SerialOld): 
        单线程的工作方式(会暂停所有用户线程)

 (2)并行的垃圾回收器[高吞吐量](Parallel Scavenge + Paraller Old) 并行的垃圾回收器[PS+PO---jdk 8默认的垃圾回收器]

 综上四种垃圾回收器 Serial SerialOld PS PO都会导致一个现象: 用户线程的阻塞!
        用户线程暂停 <==>  STW 
    比如:垃圾收集的时候,用户在访问的时候会直接卡主...没有线程来给用户来用.

 ☆☆☆(3)并发的垃圾回收器[高响应速度] ParNew(新生代) + CMS(老年代)  ☆☆☆ 

   CMS:Concurrent Mark Sweep并发标记清除
   ParNew是在Parallel Scavenge基础上做的改良,配合CMS使用,但大致没什么变化!

 

 别的老年代的Serial Old和PO都采取"标记整理",但是CMS采取"标记清除"!!

 (1) 初始标记: 
        找到所有GC Root根对象,短暂STW.简单标记一下
(2) 并发标记: 
        - 根据GC Roots的直接关联对象开始进行对象图的遍历.且该阶段不会暂停用户线程,允许gc线程和用户线程并发执行
        - 通过写屏障技术记录下发生错标问题的黑色对象..并放入队列中
(3) 重新标记:
        会通过"增量更新"的解决方案解决上一阶段产生的错标问题.
(4) 并发清理:
        清理掉确定会被回收的垃圾

  • 浮动垃圾:

    在gc线程与用户线程并发进行的阶段,gc线程在"并发标记"阶段,在搜集垃圾,但是在此时阶        段用户线程的操作导致的原先通过"初始标记"的"非垃圾对象"变为"垃圾对象",而此时gc收集

    器无法检测到,则该垃圾对象被称为"浮动垃圾".

  • 错标:

    在"初始标记"的垃圾对象,在"并发标记"阶段因为用户线程的影响变为了非垃圾对象.
    此时称为错标!

注意:
    (1)浮动垃圾无所谓,在下次垃圾回收的时候会把该垃圾回收.不会有什么特别的影响.
       但是"错标"的线程,会导致要使用的对象被回收了.就会造成影响.
    所以接下来的"重新标记"阶段就是解决"错标"的问题!!!
    (2)"初始标记"和"重新标记"都会产生极其短暂的STW.但可忽略不计!
    (3)当CMS并发处理失败的时候,会立马切换Serial Old来清理!(替补!!)
    (4) CMS解决错标问题采用了"增量更新"的方式.对于那些黑色增加对白色的引用,会通过写屏障的
        技术记录下来,再重新标记阶段进行以黑色为根重新扫描一遍,来解决错标的问题!

CMS缺点,不好的地方:
    (1)内存碎片
    (2)浮动垃圾
    (3)如果CMS运行期间预留的空间不足以让用户线程分配一个对象,则并发失败.
        并发失败时会先冻结用户线程,然后启动Serial Old来收集老年代.

 总结:
    (1)CMS解决了什么样的问题??
        - 解决了STW时间过长的问题,使垃圾回收时用户的等待时间变短
    
    (2)jdk 1.8之前都是分代垃圾回收,所以就是这么分代垃圾回收器.
        jdk 1.8之后都是分区垃圾回收.所以G1 ZGC等就没有老年代 新生代这种概念了!

 三、CMS并发失败的问题?

在第四阶段并发清理阶段CMS不会STW,依旧gc线程和用户线程一起运行.并不能像别的老年代垃圾回收器那样等待垃圾快满了再回收, 而是在并发清理阶段预留一定的空间给程序运行.当无法为程序分配足够的空间时,则并发失败,冻结用户线程,然后换为Serial Old来清理.

别的垃圾回收器: 我gc线程垃圾回收之后你用户线程再使用,

而CMS就是在并发清理(回收阶段)也会让你用户线程继续跑.所以CMS就需要在垃圾回收阶段预留给用户线程足够的空间来使用,一旦用户线程要使用的空间大于预留的空间,则并发失败!
 

 四、CMS最严重的两个问题?以及优化??

- 标记清除造成的内存碎片问题

晋升失败时候,新生代发生Minnor GC,幸存区中放不下要存活的对象,只能触发对象担保机制,
晋升老年代,由于内存碎片过多,导致大对象没法被放下!

解决: 让CMS进行一定次数的Full GC的后进行一次标记整理的算法,控制住内存碎片的数量.
       可以通过参数配置...        

- 并发失败时的Serial Old

解决: 降低触发CMS GC的阈值...让其预留够足够的空间!
 

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值