zgc停顿时间与堆大小无关,因其将标记、转移等重负载操作全部并发执行,仅保留初始标记和最终重映射两个stw阶段,二者均只依赖gc roots数量且总时长通常低于1ms。

ZGC能做到停顿时间与堆大小无关,核心在于它把几乎所有耗时操作都搬到了并发阶段执行,只保留极少数、固定开销的“瞬间”STW(Stop-The-World)步骤。
关键设计:染色指针 + 多视图内存映射
ZGC不依赖传统的对象标记位存于对象头,而是把标记信息直接编码进指针本身(64位指针中预留几位),称为“染色指针”(Colored Pointer)。同时,ZGC为每个对象维护三个虚拟地址视图:Marked0、Marked1、Remapped,它们指向同一块物理内存。这种设计让标记、转移、重定位等动作无需修改对象内容或遍历整个堆,只需原子更新指针值即可完成,彻底摆脱了堆规模对停顿的影响。
真正只和GC Roots数量挂钩的STW阶段
ZGC全程仅有两个极短STW环节:
- 初始标记(Initial Mark):仅扫描GC Roots(如线程栈、静态变量、JNI引用等),停顿时间取决于Roots数量,而非堆大小;
- 最终重映射(Final Remap):修正少量在并发转移过程中仍被访问的指针,同样只涉及活跃引用路径,与堆总量无关。
这两个阶段加起来通常控制在1ms以内,且不会随堆从几百MB涨到16TB而变长。
所有重负载操作全部并发执行
传统收集器(如G1)的标记、转移、清理等步骤会阶段性阻塞应用线程;ZGC则将这些工作完全交给后台线程并发处理:
- 并发标记阶段:应用线程照常运行,后台线程遍历对象图并设置染色指针;
- 并发转移阶段:后台线程把存活对象复制到新位置,并原子更新对应指针;
- 并发重定位阶段:逐步把旧指针批量切换到新地址视图,避免一次性刷新全堆。
这些操作虽然总耗时可能随堆增大而增加,但它们不造成STW,因此不影响停顿时间。
无分代假设,简化逻辑路径
ZGC默认不分代(JDK21起支持可选分代ZGC,但基础ZGC仍保持无代设计),不维护Eden/Survivor/老年代边界,也不做跨代引用卡表扫描。这省去了大量与对象年龄、记忆集(Remembered Set)、跨代引用处理相关的复杂同步和扫描逻辑,进一步压缩了STW环节的不确定性与可变开销。











