Pause Mark Start到Pause Relocate Start的时间差反映ZGC周期中并发标记等后台工作耗时,是判断其是否跟得上应用分配节奏的核心窗口,包含Concurrent Mark、Piggyback Remap、Reference Processing和Relocation Set Selection等阶段。

Pause Mark Start 到 Pause Relocate Start 之间的时间差,不是 GC 停顿本身,而是**一次完整 ZGC 周期中两个关键 STW 阶段的间隔**。它反映的是并发标记、并发重定位准备等后台工作实际耗时,是判断 ZGC 是否“跟得上”应用分配节奏的核心窗口。
这个时间差到底在表达什么
它本质上是 ZGC 从“开始标记”到“准备重定位”的调度延迟,包含以下并发阶段:
- Concurrent Mark:遍历对象图、标记存活对象(受堆活跃度、引用深度影响)
- Piggyback Remap:复用当前周期,完成上一轮未更新完的指针(读屏障未覆盖的遗留引用)
- Reference Processing:处理软/弱/虚引用(尤其当大量 WeakHashMap 或 Cleaner 对象存在时会拖慢)
- Relocation Set Selection:评估哪些内存页(ZPage)最值得回收和压缩(依赖空闲页数量与碎片程度)
怎么看才算“异常跳动”
健康值不是固定数字,而应结合频率与趋势看波动。重点关注三类信号:
- 单次突增>50ms:大概率出现 Reference 处理阻塞或 Safepoint 进入延迟(比如 JNI 调用未及时返回)
- 持续缓慢爬升(如从 80ms → 120ms → 160ms):提示堆内对象图变复杂(例如缓存膨胀、循环引用增多),或并发线程数不足(-XX:ParallelGCThreads 设置过低)
- 周期性尖峰(如每 3–5 秒规律跳高):可能与定时任务、批量日志刷写、或外部 RPC 批量响应引发的瞬时分配爆发有关
实操:三步定位跳动根源
仅靠时间差数字无法下结论,必须联动日志上下文验证:
- 查紧邻的 Safepoint 日志:启用
-XX:+PrintSafepointStats后,若发现 “Time to safepoint” 显著高于平均(如>10ms),说明线程被阻塞,Pause Mark Start 实际被推迟 - 比对 GC Roots 扫描耗时:日志中若有类似
[GC(0) Concurrent Mark (roots) 42.3ms]记录,该值接近时间差,说明标记根集合本身成为瓶颈(常见于线程栈深、JNI 全局句柄多) - 检查 Reference 统计行:搜索
Reference Processing关键字,若出现Soft: 12345, Weak: 6789, Final: 234且数值远超平时,就是弱引用清理拖慢了 Relocate Start 的触发
辅助验证:用时间差反推系统压力
这个间隔可当作“ZGC 呼吸节奏”的节拍器:
- 稳定在 60–90ms:说明并发能力匹配当前负载,标记与准备节奏顺畅
- 压缩至<40ms:可能意味着堆使用率偏低,或 ZGC 频繁启动(检查
Heap Usage是否长期<30%) - 拉长至>200ms 且伴随
Allocation Stall日志:ZGC 已跟不上分配速度,旧对象来不及回收,需扩容或优化对象生命周期

















