ZGC标记阶段通过初始标记(极短STW)、并发标记(读屏障+三色标记)、再标记(极短STW)及非强引用并发处理实现低停顿;初始标记仅标记GC Roots一步可达对象,耗时约0.1ms;并发标记由GC线程与应用线程并行执行,借助读屏障和SATB变体避免漏标;再标记仅扫描新增根引用和SATB日志,STW低于0.2ms;软/弱/虚引用及finalize对象由专用线程异步处理,保障语义正确。
ZGC的标记阶段是整个回收循环中实现低停顿的关键起点,它不追求一次性扫完所有对象,而是通过分步、并发、带屏障保障的方式,把原本必须串行完成的“识别存活对象”任务拆解为多个可并行、可中断、且与应用线程协同工作的子过程。
这是唯一需要全局暂停的标记步骤,只做最轻量的工作:从 GC Roots(如栈帧中的局部变量、静态字段、JNI 引用等)出发,标记直接可达的对象,并将它们压入标记栈。由于只处理“一步可达”的对象,不递归遍历引用链,因此耗时通常在 0.1ms 级别,对响应时间几乎无感。
初始标记完成后,GC 线程立即启动并发标记——以初始标记压入栈的对象为起点,用深度优先或工作窃取方式遍历整个对象图。此阶段应用线程持续运行,对象引用关系可能随时变化,存在漏标风险。ZGC 通过以下机制应对:
并发标记结束后,进入再标记阶段,主要做两件事:
该阶段不重新遍历整个堆,仅处理增量日志和根集快照,STW 时间通常低于 0.2ms。
ZGC 将软引用、弱引用、虚引用以及 finalize 队列等“非强可达”对象的处理也纳入标记流程,但不放在 STW 中执行。它在并发标记后期启动专用线程异步扫描这些结构,并配合读/写屏障保证语义正确性。例如,对重写了 finalize() 的对象,ZGC 会额外打标并延迟转移,直到其 finalize 方法执行完毕。