zgc实现微秒级停顿的关键在于着色指针与读屏障协同消除stw:前者将状态编码于指针高位实现纳秒级判断,后者在每次引用读取时按需修正指针,使标记和引用更新均并发完成。

ZGC能实现微秒级停顿,关键不在于“快”,而在于“几乎不用停”。它把原本必须暂停应用线程才能做的事,拆解成应用线程自己参与、且开销极低的操作。着色指针和读屏障正是这套协同机制的两个核心支点。
着色指针:把状态信息“藏”进地址里
传统GC要把对象是否被标记、是否已转移等状态存在对象头里,每次判断都要访问内存。ZGC反其道而行——直接在64位指针的高几位(比如4位)编码状态信息,比如:
- Marked0 / Marked1:交替使用,标识对象在本轮是否存活
- Remapped:表示该指针已指向转移后的新地址
- Finalizable:标记对象等待执行finalize方法
这样,GC线程或应用线程只需检查指针本身,无需额外读取对象头。一次位运算就能判断状态,耗时在纳秒级。更重要的是,它让“对象是否被移动过”这个信息随指针一起流动,为后续读屏障提供依据。
读屏障:在每次读引用时悄悄“修路”
并发转移过程中,对象可能已被复制到新位置,但旧指针还散落在各处。ZGC不靠STW统一更新所有引用,而是把修正动作下沉到每一次对象访问时:
- 当代码执行
Object obj = fieldA;,JVM自动插入轻量读屏障 - 屏障检查指针是否带 Remapped=0 且已转移 → 若是,查转发表(Forwarding Table)拿到新地址
- 将旧指针当场更新为新地址,并返回新对象引用
这个过程对上层代码完全透明。首次访问稍慢(一次查表+写回),但后续访问就是普通指针读取——因为指针已被“自愈”成新地址。整个操作平均耗时不到100纳秒,远低于微秒级阈值。
两者配合:消除STW的根本逻辑
着色指针提供状态判断能力,读屏障提供即时响应能力,二者结合,绕开了传统GC两大停顿根源:
- 不用STW做全局标记:标记通过读屏障在应用线程访问时“顺手”完成
- 不用STW更新所有引用:引用更新由读屏障在首次访问时“按需”完成
- 转移过程全程并发:GC线程搬数据,应用线程照常跑,仅靠指针颜色和屏障协调一致
最终,ZGC只剩两个极短STW阶段:初始标记根对象(依赖根数量,通常
为什么能稳定在微秒级,而不是随堆变大而增长?
因为停顿时间只跟两件事有关:
- GC Roots的数量(线程栈、静态变量等),这个规模基本固定
- 需要处理的弱/软/虚引用数量,也与活跃业务对象相关,而非总堆大小
堆从16GB扩到2TB,Roots不会变多,读屏障单次开销也不会变长。所以ZGC的停顿是O(1)常数级,不是O(n)线性增长——这才是它区别于G1、CMS的本质。










