判断是否频繁Full GC关键看频率、触发原因和回收效果:正常为几小时至几天一次,若达每分钟≥1次需警惕,每30秒≥1次属严重异常;Cause为Metadata GC Threshold、Allocation Failure等指向具体根因;老年代回收前后无变化或下降极少表明内存泄漏或配置不当;单次STW超1秒即引发明显卡顿。

看 GC 日志判断是否频繁 Full GC,关键不是数“有没有 Full GC”,而是看它发生的频率、触发原因和回收效果。正常服务的 Full GC 几小时甚至几天一次;一旦变成几分钟、几十秒一次,就属于异常频发。
看频率:单位时间内的 FGC 次数
打开 GC 日志(如 gc.log),用文本工具或脚本统计单位时间内的 Full GC 行数:
- 每分钟 ≥1 次 → 需警惕
- 每 30 秒 ≥1 次 → 严重异常,应用可能已卡顿
- 配合监控看趋势:如果 FGC 曲线呈密集锯齿状上升,而非偶发单点,基本可断定是持续性问题
看触发原因(GC Cause)
每条 Full GC 日志开头都会带 Cause,这是定位根因的核心线索:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- Metadata GC Threshold → 元空间(Metaspace)快满了,常见于动态代理、热部署、类加载器泄漏
- Allocation Failure → 老年代空间不足,对象晋升失败,最常见,大概率是内存泄漏或堆配置不合理
- System.gc() → 代码或第三方库显式调用了 System.gc(),应全局搜索并移除
- concurrent mode failure(CMS)或 to-space exhausted(G1)→ 垃圾收集器并发阶段失败,常因老年代增长太快或 GC 线程资源不足
看回收效果:老年代是否真被清空
重点关注日志中老年代(Old / ParOldGen / G1 Old Gen)回收前后的使用量:
- 比如:
[ParOldGen: 6992345K->6992345K(6993920K)],回收前后数值几乎不变 → 对象没被回收,极可能是内存泄漏 - 每次 Full GC 后老年代使用率只下降 5%–10%,且很快又涨回高位 → 回收效率差,存活对象多
- 对比 Young GC:如果 YGC 很多但老年代缓慢上涨,说明对象在 Survivor 区反复复制后最终晋升,也指向新生代参数不合理或短生命周期对象变长
看耗时与停顿(STW 时间)
Full GC 的 real 时间就是 STW 时长,直接影响接口响应:
- 单次 > 1 秒 → 用户明显感知卡顿
- 连续多次在 500ms–2s 区间 → 监控上 RT P99 会同步飙升
- FGCT(Full GC 总耗时)占 GCT(总 GC 耗时)比例过高(如 >30%)→ GC 已成性能瓶颈
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










