java内存泄漏本质是对象持续堆积致gc压力增大、停顿变长;应通过gc日志、jstat、jconsole/visualvm监控老年代缓慢爬升等“缓慢恶化”迹象,再用jmap+mat定位泄漏源,并关注spring boot中静态集合、threadlocal等特殊泄漏点。

Java 内存泄漏导致程序变慢,本质是对象持续堆积、GC 压力增大、停顿变长。实时监控的关键不是等 OOM 发生,而是捕捉“缓慢恶化”的过程——比如老年代缓慢爬升、GC 频次增加、单次耗时拉长。以下方法可直接落地,无需重启应用:
看 GC 行为是否异常
GC 是内存健康最灵敏的晴雨表。启用详细日志后,重点盯住三项:
-
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/logs/gc.log(JDK9+ 推荐用-Xlog:gc*:file=/logs/gc.log:time,uptime,pid,tags) - 每隔 10–30 秒用
jstat -gc <pid> 1000</pid>查看实时趋势:-
OU(Old Used)持续上升且 Full GC 后不回落 → 老年代对象无法回收,高度可疑 -
FGCT(Full GC 总耗时)明显增长,或FGC(次数)陡增 → 回收效率下降,已开始拖慢响应 -
YGC(Young GC)频率异常升高 → 可能是大量短命对象逃逸到老年代,背后常有缓存滥用或日志误写
-
盯住堆内存实时曲线
用轻量工具持续观察,避免“只看峰值”:
-
JConsole(JDK 自带):连接后切换到“内存”页,勾选“所有堆内存池”,重点关注PS Old Gen或G1 Old Gen的使用曲线。若空闲操作下仍缓升,且多次手动触发 GC(点击“执行 GC”按钮)后无明显下降,基本确认泄漏 -
VisualVM(含 VisualGC 插件):比 JConsole 更直观显示新生代/老年代/元空间的动态占比和 GC 时间轴,支持保存快照对比 -
JProfiler或YourKit:开启“Live Memory”视图,按类名排序,观察实例数是否随业务操作线性增长(如每次查列表就多 100 个UserDTO,关闭页面也不减)
捕获堆现场,定位谁在占着不放
监控发现异常后,立刻抓取堆快照分析:
-
jmap -dump:live,format=b,file=heap_$(date +%s).hprof <pid></pid>(生产环境慎用,建议在低峰期执行) - 用 Eclipse MAT 打开
.hprof文件,查看 “Dominator Tree” → 找出内存占比最高的对象及其强引用链 - 对比两次 dump(如操作前 vs 操作后),用 MAT 的 “Compare Heap Dumps” 功能,直接标出新增/未释放的对象类型
补充:Spring Boot 应用要额外关注的点
- 检查
ApplicationContext中是否存在静态集合、未注销的@EventListener、ThreadLocal未清理、ScheduledTask泄漏线程 - 访问
/actuator/metrics/jvm.memory.used?tag=area:heap(需启用 Actuator),用 Prometheus 抓取指标画趋势图,比人工盯更可靠
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











