用 JDK 17 真实生成可被 MAT 打开的堆快照练习文件
本文档手把手教你用 JDK 17 生成真实的、MAT 可分析的堆快照文件.hprof并在 MAT 中完成一次完整的内存泄漏分析练习。目录一、前置准备二、编写模拟内存泄漏的 Java 程序三、编译并运行四、生成堆快照三种方式五、用 MAT 打开并分析六、MAT 练习路线图七、常见问题排查八、一键脚本一、前置准备1.1 确认 JDK 版本java-version预期输出JDK 17 即可21 也行openjdk version 17.0.12 2024-07-16 OpenJDK Runtime Environment (build 17.0.127) OpenJDK 64-Bit Server VM (build 17.0.127, mixed mode)⚠️ 不需要 JDK 17 特别版任何 JDK 11 都可以关键是有jmap和jcmd工具。1.2 下载 MAT参照之前的文档下载与你 JDK 匹配的 MAT 版本JDK 版本推荐 MAT 版本下载地址JDK 17MAT 1.14.0https://download.eclipse.org/mat/1.14.0/rcp/JDK 21MAT 1.15.0 / 1.16.0https://www.eclipse.org/mat/downloads.php1.3 创建项目目录mkdir-p~/mat-practicecd~/mat-practice二、编写模拟内存泄漏的 Java 程序2.1 完整源码在项目目录中创建LeakDemo.javaimportjava.util.*;importjava.util.concurrent.*;/** * 模拟内存泄漏的练习程序 * * 包含三种经典泄漏场景 * 1. 静态缓存 Map 无淘汰机制最常见 * 2. ThreadLocal 未清理 * 3. 大对象byte[]持续分配 * * 运行方式 * javac LeakDemo.java * java -Xms512m -Xmx512m -XX:HeapDumpOnOutOfMemoryError \ * -XX:HeapDumpPath./leak.hprof LeakDemo */publicclassLeakDemo{// 场景1静态缓存泄漏 // Spring 单例 Bean 中的 static Map只 put 不 removeprivatestaticfinalMapLong,byte[]productCachenewConcurrentHashMap();// 场景2ThreadLocal 泄漏 // 每个线程持有一个不断增长的 List线程不退出 → 内存泄漏privatestaticfinalThreadLocalListStringthreadLocalDataThreadLocal.withInitial(ArrayList::new);// 场景3大对象列表 // ArrayList 不断 add 1MB 的 byte[]永不清理privatestaticfinalListbyte[]tempBuffersnewArrayList();// 控制程序运行privatestaticvolatilebooleanrunningtrue;publicstaticvoidmain(String[]args)throwsException{longpidProcessHandle.current().pid();System.out.println();System.out.println( LeakDemo - 内存泄漏模拟程序);System.out.println( PID: pid);System.out.println();System.out.println();System.out.println(手动生成堆快照命令);System.out.println( jmap -dump:formatb,fileleak.hprof pid);System.out.println( 或);System.out.println( jcmd pid GC.heap_dump leak.hprof);System.out.println();System.out.println(等待 OOM 自动 dump或手动执行上面的命令...);System.out.println();// 启动监控线程startMonitor();longcounter0;while(running){// --- 场景1缓存泄漏 ---// 每个对象 1MB不停塞入 MapproductCache.put(counter,newbyte[1024*1024]);// --- 场景2ThreadLocal 泄漏 ---// 每个线程的 List 不断增长threadLocalData.get().add(leak-data-counter);// --- 场景3临时缓冲区虽然叫临时但永不清理---if(counter%100){tempBuffers.add(newbyte[1024*1024]);// 每10次加一个1MB}counter;// 打印进度if(counter%500){System.out.printf([%6d] cache%d, threadLocal%d, buffers%d%n,counter,productCache.size(),threadLocalData.get().size(),tempBuffers.size());}// 控制速度避免瞬间 OOM让你有时间手动 dumpTimeUnit.MILLISECONDS.sleep(50);}}/** * 监控线程每 5 秒打印堆内存使用情况 */privatestaticvoidstartMonitor(){ThreadtnewThread(()-{RuntimertRuntime.getRuntime();while(running){longused(rt.totalMemory()-rt.freeMemory())/1024/1024;longmaxrt.maxMemory()/1024/1024;doublepct(double)used/max*100;System.out.printf([Monitor] 堆: %dMB/%dMB (%.0f%%)%s%n,used,max,pct,pct85? ⚠️ 即将OOM!:);try{Thread.sleep(5000);}catch(InterruptedExceptionignored){}}},monitor);t.setDaemon(true);t.start();}}2.2 代码说明场景代码位置模拟的真实问题静态缓存泄漏productCache电商商品缓存无淘汰Map 无限增长ThreadLocal 泄漏threadLocalDataWeb 容器线程池中的 ThreadLocal 未 remove大对象堆积tempBuffers集合只 add 不 clearbyte[] 占满堆三、编译并运行3.1 编译cd~/mat-practice javac LeakDemo.java编译成功后会生成LeakDemo.class文件。3.2 运行带 OOM 自动 dump 参数java-Xms512m-Xmx512m\-XX:HeapDumpOnOutOfMemoryError\-XX:HeapDumpPath./leak.hprof\LeakDemo或者在pom.xml文件添加配置buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationjvmArguments-Xms256m-Xmx256m-XX:MetaspaceSize128m-XX:MaxMetaspaceSize256m-XX:UseG1GC-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath./heapdump.hprof-Dfile.encodingUTF-8/jvmArguments/configuration/plugin/plugins/build参数解释参数作用-Xms512m初始堆大小 512MB-Xmx512m最大堆大小 512MB故意设小快速触发 OOM-XX:HeapDumpOnOutOfMemoryErrorOOM 时自动生成堆快照-XX:HeapDumpPath./leak.hprof快照保存路径3.3 预期运行效果 LeakDemo - 内存泄漏模拟程序 PID: 12345 手动生成堆快照命令 jmap -dump:formatb,fileleak.hprof 12345 或 jcmd 12345 GC.heap_dump leak.hprof 等待 OOM 自动 dump或手动执行上面的命令... [Monitor] 堆: 45MB/512MB (8%) [ 50] cache50, threadLocal50, buffers5 [ 100] cache100, threadLocal100, buffers10 [Monitor] 堆: 158MB/512MB (30%) [ 150] cache150, threadLocal150, buffers15 ... [Monitor] 堆: 450MB/512MB (87%) ⚠️ 即将OOM! [ 480] cache480, threadLocal480, buffers48 [Monitor] 堆: 495MB/512MB (96%) [Monitor] 堆: 508MB/512MB (99%) ⚠️ 即将OOM! java.lang.OutOfMemoryError: Java heap space Dumping heap to ./leak.hprof ... Heap dump file created [268435456 bytes in 2.345 secs]leak.hprof文件已自动生成这就是一个真实的、MAT 可分析的堆快照。四、生成堆快照三种方式方式一OOM 自动生成最简单就是上面 3.2 的方式等程序自然 OOM 即可。适合练习和演示。方式二jmap 手动生成最常用 ⭐程序运行时另开一个cmd终端执行# 1. 查找 PIDjps-l# 输出示例12345 LeakDemo# 2. 生成堆快照jmap-dump:formatb,fileleak.hprofPID# 输出Heap dump file created⚠️关键参数说明formatb→ 生成二进制格式MAT 可识别不要加live参数jmap -dump:live,...会先触发 Full GC把所有泄漏对象清掉MAT 就分析不出问题了方式三jcmd 生成JDK 7 推荐# 查找 PIDjcmd# 生成堆快照jcmd12345GC.heap_dump leak.hprofjcmd是 Oracle 官方推荐的替代jmap的新工具功能更全。三种方式对比方式触发条件优点缺点OOM 自动堆满了零操作自动生成服务已崩溃jmap随时手动灵活不影响服务会触发 STW短暂停顿jcmd随时手动官方推荐功能多同 jmap五、用 MAT 打开并分析5.1 打开堆快照启动 MATFile→Open Heap Dump→ 选择leak.hprof选择Leak Suspects Report点击Finish5.2 预期看到的分析结果MAT 会自动生成报告你应该能看到类似以下内容Leak Suspects Report:Dominator Tree支配树Window→Open Dominator Tree按Retained Heap排序你会看到Path To GC Roots关键操作在 Dominator Tree 中右键ConcurrentHashMap选择Path To GC Roots→exclude weak/soft references你会看到引用链③ Histogram直方图Window→Histogram按Objects排序Class Name | Objects | Shallow Heap ----------------------------|---------|------------- byte[] | 528 | 480 MB ← 异常多的 byte[] java.lang.String | 480 | 38 MB java.util.concurrent.ConcurrentHashMap$Node | 480 | 30 MB④ Thread OverviewWindow→Thread Overview查看每个线程的内存占用找到持有大量 ThreadLocal 数据的线程。六、MAT 练习路线图打开堆快照后按以下顺序练习由浅入深第 1 步看自动报告Leak Suspects标签页看 Problem Suspect 摘要点击Details查看详情理解 MAT 的自动分析逻辑第 2 步Histogram 分析Window→Histogram按对象数量排序 → 找异常多的类按 Shallow Heap 排序 → 找大对象右键类 →List objects→with incoming references第 3 步Dominator TreeWindow→Open Dominator Tree按 Retained Heap 排序找到占用内存最大的对象理解 Shallow vs Retained 的区别第 4 步GC Roots 引用链核心技能右键对象 →Path To GC Roots→exclude weak references看清谁在引用这个对象理解为什么 GC 无法回收定位到具体的代码变量名第 5 步OQL 查询Window→OQL-- 查找所有 byte[] 且大小超过 1MB 的SELECT*FROMbyte[]WHERElength1048576-- 查找 String 对象SELECT*FROMjava.lang.String-- 查找 ArrayList 实例SELECT*FROMjava.util.ArrayListWHERElength100第 6 步对比两次快照进阶程序运行 30 秒时 dump 一次 →dump1.hprof程序运行 60 秒时 dump 一次 →dump2.hprofMAT 中打开dump2.hprof→Compare Basket→Add再打开dump1.hprof→Compare Basket→Add点击Compare→ 查看对象增长趋势七、常见问题排查7.1 MAT 打开报错 “Unknown HPROF Version”原因文件不是标准 HPROF 格式可能是文本文件或伪造的。排查# 检查文件头前 4 个字节应该是 JAVAxxd leak.hprof|head-1# 正确输出00000000: 4a41 5641 2050 524f 4649 4c45 2031 2e30# (JAVA PROFILE 1.0)# 检查文件大小ls-lhleak.hprof# 应该 100MB512MB 堆大概产生 200~400MB 的 hprof解决用jmap -dump:formatb,...或jcmd GC.heap_dump重新生成。7.2 MAT 显示 “No leak suspect was found”原因生成快照时加了live参数触发了 Full GC泄漏对象被清掉了。错误命令jmap -dump:live,formatb,fileleak.hprofpid❌正确命令jmap-dump:formatb,fileleak.hprofpid✅7.3 MAT 打开时报 OOM原因MAT 自身内存不足无法解析大文件。解决编辑MemoryAnalyzer.ini-vmargs -Xms2g -Xmx4g ← 调大这个建议设为 hprof 文件大小的 1.5~2 倍 -XX:UseG1GC7.4 生成的 hprof 文件太小只有几 MB原因程序还没来得及分配大量对象就退出了或者堆设太大、还没填满。解决减小堆-Xms256m -Xmx256m更快 OOM加快速度去掉Thread.sleep(50)确保程序真的在运行看控制台输出7.5 jmap 执行卡住或报 “Unable to attach”原因PID 不对或权限不足或容器环境限制。排查# 确认 PIDjps-l# 确认是同一个用户ps-ppid-ouser,pid,cmd# 容器环境用 jcmdjcmdpidGC.heap_dump leak.hprof八、一键脚本8.1 Linux/Mac 一键脚本run.sh#!/bin/bashset-eechoecho MAT 堆快照练习 - 一键运行echoecho# 编译echo[1/3] 编译...javac LeakDemo.javaecho✅ 编译成功echo# 创建输出目录mkdir-pdumps# 运行后台echo[2/3] 启动 LeakDemo后台运行...java\-Xms512m-Xmx512m\-XX:HeapDumpOnOutOfMemoryError\-XX:HeapDumpPath./dumps/leak_auto.hprof\-XX:PrintGCDetails\-Xloggc:./dumps/gc.log\LeakDemoPID$!echo✅ 进程已启动PID$PIDecho# 等待 30 秒让程序分配一些内存echo[3/3] 等待 30 秒后手动生成堆快照...sleep30# 手动 dump不带 live保留泄漏对象echo 正在生成堆快照...jmap-dump:formatb,file./dumps/leak_manual.hprof$PIDecho✅ 堆快照已保存到 ./dumps/leak_manual.hprofecho# 打印文件信息echo 生成的文件ls-lhdumps/echoecho 用 MAT 打开 ./dumps/leak_manual.hprof 开始练习echo# 等待用户按回车后杀掉进程read-p按回车键停止 LeakDemo...kill$PID2/dev/nullecho✅ 进程已停止8.2 Windows 一键脚本run.batecho off echo echo MAT 堆快照练习 - 一键运行 echo echo. echo [1/3] 编译... javac LeakDemo.java if errorlevel 1 ( echo ❌ 编译失败请检查 JDK 是否安装 pause exit /b 1 ) echo ✅ 编译成功 echo. mkdir dumps 2nul echo [2/3] 启动 LeakDemo后台运行... start /b java -Xms512m -Xmx512m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath./dumps/leak_auto.hprof LeakDemo echo ✅ 进程已启动 echo. echo [3/3] 等待 30 秒... timeout /t 30 /nobreak nul echo 查找 PID 并生成堆快照... for /f tokens1 %%i in (jps -l ^| findstr LeakDemo) do ( echo PID: %%i jmap -dump:formatb,file./dumps/leak_manual.hprof %%i ) echo ✅ 堆快照已保存到 .\dumps\leak_manual.hprof echo. echo 生成的文件 dir dumps echo. echo 用 MAT 打开 .\dumps\leak_manual.hprof 开始练习 echo. pause九、总结核心要点堆快照必须从真实运行的 JVM 中导出用jmap/jcmd/-XX:HeapDumpOnOutOfMemoryError不要加live参数否则 Full GC 会把泄漏对象清掉formatb必须有确保是二进制格式MAT 的-Xmx要够大建议设为 hprof 文件大小的 1.5~2 倍分析三板斧Histogram → Dominator Tree → Path To GC Roots完整命令速查# 编译javac LeakDemo.java# 运行OOM 自动 dumpjava-Xms512m-Xmx512m\-XX:HeapDumpOnOutOfMemoryError\-XX:HeapDumpPath./leak.hprof\LeakDemo# 查找 PIDjps-l# 手动 dump推荐jmap-dump:formatb,fileleak.hprofpid# 或 jcmdjcmdpidGC.heap_dump leak.hprof# 验证文件格式xxd leak.hprof|head-1# 应看到4a41 5641 2050 524f 4649 4c45JAVA PROFILE练习建议先用小堆-Xmx256m快速触发 OOM 自动生成快照再用jmap手动在不同时机生成多份快照做对比分析。掌握这套流程后线上遇到真实 OOM 你就能从容应对。附录JVM 参数速查表参数作用推荐值-Xms初始堆大小与-Xmx一致-Xmx最大堆大小根据物理内存设置-XX:HeapDumpOnOutOfMemoryErrorOOM 时自动 dump所有环境必开-XX:HeapDumpPathdump 文件路径确保目录存在且有写权限-XX:PrintGCDetails打印 GC 详情排查必备-XloggcGC 日志路径/data/logs/gc.log-XX:DisableExplicitGC禁止 System.gc()生产环境建议开启-XX:MaxDirectMemorySize限制堆外内存根据 NIO 使用量设置

相关新闻

电商商家获客难获客贵解决方案:平台卖家如何借助 BBWEYY 打造第二获客入口,含零代码SAAS、AI编程、源码定制交付

电商商家获客难获客贵解决方案:平台卖家如何借助 BBWEYY 打造第二获客入口,含零代码SAAS、AI编程、源码定制交付

平台卖家如何借助 BBWEYY 打造第二获客入口 摘要 在平台流量竞争持续升级、广告成本不断上升的背景下,越来越多电商平台商家面临站内获客贵、站外获客弱、客户沉淀难的现实问题。本文围绕电商平台商家的增长困境展开,重点讨论 BBWEYY 小程序与 GEO 服务…

2026/7/29 15:17:04 阅读更多 →
Arduino 101开发环境搭建指南:从驱动安装到第一个Blink程序

Arduino 101开发环境搭建指南:从驱动安装到第一个Blink程序

1. 从零开始:为什么选择 Arduino/Genuino 101 作为起点? 如果你刚刚踏入嵌入式开发或者物联网硬件的大门,面对琳琅满目的开发板,可能会感到一丝迷茫。Arduino Uno、ESP8266、树莓派 Pico…… 每个都宣称自己简单易用。那么&#x…

2026/7/29 15:17:04 阅读更多 →
三只猫课后作业3

三只猫课后作业3

说明 下面的思考以及答案,都是本人凭经验输出的,对于 AI,我的经验很不足的,主要是起到一个记录作用,以后熟悉这块之后再回过头来看看自己的来时路。 作者有一句话,值得在平时工作中使用:要思考a…

2026/7/29 15:17:04 阅读更多 →

最新新闻

树莓派GPIO开发:从WiringPi弃用看Libgpiod与GPIO Zero的迁移指南

树莓派GPIO开发:从WiringPi弃用看Libgpiod与GPIO Zero的迁移指南

1. 项目概述:一个时代的落幕与新的开始最近在捣鼓树莓派5的时候,想用经典的WiringPi库来点个灯,结果发现官方仓库的README里赫然写着“Deprecated”几个大字。那一刻,感觉就像一位熟悉的老伙计突然宣布退休,心里五味杂…

2026/7/29 15:24:16 阅读更多 →
AU-48双模拟麦模块:USB回环参考路径与低阻抗直驱输出的电路设计分析

AU-48双模拟麦模块:USB回环参考路径与低阻抗直驱输出的电路设计分析

一、双模拟麦克风输入架构与USB免驱的电路协同AU-48是一款仅支持模拟麦克风输入的双麦语音处理模组,与AU-60/A59P/A-59U等支持数字麦克风(PDM/I2S)的产品形成明确区分。模拟麦克风方案的优势在于麦克风选型的灵活性:用户可以自由选…

2026/7/29 15:24:16 阅读更多 →
零门槛AI短视频创作:5分钟学会用Pixelle-Video制作专业级视频

零门槛AI短视频创作:5分钟学会用Pixelle-Video制作专业级视频

零门槛AI短视频创作:5分钟学会用Pixelle-Video制作专业级视频 【免费下载链接】Pixelle-Video 🚀 AI 全自动短视频引擎 | AI Fully Automated Short Video Engine 项目地址: https://gitcode.com/GitHub_Trending/pi/Pixelle-Video 想要制作专业短…

2026/7/29 15:24:16 阅读更多 →
物联网安全:硬件安全模块(HSM)与PIC32MZ微控制器适配方案

物联网安全:硬件安全模块(HSM)与PIC32MZ微控制器适配方案

1. 物联网安全现状与硬件安全模块的必要性在当今万物互联的时代,物联网设备数量呈指数级增长,但随之而来的安全威胁也日益严峻。根据行业统计,2023年全球物联网设备遭受的网络攻击次数较前一年增长了近300%。传统基于软件的安全方案在面对物理…

2026/7/29 15:24:16 阅读更多 →
UI 色彩系统的数学之美:从色轮理论到算法生成色板的底层原理

UI 色彩系统的数学之美:从色轮理论到算法生成色板的底层原理

UI 色彩系统的数学之美:从色轮理论到算法生成色板的底层原理 一、引子:为什么"好看的配色"可以写成算法 设计师花四年学的色彩理论,本质上是一组数学公式在 HSL 色彩空间上的操作。互补色 色相 180,三等分配色 色相 …

2026/7/29 15:24:16 阅读更多 →
汽车无线连接核心技术:WiLink 8Q芯片架构、车规级设计与工程实践

汽车无线连接核心技术:WiLink 8Q芯片架构、车规级设计与工程实践

1. 项目概述:为什么汽车无线连接是块“硬骨头”?干了十几年车载电子,我越来越觉得,汽车无线连接这活儿,真不是简单地把手机里的Wi-Fi和蓝牙模块塞进车里就完事了。你想想,手机揣兜里,环境再恶劣…

2026/7/29 15:23:15 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻