堆溢出解决思路

OOM:Java 堆溢出 java.lang.OutOfMemoryError: Java heap space

现象:‑Xmx 设置的最大堆内存被占满,GC 反复回收,回收后内存依然不够,抛出堆溢出。

一、定位步骤(排查思路)

  1. 开启堆 dump,发生 OOM 自动导出堆快照

    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=/xxx/heap.hprof

程序 OOM 时自动生成 hprof 文件,用 MAT(Memory Analyzer Tool)(Eclipse 开源的内存分析工具,专门分析 hprof 堆转储快照文件,用来排查 Java 内存泄漏、堆 OOM)分析。

  1. MAT 分析 hprof 做三件事 ① 看大对象、支配树:是谁持有大量对象,是谁的引用链不让对象 GC。 ② 看对象数量:哪个类实例数量异常暴涨。 ③ 找泄漏点:对象本应该被回收,但被 GC Roots 强引用死死抱住。

区分两种完全不同情况:

  1. 内存泄漏(Memory Leak):对象不再业务使用,但存在强引用,无法 GC,内存只涨不降。
  2. 内存溢出(Memory Overflow):业务本身就需要这么多对象,内存给小了,没有泄漏。

二、情况 1:内存泄漏(最常见)

对象不用了,还被强引用持有,无法 GC。

常见泄漏场景

  1. 集合(List/Map)全局 static,只 add 不 remove,全局集合不断累积对象。
  2. ThreadLocal 没有 remove ();线程池线程复用,ThreadLocalMap 还持有对象引用。
  3. 监听器、回调注册,注销失败,引用没释放。
  4. 内部类持有外部类引用;匿名内部类捕获外部对象。
  5. 缓存没有设置淘汰策略(没有 LRU、过期时间),无限膨胀。

解决:

  • 不用的对象手动清除集合元素;
  • ThreadLocal 用完必须 remove;
  • 缓存增加最大容量、过期淘汰(Caffeine、Guava Cache);
  • 及时注销监听器回调;
  • 避免长生命周期对象持有短生命周期对象。

三、情况 2:没有泄漏,业务确实需要大量对象(堆内存配置过小)

例子:一次性查询百万数据全部加载进 List,全部放到内存。

MAT 看对象都是业务正常需要的,没有不该存活的对象。

解决思路二选一:

  1. 调高‑Xmx 堆内存,机器物理内存允许的前提下加大堆;
  2. 不要一次性全加载到内存,做流式处理 / 分页:分批读取、游标分页,不要把全量数据装入 List;使用迭代器逐条处理。

坑:select * from table 查出几十万行封装进 List,直接打爆堆,属于业务写法问题,不是泄漏。

四、代码层面临时优化手段

  1. 大对象尽量方法内局部变量,方法执行结束,无其他引用就可以 GC;
  2. 大集合用完置为 list=null,帮助 GC Roots 解除引用(更多是可读性,JVM 会自动识别);
  3. 避免在循环内疯狂 new 大量对象;循环内尽量复用对象,减少对象创建(看业务)。

五、GC 角度分析

观察 GC 日志:

复制代码
-XX:+PrintGCDetails

如果看到:YGC 频繁,每次回收后可用内存很少;频繁 Full GC,内存几乎释放不下来 → 大概率内存泄漏。 如果一次性突增大量对象直接打满堆,回收效果尚可,只是瞬时需要内存大 → 业务数据量问题。

相关推荐
bbq粉刷匠3 小时前
ArrayList 整体认识
java·jvm·数据结构
math_hongfan3 小时前
鸿蒙存储碎片高级清理机制:数据库Vacuum/文件碎片整理/缓存过期清理/主动空间回收策略
jvm·数据库·学习·缓存·华为·harmonyos·鸿蒙
花生了什么事o2 天前
JVM 垃圾回收:对象如何被判定和回收
java·jvm
程序员雷欧2 天前
ThreadPoolExecutor 深度解析:从核心参数到源码实现的全面剖析
java·开发语言·jvm
wuminyu2 天前
JUC包的AQS与JVM的ObjectMonitor机制对比分析
java·linux·c语言·jvm·c++
梦云莓铃 脚后跟法3 天前
从一个真实案例理解 JVM 标量替换
jvm
看浪的路人3 天前
第3讲:手写第一个 MCP Server(Python SDK)
jvm·数据库·oracle
lee_curry3 天前
RuoYi Cloud:Gateway、Auth、System 接入 Prometheus JVM 监控,并练习多副本、滚动升级和故障恢复
jvm·gateway·prometheus