直接看gc日志中的reason字段即可快速定位full gc原因:allocation failure(老年代将满或survivor过小)、metadata gc threshold(元空间耗尽)、system.gc()(显式调用)、concurrent mode failure(cms碎片化)、ergonomics(jvm自适应触发)。

直接看日志里的关键字段和上下文,就能快速锁定 Full GC 是哪类原因触发的。不用等OOM,也不用先 dump 堆,GC 日志本身已经包含足够多的线索。
看 Full GC 日志中的触发原因关键词
每条 Full GC 日志开头或括号内通常会带一个 reason(原因标识),这是最直接的判断依据:
- Allocation Failure:新生代满、对象晋升失败,老年代没空间接收 → 老年代真的快满了,或者 Survivor 区太小导致对象提前晋升
- Metadata GC Threshold 或 Metaspace allocation failure:元空间(Metaspace)耗尽 → 类加载过多,比如热部署、动态代理、大量反射、自定义 ClassLoader 泄漏
-
System.gc():代码或第三方库显式调用了
System.gc()→ 检查是否有监控埋点、测试代码、旧框架(如某些老版本 Druid、Quartz)自动触发 -
concurrent mode failure(CMS 收集器):CMS 并发清理阶段还没做完,老年代就撑不住了 → 老年代碎片化严重,或预留空间(
-XX:CMSInitiatingOccupancyFraction)设得太高 -
Ergonomics:JVM 自适应策略主动触发 → 多见于开启了
-XX:+UseAdaptiveSizePolicy,且堆各区域比例频繁调整失败
结合前后几行日志看内存变化趋势
单看一行 reason 不够,要拉出前后 3~5 次 GC 记录,观察“老年代使用量”是否持续上涨:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 如果每次 Full GC 后老年代占用率从 85% → 70% → 82% → 75% → 86%,呈缓慢爬升 → 很可能是内存泄漏(对象被意外强引用)
- 如果 Full GC 后老年代瞬间降到 10% 以下,但几分钟后又冲到 95% 触发下一次 → 更可能是业务流量突增 + 新生代配置不合理,对象批量晋升
- 关注
O(Old)列数值:用jstat -gcutil PID 2000实时看,若 O 持续 >80% 且不回落,基本可确认是老年代瓶颈
区分 Full GC 和 “伪装成 Full GC” 的行为
有些日志写着 Full GC,实际不是真正意义上的整堆回收:
- G1 收集器下出现
Full GC (Ergonomics)或Full GC (G1 Evacuation Pause):其实是 G1 回退到单线程串行收集,说明并发标记失败或 Humongous 分配失败,根源常在大对象或堆碎片 - ZGC / Shenandoah 日志里几乎不会出现 Full GC 字样:它们的设计目标就是消除 STW 全堆回收,若看到 Full GC,大概率是退化为 Serial GC,说明系统资源严重不足(如 swap 频繁、CPU 被抢占)
- 日志中
PSFullGC(Parallel Scavenge + Parallel Old)或CMS Full GC:说明用的是对应组合,可反推 JVM 参数是否匹配当前负载
用工具辅助识别模式(非必须但高效)
人工扫日志容易漏,推荐用轻量工具快速聚类:
- GCViewer:本地打开 gc.log,自动统计 Full GC 类型分布、停顿时间曲线、老年代/元空间增长斜率
- gceasy.io(上传日志在线分析):能标出“可疑内存泄漏迹象”“元空间增长速率异常”等提示,适合快速给结论
- 自己写个简单脚本统计:比如
grep "Full GC" gc.log | grep -o "reason=.*" | sort | uniq -c,一眼看出哪类原因占主导
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










