Java 频繁GC 完整排查流程

频繁GC 是Java最常见的线上故障之一,直接表现:CPU 高、响应慢、卡顿、甚至OOM

我给你一套最实用、最快定位的排查步骤,从查看GC情况 → 定位原因 → 解决问题,全程不猜、不重启。


一、先确认:是不是真的频繁GC?

1. 看GC实时状态(最关键)

bash 复制代码
jstat -gc <PID> 1000 10

每1秒输出一次GC,共10次。

重点看这4列

  • YGC:YoungGC 次数(每秒涨好几次 = 频繁YoungGC)
  • YGCT:YoungGC 总耗时
  • FGC :FullGC 次数(只要一直在涨 = 严重问题
  • FGCT:FullGC 总耗时

判定标准(线上通用)

  1. FGC 每分钟 ≥1 次 → 严重频繁GC,必须立刻处理
  2. YGC 每秒 ≥2 次 → 频繁YoungGC
  3. GC耗时占比 >10% → 影响业务

二、快速判断:频繁GC 分 3 种类型

1. 频繁 FullGC(最危险)

症状:CPU 高、应用卡顿、FGC 疯狂上涨

原因:内存泄漏、堆内存不足、大对象、元空间溢出

2. 频繁 YoungGC

症状:YGC 很高,但FGC不涨

原因:新生代太小、创建对象太快

3. YoungGC 高 + 慢慢触发 FullGC

原因:内存泄漏(最常见)


三、3步定位频繁GC根因(实战流程)

第一步:看堆内存使用情况

bash 复制代码
jmap -heap <PID>

重点看:

  • 堆总配置
  • 老年代使用率
  • 元空间使用率

如果老年代快满了还在涨 → 内存泄漏。


第二步:导出堆快照(定位谁在占用内存)

bash 复制代码
jmap -dump:format=b,file=heap.hprof <PID>

⚠️ 注意:

  • 生产导出时会STW,建议低峰期执行
  • 或者加参数:-dump:live,format=b... 只抓存活对象(更快)

第三步:分析堆快照(找泄漏代码)

用以下工具打开 heap.hprof

  • Eclipse MAT(最强)
  • JProfiler
  • IDEA 自带 Profiler

你重点找这3类问题

  1. 某个业务对象实例数暴增(内存泄漏)
  2. 超大集合(List/Map 只加不删)
  3. 静态变量缓存了大量对象(最常见泄漏点)

四、90% 的频繁GC 就这 5 种原因

1. 内存泄漏(最常见)

特征:FGC 越来越频繁,老年代回收不掉

典型代码:

  • static Map 不断put数据,不清理
  • 线程池使用不当,ThreadLocal 没remove
  • 流、连接未关闭

2. 堆内存太小

特征:GC 后内存依然占满

解决:加大 -Xmx

3. 创建大对象/瞬时对象过多

比如:超大List、批量查询、JSON序列化

特征:YGC 非常频繁

4. 元空间溢出

特征:FGC,OGF: Metaspace

原因:反射、动态代理、大量类加载

5. 直接内存泄漏

NIO/Netty 未释放直接内存,导致频繁FullGC


五、1分钟快速排查命令(直接复制)

bash 复制代码
# 1. 找Java进程
ps -ef | grep java

# 2. 实时GC监控
jstat -gc <PID> 1000

# 3. 看堆内存
jmap -heap <PID>

# 4. 导出堆dump
jmap -dump:live,format=b,file=heap.hprof <PID>

# 5. 看线程栈(排查CPU+GC关联)
jstack <PID>

六、解决方案(直接对照用)

1. 内存泄漏

修复代码:

  • 用完的集合清空
  • ThreadLocal 调用 remove()
  • 关闭流/连接
  • 缓存加过期、加淘汰策略

2. 新生代太小

复制代码
-Xmn2g 或调整 NewRatio

3. 堆太小

复制代码
-Xms4g -Xmx4g

4. 元空间太小

复制代码
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m

5. 对象创建太快

优化批量查询、减少大对象、异步、缓存


七、最实用的GC排查口诀

复制代码
FGC频繁查泄漏,
YGC频繁看对象,
堆满就是内存漏,
泄漏都在集合里。

总结

  1. jstat -gc 确认频繁GC
  2. jmap -dump 导出堆
  3. MAT 分析谁占内存
  4. 90% 是static集合、ThreadLocal、缓存无回收导致泄漏
相关推荐
用户128526116026 小时前
我把祖传Java项目重构后,接口响应从3s砍到了200ms,只改了这几行代码
java
Linsk6 小时前
组件 = 模板 + 业务逻辑
java·前端·vue.js
星沉远浦7 小时前
用Gemini高效解决Java代码报错难以定位的问题
java
用户2986985301410 小时前
Word 文档字符级格式化:Java 实现方案详解
java·后端
笨鸟飞不快11 小时前
从单个服务到集群:一次完整的性能排查复盘
java·前端
荣码11 小时前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
SamDeepThinking11 小时前
Java微服务练习方式
java·后端·微服务
朦胧之21 小时前
AI 编程-老项目改造篇
java·前端·后端
程序猿大帅1 天前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
程序员晓琪1 天前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端