Java应用在Debian上出现内存泄漏的排查与修复
一、快速确认与现场保护
- 确认泄漏特征:观察 RSS/堆内存是否随时间单调增长且 Full GC 后仍不回落;伴随 OutOfMemoryError 或响应显著变慢。
- 保护现场:
- 保留最近一次或数次 Heap Dump(见下文),避免被覆盖。
- 采集 GC 日志 与 线程转储,便于关联对象增长与线程行为。
- 如进程已不稳定,先备份业务日志与配置,再重启,减少影响面。
二、定位步骤与关键命令
- 监控与采样
- 实时观察堆与 GC:使用 jstat -gc ;查看类加载、堆各代使用与 GC 次数/时间。
- 线程与阻塞点:使用 jstack 抓取线程栈,排查线程泄漏、阻塞与死锁。
- 可视化监控:使用 jconsole 或 VisualVM 观察内存曲线、线程、类加载与 MBeans。
- 获取堆转储
- 按需导出:jmap -dump:format=b,file=heapdump.hprof (注意短暂 STW)。
- OOM 自动导出:在启动参数加入 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/yourapp/,便于下次崩溃自动落盘。
- 分析堆转储
- 使用 Eclipse MAT 或 VisualVM 打开 .hprof:优先查看 Histogram(对象数量/占用)、Dominator Tree(支配树)、Leak Suspects(泄漏疑点报告),定位持有对象的根引用链。
- 无法导出堆时的兜底
- 生成系统级 core dump:gcore -o /tmp/java_core (会短暂停顿);再用 jhsdb jmap --exe /usr/lib/jvm/…/bin/java --core /tmp/java_core. --dumpfile heap.hprof 导出 hprof,最后用 MAT 分析。
- 容器与权限提示
- 容器内执行需具备 SYS_PTRACE 能力或进入宿主机命名空间;生成的 core/hprof 文件可能很大,确保磁盘与 I/O 充足。
三、常见根因与修复要点
- 静态集合/缓存 长期持有对象引用:改为弱引用/软引用或引入过期/淘汰策略(如 WeakHashMap、带大小的缓存)。
- 资源未关闭:数据库连接、文件/网络流、会话等务必在 try-with-resources 或 finally 中关闭,或使用池化并正确归还。
- 线程本地变量 ThreadLocal 使用不当:线程池场景下易累积,使用完及时 remove,避免类加载器泄漏。
- 内部类/回调持有外部类:生命周期不一致导致外部对象无法回收,改为静态内部类或弱引用持有。
- 缓存无边界:引入 最大容量、TTL、LRU/LFU 等限制与主动清理机制。
- 变更对象哈希/相等性 导致 Map 键无法被回收:确保 hashCode/equals 稳定且必要时使用不可变键。
四、JVM与运行环境优化
- 堆与元空间
- 合理设置 -Xms/-Xmx(如逐步调大到可稳定承载业务的水平),避免过小导致频繁 GC,过大掩盖问题。
- Java 8+ 关注 Metaspace:使用 -XX:MetaspaceSize / -XX:MaxMetaspaceSize 避免元空间无限增长。
- 垃圾回收器选择
- 结合延迟/吞吐目标选择 G1、ZGC 或 Shenandoah 等;在 JDK 11+ 场景,G1/ZGC 通常更易在通用服务中取得平衡。
- 诊断参数
- 开启 -XX:+HeapDumpOnOutOfMemoryError 与 -XX:HeapDumpPath;按需开启 Flight Recorder(JDK 8u40+)进行低开销持续记录,配合 Java Mission Control 分析。
- Tomcat 场景
- 在 $CATALINA_OPTS 或 setenv.sh 中配置堆与 GC 参数;定期升级 Tomcat 以修复已知泄漏问题;发生泄漏时结合 jvisualvm/MAT 分析堆转储。
五、最小可行排查命令清单
- 查找进程:jps -l 或 ps aux | grep java
- 实时 GC/内存:jstat -gc 1000
- 线程栈:jstack > thread.dump
- 堆转储:jmap -dump:format=b,file=heap.hprof
- 自动落盘 OOM:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/yourapp/
- core 转 hprof:jhsdb jmap --exe /usr/lib/jvm/…/bin/java --core /tmp/java_core. --dumpfile heap.hprof
- 分析工具:jconsole / VisualVM / Eclipse MAT / Java Mission Control