遇到OutOfMemoryError: Java heap space,说明JVM堆已无法分配新对象,程序将崩溃;需先用jstat、jmap确认是否真缺内存或存在泄漏,再通过HeapDumpOnOutOfMemoryError自动留证,最后用MAT分析GC Roots定位泄漏源头。

遇到 java.lang.OutOfMemoryError: Java heap space,说明 JVM 堆已无法为新对象分配空间,程序将崩溃——这不是可捕获继续运行的异常,而是必须立即响应的资源告警。
先快速确认是不是真缺内存
别急着调大 -Xmx。很多情况是堆明明够用,但对象被意外强引用住,GC 回收不了:
- 用 jstat -gc <pid> 看老年代使用量(OU):如果每次 Full GC 后 OU 持续上升,基本就是内存泄漏
- 用 jmap -histo <pid> 查数量异常多的类,比如 byte[]、ArrayList、自定义 DTO 列表
- 若伊甸园(EU)频繁满、但 OU 增长缓慢,可能是短期对象太多,需优化生命周期或调整新生代比例
让 JVM 出事时自动留证据
生产环境不能靠“等下次再看”,必须提前配置自动诊断能力:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 启动参数加上 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dump/,OOM 时自动生成 .hprof 文件
- 同步加 -XX:+PrintGCDetails -Xloggc:/opt/logs/gc.log,记录 GC 行为,判断回收效率是否骤降
- 确保 dump 路径可写、磁盘空间充足,否则 dump 失败却无提示
用 MAT 精准揪出泄漏源头
拿到 .hprof 后,关键不是看谁占内存多,而是看“谁不让它被回收”:
立即学习“Java免费学习笔记(深入)”;
- 用 Eclipse MAT 打开,先看 Leak Suspects Report,它会标出高嫌疑对象组
- 切换到 Dominator Tree,按 Retained Heap 排序,重点关注 ArrayList.elementData、ThreadLocalMap、ConcurrentHashMap 等容器类
- 对可疑对象右键 → Path to GC Roots → 排除弱/软引用,只保留强引用链,就能看到是哪个静态字段、单例或线程池里的 ThreadLocal 在长期持有
常见泄漏点和对应修复方式
以下写法看似无害,实则极易堆积对象:
- 静态集合无界增长:如 static Map<String, List<Order>> cache = new HashMap<>(); —— 改用 Guava Cache 或 Caffeine,并设 maximumSize 和 expireAfterWrite
- ThreadLocal 未清理:在线程池复用场景下,set() 后忘记 remove() —— 必须在 finally 块中显式调用 remove()
- 流/连接未关闭:文件、数据库连接、网络 Socket 未用 try-with-resources 或未显式 close —— 补全资源释放逻辑
- 监听器注册后未反注册:GUI 或事件总线中添加监听器后未在销毁时 remove —— 生命周期需严格配对

















