直接回答:GC 日志回答四个问题:什么时候 GC、为什么触发(Allocation Failure/Metadata/GCLocker)、回收了多少(堆从 X→Y,总容量 Z)、花了多久(real 墙钟、user CPU、sys)。以 G1 为例看 Pause Young 行的“Eden/Survivor/Old 各区变化”与停顿时间;连续的 Full GC(G1 里是 evacuation failure 或 Old 区打满后的兜底串行 Full GC)是最严重的信号——吞吐型应用 Full GC 一次就该排查。
展开解析:分析套路:先宏观后微观。宏观:GC 频率(Young GC 每秒多次说明 Eden 太小或分配速率高)、停顿分布(P99 停顿是否超 SLA)、回收效率(每次 Young GC 后 Old 增长多少——持续净增长预示泄漏或晋升过快)。微观:单条日志看 user/sys/real 比值——real 远大于 user 说明线程被 IO 或 CPU 争抢拖住(容器 CPU limit 限速的典型表现),sys 高可能是透明大页或内存交换。触发原因的诊断价值:Metadata GC Threshold 是类加载膨胀(检查 Metaspace 设置与类加载泄漏);GCLocker 是 JNI 临界区阻止 GC;Allocation Stall(ZGC/Shenandoah)是回收跟不上分配。工具链:GCEasy、GCViewer 离线分析,线上用 JFR 持续录制(jdk.GCPhasePause 等事件)比解析日志更结构化。调优决策树:停顿长先看回收器选型与堆大小,吞吐低先看分配速率(多数 GC 问题的根因是代码制造了垃圾而不是 GC 参数)。
追问方向:humongous 对象在 G1 里有什么问题?ZGC 的日志关注点有何不同?
(约 490 字)