gc日志主要包含时间戳、gc类型(如young gc、full gc)、gc原因、gc前后的堆内存使用情况(各区域大小及变化)、gc耗时以及具体的回收动作详情。通过分析这些信息,可以判断系统是否存在内存泄漏、堆配置是否合理以及gc停顿对应用性能的影响。

如何解析GC日志中的时间戳与GC类型
解析GC日志时,首先需要关注每行日志开头的相对时间戳和GC事件类型。时间戳通常以秒为单位,显示从JVM启动开始经过的时间,用于计算GC频率和停顿时长。GC类型标识了触发的是年轻代收集(Young GC)还是全局收集(Full GC),这是判断垃圾回收行为的基础。

[0.123s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause)
上述示例展示了G1收集器的一次年轻代暂停。日志结构通常遵循“[时间][级别][标签] 描述”的格式。在OpenJDK 9及以后的版本中,日志层级更加清晰,`Pause Young`表示年轻代收集,而`Full`则代表全局收集。通过统计这些类型的出现频率,可以快速定位频繁的GC事件。
立即学习“Java免费学习笔记(深入)”;
如何分析GC前后的堆内存变化与耗时
除了类型,GC日志的核心价值在于展示堆内存的变化量。每一段GC日志通常会列出各个内存区域(如Eden、Survivor、Old Gen或G1的各个Region)在GC前的大小、GC后的大小以及被回收的空间。同时,日志末尾会明确给出该次GC的总耗时,单位通常为毫秒。

[0.125s][info][gc,heap] GC(0) Eden: 1048576K->0B(1048576K) Survivors: 102400K->102400K Heap: 2097152K->1048576K(4194304K)
在上面的输出片段中,可以看到Eden区从约1GB变为0,说明所有存活对象被移动到了Survivor区或晋升到老年代。Heap行显示了整个堆的使用量从约2GB下降到约1GB,意味着回收了约1GB的垃圾。耗时可以通过对比两次GC日志的时间戳差值,或直接读取日志中提供的`Duration`字段来获取。这些数据有助于评估GC对应用吞吐量的影响。
基于G1收集器日志中的Evacuation Failure具体问题分析
当使用G1收集器时,日志中可能出现`Evacuation Failure`这一特定信息。这发生在年轻代空间不足,且无法将存活对象成功复制到Survivor区或老年代时。此时,G1会退化为单线程的Serial Old收集器进行Full GC,导致严重的停顿。
要排查此问题,需检查日志中是否有`Evacuation Failure`字样,并观察随后的`Full GC`耗时是否异常长。这通常意味着老年代碎片化严重或预留空间不足。解决方法包括增大`-XX:MaxGCPauseMillis`设定的目标停顿时间对应的堆大小,或者调整`-XX:G1ReservePercent`以增加老年代的预留空间,避免复制失败。


















