使用工具分析:
Eclipse MAT(Memory Analyzer Tool):打开 `heapdump.hprof`,查看支配树(Dominator Tree),找出占用内存最大的对象。
VisualVM 或 JProfiler:检查对象实例数量和引用链。
4. 排查内存泄漏
常见泄漏点:
静态*类:如 `static Map` 长期持有对象引用。
未关闭资源:数据库连接、文件流等。
缓存配置不合理:如未设置过期时间或大小限制。
代码检查:
查找大对象或频繁创建对象的代码段。
使用弱引用(WeakReference)或软引用(SoftReference)优化缓存。
5. 优化代码与配置
缓存优化:
java
// 使用Caffeine缓存示例,限制大小和过期时间
Cache cache = Caffeine.newBuilder
maximumSize(1000)
expireAfterWrite(10, TimeUnit.MINUTES)
build;
减少对象创建:重用对象或使用对象池(如Apache Commons Pool)。
6. 堆外内存检查
若堆内存正常但进程内存高,使用NMT排查:
bash
jcmd VM.native_memory summary
检查Direct Buffer或JNI调用,避免不合理的堆外内存分配。
7. 线程与堆栈分析
查看线程数量:
bash
jstack | grep 'java.lang.Thread.State' | wc -l
调整线程栈大小(`-Xss256k`)减少内存占用,若线程过多。
8. 持续监控与测试
启用JFR实时监控:
bash
jcmd JFR.start name=my_recording settings=profile
jcmd JFR.dump name=my_recording filename=recording.jfr
使用Java Mission Control(JMC)分析JFR记录,定位内存分配热点。
9. 使用Arthas在线诊断
实时查看内存情况:
bash
arthas
dashboard 查看内存、线程状态
heapdump live /path/to/dump.hprof 生成堆转储
10. 总结与验证
验证调整效果:修改后监控内存使用率是否下降,GC是否正常。
压测复现问题:在测试环境模拟高负载,确认优化措施有效。
通过以上步骤,逐步排查和优化,可有效降低Java应用的内存使用率。若确认是内存泄漏,需结合代码修复;若资源不足,则考虑扩容或优化资源分配。