Appearance
GC 日志怎么看:先看频率、停顿时间,再看是不是 Young GC 和 Full GC
很多人第一次看 GC 日志,会直接被一大串时间、分区和内存数字劝退。
其实真正排查线上问题时,不需要一上来就做 JVM 调优专家。先把最重要的几个判断做对,已经能解决很多问题。
先说结论
看 GC 日志时,优先回答四个问题:
- GC 发生得频不频繁
- 停顿时间长不长
- 是 Young GC 多,还是 Full GC 多
- GC 之后内存有没有明显回落
这四件事比单纯盯着某一行日志更重要。
一、先把两类 GC 分清楚
Young GC
主要回收新生代。
一般特点:
- 次数相对更多
- 单次停顿通常更短
Full GC
会涉及老年代,通常代价更大。
如果线上频繁出现 Full GC,通常就要提高警惕了。
它可能意味着:
- 老年代对象堆积严重
- 内存泄漏
- 大对象分配异常
- 晋升压力过大
二、GC 日志最值得先看什么
1. 频率
如果 GC 非常频繁,即使每次停顿不长,也可能明显影响吞吐。
2. 停顿时间
如果单次停顿很长,用户侧更容易直接感知到卡顿。
3. 回收前后内存变化
例如:
- GC 前使用量很高
- GC 后却几乎没降多少
这往往说明:
- 活对象很多
- 或者存在无法释放的引用
三、先给出一套够用的阅读顺序
可以按这个顺序看:
- 先看是否频繁出现 Full GC
- 再看每次停顿是否明显变长
- 看 GC 后堆是否能降回合理区间
- 如果降不回去,再结合 Heap Dump、MAT、对象分布继续查
四、GC 日志常见的几种信号
1. Young GC 很多,但 Full GC 很少
这不一定是问题。
如果:
- 停顿可接受
- 服务吞吐正常
那只是正常回收行为。
2. Full GC 开始频繁出现
这是更值得优先关注的信号。
要继续排查:
- 老年代是不是一直涨
- 是否有缓存、集合、ThreadLocal 等对象留住内存
3. GC 后内存回不去
这通常比“GC 频繁”更值得警惕。
因为它更像:
- 活对象真实很多
- 或者存在泄漏
4. 停顿时间越来越长
这可能意味着:
- 堆太大但对象结构复杂
- Full GC 成本高
- 内存碎片或晋升压力明显
五、日志之外还要配合看什么
GC 日志不是孤立看的。
通常还要结合:
- 应用响应时间
- CPU 使用率
- 堆使用趋势
jstat- Heap Dump
如果只是盯日志文本,很容易只看到表象。
六、JDK 版本不同,日志参数也不同
JDK 8 常见写法
bash
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/gc.logJDK 9+ 常见写法
bash
-Xlog:gc*:file=/path/gc.log:time,uptime,level,tags如果你现在是新项目,优先按 JDK 9+ 的方式理解更合适。
七、一个更贴近排障现场的判断方式
可以这样简单分层:
应用偶尔卡顿
先看:
- 是否存在长时间停顿的 Full GC
内存一直涨
先看:
- GC 后内存是否回落
吞吐明显下降
先看:
- GC 频率是否异常高
- 应用线程是否大量时间都花在 GC 停顿外等待资源
八、不要一上来就调参数
很多 JVM 问题,最后根因并不是“参数不够好”,而是:
- 集合无限增长
- 缓存没有上限
- 临时对象产生过多
- 大对象处理方式不合理
所以更稳妥的顺序通常是:
- 先确认是不是代码层对象问题
- 再考虑 JVM 参数和 GC 策略优化
一句话总结
GC 日志最重要的不是逐行背格式,而是先看:
- 频率
- 停顿
- Full GC
- 回收后是否降得下来
把这四件事看明白,GC 日志就已经不再难读了。