商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > ZGC回收循环中的标记阶段逻辑详解

ZGC回收循环中的标记阶段逻辑详解

  发布于2026-07-10 阅读(0)

扫一扫,手机访问

ZGC的标记阶段,是整个回收循环中实现低停顿的关键起点。它并不追求一次性扫完所有对象,而是通过分步、并发、带屏障保障的方式,把原本必须串行完成的“识别存活对象”这个任务,拆解成多个可并行、可中断、且与应用线程协同工作的子过程。下面,我们不妨拆开来看,ZGC到底是怎么做到这一点的。

ZGC回收循环中的标记阶段逻辑详解

初始标记:STW,但极短到几乎无感

这是唯一需要全局暂停的标记步骤,但ZGC只做最轻量的工作——从GC Roots(比如栈帧中的局部变量、静态字段、JNI引用等)出发,标记直接可达的对象,然后把它们压入标记栈。关键点在于,它只处理“一步可达”的对象,不递归遍历引用链。所以,这轮STW的耗时通常只有0.1ms级别,对响应时间几乎无感。

并发标记:核心阶段,完全并发

初始标记一结束,GC线程就立刻启动并发标记——以初始标记压入栈的对象为起点,采用深度优先或工作窃取方式遍历整个对象图。这个阶段,应用线程还在持续运行,对象引用关系随时可能变化,漏标风险随之而来。ZGC通过以下机制来应对:

  • 读屏障全程介入:每当应用线程读取一个对象引用时,ZGC的读屏障会检查该引用是否指向已标记但尚未完成遍历的对象。如果发现未完成标记,会触发“预标记”,将其加入待处理队列,确保不被遗漏。
  • 三色标记法 + 增量更新:ZGC使用黑色(已标记且引用全扫描)、灰色(已入栈但引用未扫完)、白色(未访问)三色模型。当应用线程修改引用(比如将某个白对象赋给黑对象字段)时,写屏障会记录这个变更,后续再标记阶段统一补漏。

这套组合拳,让并发标记既高效又可靠。

再标记:STW,仍极短

并发标记结束后,进入再标记阶段,主要做两件事:

  • 快速扫描GC Roots中新增的引用(比如刚压栈的线程局部变量),确保根集合处于最新状态;
  • 处理并发期间因引用变更产生的少量“浮动垃圾”或“漏标对象”,通过SATB日志回溯修正。

这个阶段不重新遍历整个堆,只处理增量日志和根集快照,STW时间通常低于0.2ms。可以说,ZGC把暂停时间压到了极致。

非强引用与非强根的并发处理

ZGC将软引用、弱引用、虚引用以及finalize队列等“非强可达”对象的处理也纳入标记流程,但不会放在STW中执行。它在并发标记后期启动专用线程,异步扫描这些结构,并配合读/写屏障保证语义正确性。举个例子,对重写了finalize()的对象,ZGC会额外打标并延迟转移,直到其finalize方法执行完毕。这种设计,既保证了语义的完整性,又避免了不必要的停顿。

本文转载于:https://www.php.cn/faq/2799326.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注