JVM 面试必问的 CMS,你懂了吗?

本文深入探讨了CMS垃圾收集器,包括卡表、mod-union table的原理,CMS的7个步骤过程,以及CMS面临的问题和调优策略。CMS使用写屏障优化并发标记,但在并发阶段可能导致空间碎片、Full GC等问题,需要通过调整参数进行优化。
摘要由CSDN通过智能技术生成

前言

虽然 CMS 已经是很古老的垃圾回收器了,大家现在动不动就G1、ZGC啥的,但是据我所了解,还是有很多公司的生产环境主要使用的 CMS,包括我自己呆过的几家大厂也是。

因此在 JVM 面试中,CMS 也是问的最多的,包括我自己现在面试别人时,问到 JVM 这一块,我也喜欢从CMS开始,逐渐深入。

不多废话,今天我们就来盘他。

正文

1、什么是卡表(card table)?

试想一下,在进行 YGC 时,如何判断是否存在老年代到新生代的引用?

一个简单的办法是扫描整个老年代,但是这个代价太大了,因此 JVM 引入了卡表来解决这个问题。

卡表又称为卡片标记(card marking),由 Paul R. Wilson 和 Thomas G. Moher 在1989年发表的论文里提出。

其原理为,在逻辑上将老年代空间分割为若干个固定大小的连续区域,分割出来的每一个个区域就称为卡片(card)。另外,为每个卡片准备一个与其对应的标记位,最简单的实现方案是由字节数组实现,以卡的编号作为索引。每个卡的大小通常介于128~512字节之间,一般使用2的幂字节大小,例如HotSpot使用512字节。

当卡片内部发生引用变化时(指针写操作),写屏障会将该卡在卡表中对应的字节标记为脏(dirty)。

有了卡表后,在 YGC 时,只需将卡表中被标记为 dirty 的 card 也作为扫描范围,就可以保障不扫描整个老年代也不会有遗漏了。
 

2、什么是 mod-union table?

通过上面对 card table 的介绍,我们知道 card table 会记录下老年代所有发生过引用变化对象所在的 card,而 CMS 在并发标记等阶段,也需要记录下老年代发生引用变化的对象以便后续重新扫描,是否可以直接复用 card table?

答案是不行的,这是因为每次 YGC 过程中都涉及重置和重新扫描 card table,这样是满足了 YGC 的需求,但却破坏了CMS的需求,CMS 需要的信息可能被 YGC 给重置掉了。为了避免丢失信息,于是在 card table 之外另外加了一个 Bitmap 叫做 mod-union table。

在 CMS 并发标记正在运行的过程中,每当发生一次 YGC,当 YGC 要重置 card table 里的某个记录时,就会更新 mod-union table 对应的 bit,相当于将 card table 里的信息转移到了 mod-union table 里。

这样,最后到 Final remark 的时候,card table 加 mod-union table 就足以记录在并发标记过程中老年代发生的所有引用变化了。

3、CMS 垃圾收集的过程?

CMS 垃圾收集的过程网上通常有两个版本,4个步骤的和7个步骤的,两个版本其实都是对的。

4个步骤应该主要是跟随周志明的说法,而 CMS 的相关论文其实也是按4个步骤介绍。

7个步骤则应该更多是从 CMS 的日志得出的说法,而7个步骤里其实也包含了上述的4个步骤,可以理解为7个步骤是更细的说法。

个人而言,我会更喜欢7个步骤的说法,因此这边介绍下7个步骤的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值