Java 内存泄漏(Memory Leak)通常指对象已经不再使用,但却因为某些引用关系无法被 GC 回收,导致堆内存持续增长,最终可能触发 OutOfMemoryError: Java heap space。
下面从思路 → 工具 → 实操步骤 → 常见场景系统讲一遍。
不是所有内存涨都是泄漏:
-Xmx 设置太小判断标准:
内存泄漏 = 强引用未释放
排查步骤一句话总结:
定位泄漏对象 → 找到是谁引用它 → 看代码为什么没释放
jps # 查看 Java 进程
jstat -gc <pid> # 看 GC 情况
jmap -heap <pid> # 看堆配置和使用
重点看:
OU(Old Gen Used)是否一直涨jmap -dump:live,format=b,file=heap.hprof <pid>
或 JVM 参数(OOM 自动 dump):
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/heap.hprof
| 工具 | 特点 |
|---|---|
| MAT (Eclipse Memory Analyzer) | 最强,推荐 |
| VisualVM | 轻量 |
| JProfiler | 商业,好用 |
| Arthas | 线上排查神器 |
MAT 会自动提示:
“哪些对象占内存最多,谁引用了它们”
找:
HashMapArrayListThreadLocal右键对象 → Path to GC Roots
你会看到类似:
HashMap
└── CacheManager.instance
└── static field
✅ 基本就定位到泄漏点了
# 查看内存占用最大的类
dashboard
# 查看某个类实例数
sc -d com.xxx.User
# 查看对象引用
heapdump /tmp/heap.hprof
public static List<User> list = new ArrayList<>();
✅ 解决:用 WeakHashMap 或定时清理
threadLocal.set(obj);
// 忘记 remove
✅ 解决:
try {
threadLocal.set(x);
} finally {
threadLocal.remove();
}
eventBus.register(this);
// 没 unregister
Map<String, Object> cache = new HashMap<>();
✅ 用:
WeakReferenceLRUCaffeine / Guava CacheInputStream in = ...
// 没 close
✅ try-with-resources
✅ 编码规范:
static 存业务对象✅ JVM 参数:
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails
Java 内存泄漏排查 = 抓堆 dump + MAT 看引用链 + 改代码断引用
如果你愿意,可以把:
发出来,我可以直接帮你定位是哪一行在泄漏。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。