zgc通过将对象状态编码进64位指针高4位实现并发清理,无需stw遍历对象头;marked0/marked1支持三色标记,remapped标识重定位,配合读屏障按需修正引用,停顿仅限初始标记和最终重映射。

ZGC 通过把对象状态“塞进指针本身”,绕开了传统 GC 对象头读写和全局同步的瓶颈,从而实现真正意义上的并发清理。它不依赖暂停线程来统一刷新状态,而是让每个指针自带“身份标签”,配合读屏障按需响应,整个过程对应用线程几乎无感。
颜色指针怎么存状态?
ZGC 在 64 位指针中预留若干高位(JDK 15+ 常用 4 位)作为元数据区,不改变实际地址有效位的前提下,编码对象生命周期阶段。典型布局包括:
- Marked0 / Marked1:标记阶段用的双色位,支持三色标记(白→灰→黑)的并发迭代,避免漏标
- Remapped:表示该指针已指向重定位后的新地址,用于区分“旧引用”和“新位置”
- Finalizable(部分版本):标识需执行 finalize 的对象,隔离处理逻辑
这些位不是额外内存开销,而是直接复用指针空闲位——地址空间足够大(如支持 4TB 堆),高位冗余可安全借用。
颜色如何驱动并发清理?
颜色不是静态标签,而是一套状态机,随 GC 阶段自动流转:
- 初始时所有指针为 Remapped(视图干净,指向原始地址)
- 进入标记阶段,新分配对象或被访问的存活对象指针转为 Marked0;标记线程与应用线程并发更新,无需锁
- 标记完成进入转移(整理)阶段,ZGC 并行复制存活对象到新页,并将对应指针的 Remapped 位置 1,同时保留旧地址映射(靠虚拟内存多重映射实现)
- 读屏障检测到指针是 Marked0/Marked1 但尚未 Remapped,就触发“重定向”:原子更新指针指向新地址,并返回正确值
整个过程没有全局遍历、不修改对象头、不阻塞写操作——清理动作分散在每次读取中完成。
为什么能避免 STW?
关键在于“状态下沉 + 按需修正”:
- 传统 GC 要 STW 是因为必须冻结所有线程,统一扫描对象图并修正引用;ZGC 把这个修正动作拆解到每一次
load操作里,由读屏障即时完成 - 对象移动时,物理内存复制由 GC 线程异步进行,应用线程继续运行;只要读屏障能识别出“该指针还没重映射”,就帮它跳转一次,后续再读就是稳定的新地址
- 唯一需要 STW 的环节极短:仅初始标记(找根集)和最终重映射(批量刷新剩余旧引用),通常控制在
它本质上把“集中式修正”变成了“分布式懒更新”,代价是每次读多一次位判断和可能的一次指针修正——但现代 CPU 流水线对此优化极好,实测开销可控。











