GC Overhead limit exceeded错误表明JVM将98%时间用于GC却仅回收不足2%内存,需通过GC日志识别Allocation Failure高频、Full GC间隔缩短且老年代占用率不变、新生代频繁无用回收等信号,结合堆转储分析Retained Heap及引用链,定位静态缓存、ThreadLocal未remove、资源未关闭等代码根源。

这个错误不是内存真不够,而是 GC 反复干活却收效甚微——98% 的时间在回收,只腾出不到 2% 的空间。排查关键不在“加内存”,而在找出“为什么回收不动”。
看 GC 日志,确认是否真的陷入恶性循环
启动时加上参数:-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
打开 gc.log 后盯住三类信号:
- 同一秒内连续出现多次
Allocation Failure或Metadata GC Threshold,说明分配压力持续高压 - Full GC 间隔越来越短,但每次回收后老年代占用率几乎不变(比如只降 1–3%)
- OOM 前密集刷屏
PSYoungGen或G1 Evacuation Pause,代表新生代在疯狂做无用功
抓堆镜像,找长期驻留的对象
别等崩溃才 dump,GC 频繁时就主动执行:jmap -dump:format=b,file=heap.hprof <pid>
用 VisualVM、JProfiler 或 MAT 打开后重点看:
- 按 Retained Heap 排序,排在前面的类未必是实例最多,而是“拖着最多其他对象”的那个
- 点开可疑类(比如 HashMap、ConcurrentHashMap、ArrayList),看它的 Reference Chain,找到最上层强引用者
- 常见“钉子户”:静态缓存没清理、ThreadLocal 没 remove、监听器注册后没反注册、流/连接未 close 导致关联缓冲区滞留
查运行时行为,排除开发环境干扰
如果是 IDEA 启动报错,先检查:
- Run Configuration 里的 VM options 是否过小(Spring Boot 项目建议
-Xms1g -Xmx2g) - 是否开了 “Build project automatically”,导致反复编译+类重载,触发 ClassLoader 泄漏
- 是否装了过多插件(尤其 Lombok、MyBatisX、Database Tools 类),它们可能在后台持有大量临时对象
扫代码,聚焦三类高频泄漏源
工具只能指方向,根因一定在代码里:
- 静态集合:
static Map<?, ?> cache = new HashMap<>()—— 没配 size 限制、LRU 或定时清理 - ThreadLocal:用完没调
remove(),尤其在线程池场景下会跨请求累积 - 资源未释放:
InputStream/Connection/Statement没用 try-with-resources,或 finally 里没 close
不复杂但容易忽略
立即学习“Java免费学习笔记(深入)”;


















