使用Eclipse Memory Analyzer分析java程序占用内存的情况


简介

Eclipse 内存分析器(Eclipse Memory Analyzer)是一款快速且功能强大的 Java 堆内存分析工具,可帮助您发现内存泄漏并降低内存消耗。

使用内存分析器,您可以分析包含数亿个对象的堆转储文件,快速计算对象的保留大小(retained sizes),查看哪些对象阻止了垃圾回收器(Garbage Collector)对其进行回收,并运行报告以自动提取潜在的内存泄漏嫌疑对象。

Eclipse Memory Analyzer Tool (MAT)是eclipe发面的jvm运行内存分析工具,可以分析java程序运行中不同线程占用内存的情况,对于分析内存溢出异常定位有很大的帮助。

1。下载安装

下载地址:Memory Analyzer (MAT)  Downloads | The Eclipse Foundation

根据不同的需要,个人可以自行下载不同的版本: 

1.1 推荐下载Stand-alone Eclipse RCP Applications 独立程序。以下步骤都是用独立安装版本进行说明。

1.2 通过eclipse的扩展功能的方式安装, 又分两种方法:一是通过的eclipse的安装扩展的方法直接添加的装更新网址, 另一种是直接下载zip包到本地,然后再手动安装eclipse扩展。

1.3 当前(2025-8-5)的版本需要JDK17才能运行, 也就是说要在系统装到jdk17方可正常运行MAT

2。布署运行

不管下载的的哪个平台(win/mac/linux)的版本, 都是一个压缩包。解压后进入要目录, 双击可执行文件 MemoryAnalyzer.(exe ..不同平台有不同辍,这都不重要,重要的是运行可执行文件)。

 

3。 生成需要分析的内存堆

比如我的tomcat程序或者springboot jar包运行时卡住了, 反应极为缓慢或都直接卡死不响应, 怀疑cpu/mem占用过高, 那么我们就需要导出这个运行的程序占用内存堆的数据。

在linux平台用以下方法导出

(1) 通过 “ps”命令可以得到系统各进程cpu/mem占用情况

# ps aux

得到的系统程序运行情况大概如下 

可以看到, 列数据依次代表: 用户名, 进程ID,cpu占用率,内存占用率。。。。知道些就可以进行必的筛选了。

比如我们可以通过以下命令筛选占用CPU达到70%以上的java程序(不管tomcat还是 springboot都是java运行的程序)

# ps aux|grep java|awk ‘{if($3>70.0) print $2}’|sed -n 1p

grep 过虑java程序,awk只打印cpu(第三列)占用超过70%的PID号, sed只选第一个,不仅想看第一个,那么可以不加sed过虑。

假如我们等到的PID为12507如下:

当然也可以根据内存占用率来读取PID, 参考命令如下 :

# ps aux|grep java|awk ‘{if($4>40.0) print $2}’|sed -n 1p

$4就是第4列,即内存占用率, 假如系统总内存是8G, 那么大于%40就是占用内存超过3.2G的程序。

 

如是windows系统运行的java程序, 那查找cpu/内存占用率高的就相对简单了, 打开任务管理器,对进程进行排序即可,如下图:

 

(2)接下来可以根据pid导出内存堆数据:

# $JAVA_HOME/bin/jmap -dump:format=b,file=/root/heap.12507.hprof 12507

得到文件 /root/heap.12507.hprof 

4.分析内存堆

如果linx系统本机已经有桌面(gnome/kde等)直接在linux运行MAT并导入内存堆。如果想下载到windows主机进行分析,堆文件过大时,可以先用tar打包工具压缩打包再下载,下载后再解包。

(1)在MAT导入内存堆

File / Open Heap Dump …

选择上一步导出的hprof文件 ,选择好后会弹出一个选择分析选项, 默认finish。

 

(2)导入成功后查看“Overview”, 把鼠标移到点用率最高的饼块,可以看到” http-nio-8080-exec-10″这个线程占用了最多的空间内存

 

(3)分析是哪个类方法处理什么数据导致的占用率高, 点击“Leak Suspects”, 可以看到,这个线程里的某个 java.lang.Object[] 对象占用了大部(83.5%), 接下来看看是哪个类哪个方法处理了什么数据。

(4)堆栈跟踪, 点“See stacktrace”, 排除一些公共类, 可以看到”SoapServiceImpl”的其中一个方法出了问题

 

(5) 查看是处理哪些数据导致占用内存过高。回到”Overview”标签, 点”Dominator Tree”

 

来到 dominator_tree标签, 根据线程名称和占比数据, 依次点开, 就可以查看到是处理什么数据了,如下图:

 至此, 定位方法和处理数据的内容都已经找到, 然后根据这个结果。 回去优化java代码。