zgc通过染色指针与读屏障实现亚毫秒级停顿:将标记/重映射状态编码至64位指针高位,读屏障在每次对象访问时轻量检查并自动修正引用,使标记、转移、重映射全程并发,仅需极短stw校验。

ZGC(Z Garbage Collector)在 Java 中通过指针着色(Pointer Coloring)和读屏障(Load Barrier)实现几乎全并发的垃圾回收,核心目标是让 GC 线程与应用线程大部分时间并行执行,从而把停顿时间控制在 10ms 以内,且不随堆大小显著增长。
指针着色:在引用中隐式编码元数据
ZGC 将对象引用(即指针)的低几位(通常是低 4 位)用于标记状态,而不是单独维护额外的元数据结构。这些位不参与地址寻址(因为内存按 2⁴=16 字节对齐,低 4 位恒为 0),因此可安全复用。
ZGC 定义了四种颜色位组合,对应不同阶段的对象状态:
- 00:Remapped(已重映射)——对象已完成迁移,引用指向新地址,是最稳定的状态;
- 01:Marked0 / Marked1(标记中)——表示该对象已被标记为存活,具体用哪一位区分两次标记周期(避免漏标);
- 10:Remap(重映射中)——对象已复制到新位置,但部分引用尚未更新;
- 11:Invalid(无效)——该引用当前不可用(如指向已释放区域),GC 会拒绝访问或触发处理。
这种设计省去了传统 GC 中的“标记位数组”或“卡表”,降低了内存开销和缓存压力,也使标记、重映射等操作能直接通过指针本身判断状态。
读屏障:拦截每次对象引用访问
ZGC 在每次从堆中读取对象引用时(即执行 load 指令,如 a.field 或 array[i]),插入一段轻量级检查逻辑——这就是读屏障。它不是 JVM 解释执行的 Java 代码,而是由 JIT 编译器在生成机器码时自动内联的汇编片段。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
读屏障的主要任务是:检查被读取的引用是否处于非 Remapped 状态;若不是,则根据颜色位做相应处理:
- 遇到 Marked 引用:确保该对象在本次 GC 周期中被正确标记(可能触发并发标记);
- 遇到 Remap 引用:将该引用原子地更新为指向新地址(即“自愈”),并清除颜色位,变成 Remapped;
- 遇到 Invalid 引用:触发 GC 暂停极短时间(通常子毫秒级)进行修复或等待,但极少发生。
关键点在于:所有用户线程的读操作都经过此屏障,因此即使 GC 正在移动对象,应用线程也能安全、透明地获得最新地址,无需 Stop-The-World 来修正全部引用。
并发三阶段如何协同工作
ZGC 的并发性体现在标记、转移(relocation)、重映射三个主阶段均可与用户线程同时运行:
- 并发标记:GC 线程遍历对象图打标,读屏障保证新访问到的未标对象能被即时补标(解决并发修改导致的漏标);
- 并发转移:GC 线程将存活对象复制到新内存页;旧对象暂不立即清理,引用仍可通过读屏障跳转到新位置;
- 并发重映射:实际并不集中更新所有引用,而是靠读屏障“懒更新”——每次读到旧引用就当场修正,逐步完成重映射。
整个过程没有全局暂停来扫描根集合或更新引用表,只有极短的初始标记(STW 扫描根)和最终重映射确认(STW 校验),总停顿时间与活跃对象数无关,只取决于根数量(通常几百微秒)。
为什么不需要写屏障
ZGC 不使用写屏障(Store Barrier),因为它不要求在每次字段赋值时做额外动作。这得益于其“转移即重映射”的设计:对象一旦被转移,旧地址仍保留(带颜色位),后续读操作通过读屏障自动跳转,而写操作直接作用于新地址(因为写入前必然先读引用,已触发重映射)。这大幅降低了写操作的性能开销,尤其适合高吞吐写密集型场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










