ZGC 的执行日志可以通过 JVM 参数配置输出,包含垃圾回收的阶段、时间、堆内存变化等关键信息,是分析 ZGC 运行状态、调优性能的重要依据。以下是 ZGC 日志的配置方式、关键内容解读及示例分析:
一、启用 ZGC 日志的核心参数
通过 -Xlog
系列参数控制 ZGC 日志的输出(JDK 9+ 统一日志框架),常用配置如下:
参数示例 | 说明 |
---|---|
-XX:+ZPrintGC |
基础日志:输出 GC 触发、阶段、耗时等关键信息(简洁版) |
-XX:+ZPrintGCDetails |
详细日志:包含堆区域变化、指针颜色调整、线程参与等细节 |
-Xlog:gc*:file=zgc.log:time,level,tags |
输出到文件:将 GC 相关日志(gc* )写入 zgc.log ,包含时间、级别、标签 |
-Xlog:gc=debug:file=zgc-debug.log |
调试级日志:输出更细粒度的阶段执行细节(适合深度分析) |
二、ZGC 日志的核心内容解读
ZGC 的日志按 回收周期 划分,每个周期包含多个阶段,关键信息如下:
1. 日志开头:GC 触发原因与堆状态
log
[0.834s][info][gc] ZGC(0) Initial Mark Start (size 256M)
ZGC(0)
:第 0 次 ZGC 回收(从 0 开始计数)。Initial Mark Start
:开始初始标记阶段。size 256M
:当前堆大小为 256MB。- 触发原因可能包括:
Allocation Rate
(内存分配速率过高)、Heap Exhausted
(堆即将耗尽)等。
2. 核心阶段日志(按执行顺序)
(1)初始标记(Initial Mark)------ STW 阶段
log
[0.835s][info][gc] ZGC(0) Initial Mark End (1.2ms)
End (1.2ms)
:初始标记结束,耗时 1.2ms(STW 时间,极短)。- 作用:标记根对象(线程栈、静态变量等),为后续并发标记奠定基础。
(2)并发标记(Concurrent Mark)
log
[0.835s][info][gc] ZGC(0) Concurrent Mark Start
[0.842s][info][gc] ZGC(0) Concurrent Mark End (7.3ms)
- 全程并发执行(与应用线程同时运行),耗时 7.3ms。
- 作用:遍历对象图,标记所有存活对象(通过着色指针标记状态)。
(3)最终标记(Final Mark)------ STW 阶段
log
[0.842s][info][gc] ZGC(0) Final Mark Start
[0.842s][info][gc] ZGC(0) Final Mark End (0.3ms)
- STW 时间 0.3ms,处理并发标记中遗漏的对象(如并发标记期间新产生的根对象)。
(4)并发预备转移(Concurrent Prepare for Relocation)
log
[0.842s][info][gc] ZGC(0) Concurrent Prepare for Relocation Start
[0.843s][info][gc] ZGC(0) Concurrent Prepare for Relocation End (0.9ms)
- 并发执行,准备需要转移的 Region(筛选出内存碎片多、存活对象少的 Region)。
(5)初始转移(Initial Relocate)------ STW 阶段
log
[0.843s][info][gc] ZGC(0) Initial Relocate Start
[0.843s][info][gc] ZGC(0) Initial Relocate End (0.2ms)
- 极短 STW(0.2ms),转移根对象直接引用的对象(为并发转移铺路)。
(6)并发转移(Concurrent Relocate)
log
[0.843s][info][gc] ZGC(0) Concurrent Relocate Start
[0.851s][info][gc] ZGC(0) Concurrent Relocate End (8.1ms)
- 并发执行,将存活对象从旧 Region 转移到新 Region(压缩内存,避免碎片),通过着色指针和读屏障保证应用线程访问正确地址。
(7)并发清理(Concurrent Cleanup)
log
[0.851s][info][gc] ZGC(0) Concurrent Cleanup Start
[0.852s][info][gc] ZGC(0) Concurrent Cleanup End (0.5ms)
- 并发回收空 Region(已完成对象转移的旧 Region),释放内存供下次分配。
3. 周期总结:总耗时与堆变化
log
[0.852s][info][gc] ZGC(0) Heap After GC: 128M used, 384M capacity (1.5s)
Heap After GC
:GC 后堆使用量 128MB,总容量 384MB。- 整个 GC 周期耗时 1.5s(主要是并发阶段,STW 总耗时仅 ~2ms)。
三、关键指标与分析重点
- STW 时间 :关注
Initial Mark
、Final Mark
、Initial Relocate
三个阶段的耗时,正常应 <10ms,若超标可能需调优堆大小或 GC 线程数。 - GC 频率 :短时间内频繁触发 GC(如每秒多次),可能是内存分配速率过高或堆过小,需增大堆(
-Xmx
)或优化对象创建。 - 堆使用率 :
Heap After GC
的使用率若持续超过 70%,可能导致 GC 频繁,建议调整堆大小或ZMaxHeapSizePercent
(默认 90%)。 - 转移效率 :
Concurrent Relocate
耗时过长,可能是存活对象过多(需优化对象生命周期)或 CPU 资源不足(增加 GC 线程:-XX:ZGCThreads=n
)。
四、实战示例:通过日志定位问题
若日志中频繁出现:
log
[5.210s][warn][gc] ZGC(10) Heap exhausted, starting GC immediately
说明堆内存即将耗尽,GC 被迫紧急触发,可能原因:
- 堆大小不足(需增大
-Xmx
); - 存在内存泄漏(需结合内存快照分析大对象)。
通过配置 ZGC 日志并聚焦上述关键信息,可有效评估其低延迟特性、定位性能瓶颈,为调优提供数据支撑。