CMS将可达性分析分解成两个阶段
a.仅扫描与根节点直接关联的对象;
b.继续向下扫描完所有对象。因此,标记阶段也被拆分成两个阶段,即初始标记和并发标记。
CMS完整的收集过程如下:
- 初始标记(init-mark):仅扫描与根节点直接关联的对象并标记,这个阶段必须STW, 由于跟节点数量有限,所以这个过程非常短暂。
- 并发标记(concurrent-marking):与用户线程并发标记。这个阶段在初始标记的基础上继续向下追溯标记。在并发标记阶段,用户线程和标记线程并发执行,所以用户不会感受到停顿。
- 并发预清理(concurrent-precleaning):与用户线程并发进行。在并发标记阶段一些对象的引用已经发生了变化,precleaning会发现这些引用关系的改变,并将存活的对象标记。举个例子:如果线程A有一个指向对象X的引用,并将该引用传递给了线程B,CMS需要记录下线程B持有了对象X,即使线程A已经不存在了。precleaning是为了减少下一阶段“重新标记”的工作量,因为remark阶段会STW。
- 重新标记(remark): remark阶段会STW。如果应用正在并发运行且在不断地改变对象引用,CMS则不能准确地确定某个对象是否存活。所以CMS会在remark阶段STW,从而获取所有引用关系的改变。
- 并发清理(concurrent-sweeping):清理垃圾对象,这个阶段GC线程和用户线程并发执行。
- 并发重置(concurrent-reset):重置CMS收集器的数据结构,做好下一次执行GC任务的准备工作。