在 Java 中,CMS(Concurrent Mark-Sweep)和 G1(Garbage-First)垃圾收集器都支持并发垃圾回收,即在应用程序运行的同时执行部分垃圾回收工作。为了维持并发的正确性,它们需要解决以下问题:
- 对象图的动态变化:在并发标记过程中,应用程序线程可能会创建新对象、修改对象引用或使对象不可达。
- 漏标(Missing Objects):在并发标记过程中,某些存活对象可能被错误地标记为垃圾。
- 多标(Floating Garbage):在并发标记过程中,某些垃圾对象可能被错误地标记为存活。
为了应对这些问题,CMS 和 G1 都采用了多种机制来维持并发的正确性。
CMS 如何维持并发的正确性
CMS 是一种以低延迟为目标的垃圾收集器,主要针对老年代的并发标记清除。它通过以下机制维持并发的正确性:
1. 初始标记(Initial Mark)
- 初始标记是 STW(Stop-The-World)的,它会暂停所有应用线程,标记从 GC Roots 直接可达的对象。
- 这一步的目的是快速确定一部分存活对象,作为并发标记的起点。
2. 并发标记(Concurrent Mark)
- 在并发标记阶段,CMS 会遍历对象图,标记所有可达对象。
- 由于应用线程同时运行,对象图可能会发生变化。为了解决这个问题,CMS 使用了写屏障(Write Barrier):
- 当应用线程修改对象引用时,写屏障会记录这些修改,确保并发标记不会漏标新创建的对象或新引用的对象。
3. 重新标记(Remark)
- 重新标记是 STW 的,它会暂停所有应用线程,处理在并发标记期间遗漏的对象。
- CMS 使用**增量更新(Incremental Update)**算法:
- 在并发标记期间,如果应用线程修改了对象引用,写屏障会将这些修改记录下来。
- 在重新标记阶段,CMS 会重新扫描这些被修改的对象,确保所有存活对象都被正确标记。
4. 并发清除(Concurrent Sweep)
- 在并发清除阶段,CMS 会清理未被标记的对象(即垃圾对象)。
- 由于清除是并发的,可能会产生浮动垃圾(Floating Garbage),即一些已经被标记为存活的对象实际上已经变成垃圾。这些浮动垃圾会在下一次垃圾回收时被清理。
G1 如何维持并发的正确性
G1 是一种面向全堆的垃圾收集器,它将堆划分为多个区域(Region),并支持并发标记和混合回收。G1 通过以下机制维持并发的正确性:
1. 初始标记(Initial Mark)
- 初始标记是 STW 的,它会暂停所有应用线程,标记从 GC Roots 直接可达的对象。
- 与 CMS 类似,这一步的目的是快速确定一部分存活对象,作为并发标记的起点。
2. 并发标记(Concurrent Mark)
- 在并发标记阶段,G1 会遍历对象图,标记所有可达对象。
- G1 使用了**SATB(Snapshot-At-The-Beginning)**算法来维持并发的正确性:
- SATB 假设在并发标记开始时,所有存活对象都已经被快照记录下来。
- 当应用线程修改对象引用时,写屏障会记录被删除的引用(即从存活对象变为垃圾的对象),确保这些对象不会被错误地回收。
3. 最终标记(Final Mark)
- 最终标记是 STW 的,它会暂停所有应用线程,处理在并发标记期间遗漏的对象。
- G1 会重新扫描被修改的对象,并处理 SATB 队列中的记录,确保所有存活对象都被正确标记。
4. 清理(Cleanup)
- 在清理阶段,G1 会统计每个区域的存活对象,并选择回收价值最高的区域进行回收。
- 清理阶段是部分并发的,可能会产生浮动垃圾,这些浮动垃圾会在下一次垃圾回收时被清理。
CMS 和 G1 维持并发正确性的对比
机制 | CMS | G1 |
---|---|---|
初始标记 | STW,标记 GC Roots 直接可达的对象 | STW,标记 GC Roots 直接可达的对象 |
并发标记 | 使用写屏障记录对象引用变化 | 使用 SATB 算法记录对象引用变化 |
重新标记/最终标记 | STW,使用增量更新算法处理遗漏对象 | STW,处理 SATB 队列中的记录 |
并发清除/清理 | 并发清除,可能产生浮动垃圾 | 部分并发清理,可能产生浮动垃圾 |
主要算法 | 增量更新(Incremental Update) | SATB(Snapshot-At-The-Beginning) |
总结
- CMS 使用增量更新算法和写屏障来维持并发的正确性,确保在并发标记期间不会漏标对象。
- G1 使用SATB算法和写屏障来维持并发的正确性,确保在并发标记期间不会漏标对象。
- 两者都通过 STW 的重新标记/最终标记阶段来处理并发标记期间遗漏的对象。
- 两者都可能产生浮动垃圾,但这些浮动垃圾会在下一次垃圾回收时被清理。
通过以上机制,CMS 和 G1 能够在并发垃圾回收的同时,保证对象图的正确性,从而在低延迟和高吞吐量之间取得平衡。
THE END
暂无评论内容