探究JVM(八)简单易懂的CMS垃圾收集器,一下子就清楚工作流程

引言:CMS是第一款用户线程能够和收集器线程同时工作的垃圾收集器。相较于后来的G1和ZGC垃圾收集器来说,CMS的工作流程简单,易于理解。

工作流程

  1. 初始标记阶段:用户线程暂停,扫描根集合,标记能够直接关联到的对象。
  2. 并发标记阶段:恢复用户线程,并发扫描对象图并标记对象。
  3. 重新标记阶段:用户线程暂停,处理并发标记阶段记录下的引用修改。
  4. 并发清理阶段:恢复用户线程,并发清理可回收对象。

值得一提的是CMS采用增量更新的方法来解决并发标记阶段引用的修改问题,具体的内容可以看我之前关于增量更新和原始快照的博客。

CMS的优缺点

(1)CMS的优点比较直接,CMS的响应速度快,用户体验好,因为大部分时间用户线程可以和GC线程同时工作。
(2)CMS对处理器的资源要求比较高,因为在并发阶段有部分处理器资源要被用来处理并发标记,如果处理器的核心较少时,用户线程和GC线程争抢资源,会导致用户线程的执行速度下降。而且由于用户线程和GC线程同时工作,其中对于线程切换和线程保护的资源浪费也是不可以忽略的开销。这里引用CodeCentric Blog的一篇文章来解释这种开销:

This, however, causes additional costs for thread scheduling: direct costs through context switches and indirect costs because of cache effects. Together with the costs for additional JVM-internal safety measures, this means that each GC comes along with some non-negligible overhead, which adds up with the time taken by the GC threads to perform their actual work.

用户线程和GC线程同时运行时,随着而来的是上下文切换,内存影响,安全措施等一系列除了真正工作以外的开销。
(3)CMS垃圾收集器使用的增量更新无法解决浮动垃圾问题,虽然相较于原始快照浮动垃圾略少,但还是存在。当并发阶段,浮动垃圾过多时,新对象无法分配,这时候就会启动Serial Old来整理老年代空间,暂停时间就会变长。
(4)CMS采用的是标记清除算法,内存空间碎片化,所以有可能出现大对象无法在连续空间分配的情况,这时候就要启动Serial Old垃圾收集器进行Full GC,暂停时间同样会变长。
(5)要注意的是Serial Old GC收集范围是整个堆和方法区,因而是Full GC,这里引用R大的博客原文:

“Serial Old GC的算法是mark-compact(也可以叫做mark-sweep-compact,但要注意它不是“mark-sweep”)。具体算法名是LISP2。它收集的范围是整个GC堆,包括Java heap的young generation和old generation,以及non-Java heap的permanent generation。因而它是full GC。”

总结

(1)关于GC线程额外开销的博客:https://blog.codecentric.de/en/2013/01/useful-jvm-flags-part-6-throughput-collector/
(2)CMS采用增量更新解决并发标记问题,具体内容可以看我之前关于增量更新和原始快照的博客。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值