简介MemoryAnalyzerMAT1.11.0 是面向 Java 开发与性能调优人员的堆内存分析工具可在 JDK8 环境下独立运行用于排查内存泄漏、定位大对象与对象引用链。它支持直观查看各对象在堆空间的占用大小、类实例数量、引用关系并可通过 OQL 对象查询快速找出 GC Roots 相关信息适合处理大内存 dump 文件的场景。压缩包共 453 个文件约 76.24MB以 183 个 jar 核心组件、61 个 png 与 9 个 gif 界面资源、41 个 html 帮助文档、26 个 xml 与 23 个 properties 配置为主另含 exe 启动程序、bat 脚本及 css 主题样式结构完整可直接解压使用。目前已有 2493 人学习下载能帮助读者快速搭建内存分析环境掌握 dump 解析、对象引用追踪与 GC Roots 排查思路提升线上问题定位效率。1. MemoryAnalyzer 在 JDK8 与 win32.x86_64 下的真实定位线上堆内存告警服务重启后现场全丢只剩一份几百 MB 的 hprof 文件躺在磁盘上。这时候能救命的工具不多MemoryAnalyzer简称 MAT是其中最常被翻出来的一个。标题里的MemoryAnalyzer(JDK8)-1.11.0.20201202-win32.win32.x86_64.zip说的就是这件事一个面向 Windows 64 位平台、依赖 JDK8 运行环境的 MAT 发行包版本号 1.11.0构建日期 2020 年 12 月 2 日。它解决的核心问题只有一个——把堆转储文件打开找出到底是谁在占内存、谁在泄漏、谁在制造重复对象。适合谁用后端 Java 工程师、做性能压测的测试同学、需要排查 OOM 的运维。不适合谁只想看个内存曲线的人MAT 是重型武器启动慢、吃内存、界面不算友好但它的支配树和泄漏嫌疑报告至今没有免费工具能完全替代。这一章先把「这是什么、能解决什么」讲清楚后面几章再落到下载、解压、配置、跑通和排错。2. 从 zip 到能打开 hprof环境准备与首次启动2.1 为什么 JDK8 是硬门槛而不是可选项MAT 1.11.0 这个版本对运行时有明确要求。它内部大量使用 Eclipse RCP 框架而该框架在 JDK8 之后的模块化体系JPMS下会出现类加载冲突。常见做法是单独准备一个 JDK8不要用系统里已有的 JDK11 或 JDK17 去启动它。标题里win32.win32.x86_64表示这是 Windows 64 位版本解压后目录里会有MemoryAnalyzer.exe和plugins、features等文件夹。如果你机器上只有高版本 JDKMAT 启动时可能直接闪退或者报Java Virtual Machine Launcher错误。血泪经验是不要试图改MemoryAnalyzer.ini里的-vm指向高版本 JDK先老老实实装一个 JDK8。2.2 解压与目录结构确认拿到 zip 后不要直接双击里面的 exe先完整解压到一个没有中文和空格的路径比如D:\tools\mat。中文路径在某些 Eclipse RCP 版本下会导致插件加载失败这是踩过的坑。# 假设 zip 放在 D:\downloads cd /d D:\downloads # 用系统自带 tar 或 7-Zip 解压避免 Windows 资源管理器解压大文件时丢文件 tar -xf MemoryAnalyzer(JDK8)-1.11.0.20201202-win32.win32.x86_64.zip -C D:\tools\ # 解压后确认目录 dir D:\tools\MemoryAnalyzer逻辑说明用tar而不是右键解压是因为 Windows 资源管理器对长路径和特殊字符的处理不稳定容易漏掉plugins下的小文件。参数-C指定目标目录解压后你会看到MemoryAnalyzer.exe、MemoryAnalyzer.ini、plugins、features、configuration这几个关键项。2.3 指定 JDK8 启动并验证# MemoryAnalyzer.ini 关键片段 -vm D:/jdk8/bin/javaw.exe -vmargs -Xmx4g -Dsun.zip.disableMemoryMappingtrue逻辑说明-vm必须单独一行下面一行写javaw.exe的完整路径路径用正斜杠或双反斜杠。-Xmx4g是给 MAT 自身用的堆不是被分析应用的堆。分析大 hprof 时这个值要调大但不要超过物理内存的 70%。-Dsun.zip.disableMemoryMappingtrue是官方推荐参数避免在 Windows 上因 zip 内存映射导致启动卡死。参数怎么改如果 hprof 文件 2GB 以上-Xmx建议设为 6g 到 8g如果机器只有 8GB 内存先关掉其他占内存的程序。启动成功后菜单栏Help-About Memory Analyzer能看到版本号 1.11.0说明环境对了。3. 打开 hprof 与支配树从文件到泄漏嫌疑3.1 导入堆转储的两种方式第一种是启动时直接选Open a Heap Dump第二种是进入主界面后File-Open Heap Dump。如果 hprof 是从生产环境拿来的注意它可能被压缩过MAT 支持.hprof、.hprof.gz、.zip内的 hprof。常见做法是先用jmap导出再传到本地。# 在生产机器上导出堆转储注意这会触发 STW jmap -dump:formatb,file/tmp/heap.hprof pid # 如果文件太大可以加 live 只导出存活对象 jmap -dump:live,formatb,file/tmp/heap_live.hprof pid逻辑说明formatb表示二进制格式file指定输出路径live会先触发一次 Full GC 再导出文件更小但会暂停更久。生产环境慎用live除非你确认能承受一次 Full GC 的停顿。3.2 支配树Dominator Tree怎么读打开 hprof 后MAT 会先做索引大文件可能等几分钟。索引完成后最该看的不是 Histogram而是 Dominator Tree。支配树的含义是如果对象 A 支配对象 B那么 A 被回收时 B 一定也会被回收。这能帮你找到「谁真正持有了一大片内存」。在 Dominator Tree 里按Retained Heap排序排第一的往往就是问题源头。常见现象是某个HashMap或ArrayList的 Retained Heap 特别大展开后能看到里面存了几十万个业务对象。这时候右键该对象选Path to GC Roots-exclude weak/soft references就能看到是谁在强引用它。3.3 泄漏嫌疑报告Leak Suspects的用法与局限MAT 会自动生成 Leak Suspects 报告位置在Overview页面的Leak Suspects链接。它会给出几个「嫌疑点」比如「一个实例占了 60% 的堆」。但要注意它只是嫌疑不是定罪。我遇到过 Leak Suspects 指向一个缓存对象但实际原因是缓存没有设上限业务代码不断往里塞数据。// 典型问题代码无界缓存 private static final MapString, Object CACHE new HashMap(); public void put(String key, Object value) { CACHE.put(key, value); // 没有淘汰策略迟早 OOM }逻辑说明MAT 能告诉你这个HashMap很大但为什么大、该不该大需要结合业务判断。参数上关注Retained Heap而不是Shallow Heap前者才是这个对象被回收后能释放的总内存。4. 避坑与排查MAT 使用中的五个真实翻车现场4.1 启动报 “Java was started but returned exit code13”现象双击MemoryAnalyzer.exe后弹窗提示 exit code 13。原因-vm指向的 JDK 位数不对比如用 32 位 JDK 启动 64 位 MAT或者路径写错。解决确认D:/jdk8/bin/javaw.exe存在且是 64 位版本。用java -version确认输出里有64-Bit。4.2 打开 hprof 时卡在 “Parsing heap dump”现象进度条长时间不动CPU 占用高但内存不涨。原因hprof 文件损坏或者导出时进程被 kill 导致文件不完整。解决用jhat或Eclipse Memory Analyzer的命令行版本先校验如果文件头不对只能重新导出。后悔药是导出时加-dump:formatb并确保磁盘空间充足。4.3 分析大文件时 MAT 自身 OOM现象MAT 报OutOfMemoryError: Java heap space。原因MemoryAnalyzer.ini里-Xmx太小。解决改成 6g 或 8g同时加-XX:-UseGCOverheadLimit。注意 32 位 JDK 最大只能到 1.5g 左右所以必须用 64 位 JDK。4.4 中文路径导致插件加载失败现象MAT 启动后菜单缺失或者报Could not find plugin。原因解压路径含中文或空格。解决移到D:\tools\mat这类纯英文路径。这是 Eclipse RCP 的老毛病不是 MAT 独有。4.5 误把 Shallow Heap 当 Retained Heap现象在 Histogram 里看到某个类实例数很多以为泄漏结果发现每个对象都很小。原因Shallow Heap 只是对象自身大小不包含它引用的其他对象。解决切到 Dominator Tree 看 Retained Heap或者右键选Calculate Retained Size。这个坑新手必踩记住一句话找泄漏看 Retained看数量看 Shallow。5. 进阶技巧用 OQL 和对比功能定位增长点5.1 OQL 查询像 SQL 一样查堆MAT 内置 Object Query Language可以精确查找对象。比如找出所有大于 1MB 的byte[]SELECT * FROM byte[] b WHERE b.retainedHeapSize 1048576逻辑说明byte[]是数组类型retainedHeapSize是 MAT 的内置属性。这条查询能快速定位大数组常用于排查缓冲区泄漏。参数上1048576是 1MB 的字节数可以按需调整。5.2 对比两个 hprof找出增长的对象MAT 支持把两个堆转储做对比。做法是先打开一个 hprof然后File-Compare with another Heap Dump选另一个文件。它会生成一个对比表显示哪些类实例数增加了、哪些减少了。这个功能在排查「运行一段时间后内存上涨」时特别有用。# 间隔一段时间导出两次 jmap -dump:formatb,file/tmp/heap1.hprof pid sleep 3600 jmap -dump:formatb,file/tmp/heap2.hprof pid逻辑说明两次导出之间让服务跑一段时间然后对比。重点看Objects列增加最多的类那通常就是泄漏点。注意两次导出都会 STW尽量在低峰期做。5.3 一个我常用的习惯每次分析完我会把 Leak Suspects 报告和 Dominator Tree 的前 20 名截图存档并在文件名里写上日期和版本。下次再出问题先翻上次的存档对比一下是不是同一个对象在涨。这个习惯帮我省过好几次重新分析的时间。MAT 不是万能的它给的是线索定罪还得靠代码和业务逻辑。希望帮到你。本文还有配套的精品资源点击获取
