g1与zgc均通过并发标记-清理实现低延迟:g1采用分代region布局与remembered set,stw仅限初始/最终标记;zgc基于染色指针、读屏障与内存多重映射,stw压缩至亚毫秒级。

JVM 垃圾回收器实现并发标记和清理,核心在于把原本必须全程 Stop-The-World(STW)的标记-清除过程拆解为多个阶段,只在关键节点暂停用户线程,其余大部分工作与应用线程(Mutator)并行执行。主流代表是 CMS 和 G1(部分阶段),ZGC 和 Shenandoah 则进一步压缩 STW 到毫秒级。
并发标记的关键:三色抽象 + 增量更新
并发标记不是“完全不暂停”,而是用三色标记法(White-未处理、Gray-已标记但引用未扫描、Black-已标记且引用已扫描)管理对象状态,并配合写屏障(Write Barrier)捕获并发修改:
- 初始标记(Initial Mark):STW,仅标记 GC Roots 直接关联的对象,耗时极短
- 并发标记(Concurrent Mark):与用户线程同时运行,遍历对象图,将 Gray 对象转为 Black
- 重新标记(Remark):STW,修正并发标记期间因引用变更导致的漏标(如新创建对象、引用被修改),是 CMS 最耗时的 STW 阶段
- 写屏障作用:当用户线程修改引用(如 a.field = b)时,触发屏障逻辑,把被修改的对象或原引用对象加入待扫描队列,确保不会漏标
并发清理的前提:不移动对象 + 空闲列表管理
清理阶段能并发,是因为它不涉及对象移动,只做逻辑回收:
- 清除操作本质是遍历堆,把未被标记(White)的对象所占空间归入空闲列表,供后续分配复用
- CMS 使用标记-清除算法,清除阶段可与用户线程并发;但不整理内存,易产生碎片
- G1 的并发清理(Concurrent Cleanup)则基于 Remembered Set 和 Region 粒度,识别出完全可回收的 Region 后,并发地将其释放并加入可用 Region 池
避免对象丢失:增量更新 vs 原始快照
并发环境下,用户线程可能在 GC 线程扫描途中修改引用链,造成“对象丢失”(本该存活却被清掉)。两种主流解决方案:
- 增量更新(Incremental Update):CMS 采用。当引用被改为指向一个未标记对象时,将该对象重新标记为 Gray,确保后续会被扫描到
- 原始快照(Snapshot At The Beginning, SATB):G1/ZGC 采用。在标记开始前记录所有存活对象快照,之后新增或断开的引用不影响本次标记结果,只需处理“变黑”的对象
实际配置中的体现
启用并发行为需显式指定收集器及调优参数:
- CMS:-XX:+UseConcMarkSweepGC 开启;-XX:CMSInitiatingOccupancyFraction=75 控制老年代触发阈值
- G1:-XX:+UseG1GC 默认启用并发标记;-XX:MaxGCPauseMillis=200 设定目标停顿时间,驱动并发回收节奏
- ZGC:-XX:+UseZGC 即启用全并发标记与清理,STW 仅限于初始标记与最终重映射,通常











