如何在 Java 中进行内存泄漏分析?

Sherwin.Wei Lv8

如何在 Java 中进行内存泄漏分析?

回答重点

先确认是否真的发生了内存泄漏,即观察内存使用情况。

利用 jstat 命令(jstat -gc <pid> <interval in ms> )来观察 gc 概要信息,如果发现 GC 后内存并没有明显的减少且还是持续增加持续触发 gc,那说明内存泄漏的概率很大。

此时可以利用 jmap(jmap -dump:format=b,file=heapdump.hprof <pid>)生成 heap dump,然后将其导入 Eclipse MAT 或者 VisualVM 工具内进行分析,通过大量内存的占用可以找到对应的对象。

通过对象找到对应的代码分析,确认是否可能存在内存泄漏的场景,最终修复代码,解决内存泄漏的问题。

扩展知识

Eclipse Memory Analyzer (MAT)

Eclipse Memory Analyzer (MAT) 是一个强大的 Java 堆分析工具,主要用于查找和解决内存泄漏问题。

主要功能

1)堆转储分析

  • 支持分析 .hprof 格式的堆转储文件,生成对象的详细视图和引用路径。

2)泄漏检测

  • 自动检测内存泄漏,提供泄漏报告,帮助开发者定位问题对象。

3) 对象查询

  • 使用 OQL(Object Query Language)对对象进行查询,快速查找特定对象。

4) 视图和图表

  • 提供对象分布图、保留集分析等可视化功能,帮助理解内存使用情况。

5)整合

  • 可以与 Eclipse IDE 集成,方便开发者直接在开发环境中进行分析。

使用方法

  • 生成堆转储:使用 jmap -dump 命令生成 .hprof 文件。
  • 导入文件:在 MAT 中打开堆转储文件,进行分析。
  • 使用自动分析功能获取泄漏信息,查看对象引用路径和内存占用情况。

VisualVM

VisualVM 是一个功能强大的 Java 性能监控和故障排除工具,提供实时监控和分析功能。

主要功能
1)实时监控

  • 实时查看 CPU 使用率、内存占用、线程活动等,监控应用的运行状态。

2)堆转储和分析

  • 支持生成和分析堆转储,查看内存使用情况和对象分布。

3)线程分析

  • 提供线程视图,能够显示线程状态、线程栈信息,帮助识别死锁和高 CPU 使用的线程。

4)插件支持

  • 支持通过插件扩展功能,提供更灵活的监控和分析选项。

5)JMX 监控

  • 能够监控 JMX 代理的 Java 应用,获取各种运行时指标。

使用方法

  • 启动 VisualVM:在终端运行 jvisualvm
  • 选择目标 Java 应用:在主界面选择要监控的 Java 进程。
  • 使用“监控”选项卡查看实时数据,使用“堆转储”选项生成和分析堆转储。

jstat

Java 自带的命令行工具,主要用来监控 JVM 中的类加载、GC、线程等信息。

附 jstat 输出字段解释:

  • S0C/S1C/S0U/S1U: 年轻代中Eden区、Survivor区1和Survivor区2的容量(Capacity)和使用量(Used)。
  • EC/EU: 年轻代中Eden区的容量和使用量。
  • OC/OU: 老年代的容量和使用量。
  • MC/MU: 方法区的容量和使用量。
  • CCSC/CCSU: 压缩类空间的容量和使用量。
  • YGC: 年轻代GC的次数。
  • YGCT: 年轻代GC所用的时间。
  • FGC: 老年代GC的次数。
  • FGCT: 老年代GC所用的时间。
  • GCT: 总的GC时间。

怎么分析 JVM 当前的内存占用情况?

Comments