Java 频繁GC 完整排查流程
频繁GC 是Java最常见的线上故障之一直接表现CPU 高、响应慢、卡顿、甚至OOM。我给你一套最实用、最快定位的排查步骤从查看GC情况 → 定位原因 → 解决问题全程不猜、不重启。一、先确认是不是真的频繁GC1. 看GC实时状态最关键jstat-gcPID100010每1秒输出一次GC共10次。重点看这4列YGCYoungGC 次数每秒涨好几次 频繁YoungGCYGCTYoungGC 总耗时FGCFullGC 次数只要一直在涨 严重问题FGCTFullGC 总耗时判定标准线上通用FGC 每分钟 ≥1 次→ 严重频繁GC必须立刻处理YGC 每秒 ≥2 次→ 频繁YoungGCGC耗时占比 10%→ 影响业务二、快速判断频繁GC 分 3 种类型1.频繁 FullGC最危险症状CPU 高、应用卡顿、FGC 疯狂上涨原因内存泄漏、堆内存不足、大对象、元空间溢出2.频繁 YoungGC症状YGC 很高但FGC不涨原因新生代太小、创建对象太快3.YoungGC 高 慢慢触发 FullGC原因内存泄漏最常见三、3步定位频繁GC根因实战流程第一步看堆内存使用情况jmap-heapPID重点看堆总配置老年代使用率元空间使用率如果老年代快满了还在涨→ 内存泄漏。第二步导出堆快照定位谁在占用内存jmap-dump:formatb,fileheap.hprofPID⚠️ 注意生产导出时会STW建议低峰期执行或者加参数-dump:live,formatb...只抓存活对象更快第三步分析堆快照找泄漏代码用以下工具打开heap.hprofEclipse MAT最强JProfilerIDEA 自带 Profiler你重点找这3类问题某个业务对象实例数暴增内存泄漏超大集合List/Map 只加不删静态变量缓存了大量对象最常见泄漏点四、90% 的频繁GC 就这 5 种原因1.内存泄漏最常见特征FGC 越来越频繁老年代回收不掉典型代码static Map 不断put数据不清理线程池使用不当ThreadLocal 没remove流、连接未关闭2.堆内存太小特征GC 后内存依然占满解决加大-Xmx3.创建大对象/瞬时对象过多比如超大List、批量查询、JSON序列化特征YGC 非常频繁4.元空间溢出特征FGCOGF: Metaspace原因反射、动态代理、大量类加载5.直接内存泄漏NIO/Netty 未释放直接内存导致频繁FullGC五、1分钟快速排查命令直接复制# 1. 找Java进程ps-ef|grepjava# 2. 实时GC监控jstat-gcPID1000# 3. 看堆内存jmap-heapPID# 4. 导出堆dumpjmap -dump:live,formatb,fileheap.hprofPID# 5. 看线程栈排查CPUGC关联jstackPID六、解决方案直接对照用1. 内存泄漏修复代码用完的集合清空ThreadLocal 调用 remove()关闭流/连接缓存加过期、加淘汰策略2. 新生代太小-Xmn2g 或调整 NewRatio3. 堆太小-Xms4g -Xmx4g4. 元空间太小-XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m5. 对象创建太快优化批量查询、减少大对象、异步、缓存七、最实用的GC排查口诀FGC频繁查泄漏 YGC频繁看对象 堆满就是内存漏 泄漏都在集合里。总结jstat -gc确认频繁GCjmap -dump导出堆MAT分析谁占内存90% 是static集合、ThreadLocal、缓存无回收导致泄漏