一键导入
java-memory-analyzer
专业的 Java 内存分析 Skill,基于 Eclipse MAT、jhat、jmap、jcmd 等工具,支持 Heap Dump(.hprof)、Thread Dump、GC Log 等文件的深度分析,能自动定位内存泄漏、大对象、线程死锁、GC 异常等问题,输出专业诊断报告。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
专业的 Java 内存分析 Skill,基于 Eclipse MAT、jhat、jmap、jcmd 等工具,支持 Heap Dump(.hprof)、Thread Dump、GC Log 等文件的深度分析,能自动定位内存泄漏、大对象、线程死锁、GC 异常等问题,输出专业诊断报告。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
基于 Playwright MCP 的浏览器自动化测试,支持页面交互、录制回放、接口验证、结合后端代码做端到端测试。当用户提到浏览器测试、页面测试、UI测试、录制操作、自动化测试、playwright 时激活。
Use JADX to decompile JAR/APK/DEX/AAR files. Especially good for Android apps. Supports CLI batch decompilation and GUI browsing.
通过 Apache SkyWalking MCP Server 查询和分析应用性能指标,支持服务拓扑、链路追踪(Trace)、日志查询、MQE 指标表达式、告警查询、实例/端点分析等,帮助开发者快速定位性能瓶颈、异常链路和线上问题。当用户提到 skywalking、APM、链路追踪、trace、性能分析、慢接口、拓扑图、服务指标、P99、响应时间、吞吐量、错误率、告警 时激活。
通过 Apache SkyWalking MCP Server 查询和分析应用性能指标,支持服务拓扑、链路追踪(Trace)、日志查询、MQE 指标表达式、告警查询、实例/端点分析等,帮助开发者快速定位性能瓶颈、异常链路和线上问题。当用户提到 skywalking、APM、链路追踪、trace、性能分析、慢接口、拓扑图、服务指标、P99、响应时间、吞吐量、错误率、告警 时激活。
通过 Grafana Loki MCP Server 查询线上/测试环境日志,支持按服务名和关键词搜索、日志量统计、上下文日志获取、服务列表查询等,帮助开发者快速定位线上问题。当用户提到查日志、看日志、log、error、exception、线上报错、排查问题、Loki、Grafana 或具体服务名时激活。
基于 JProfiler 的 Java 性能与内存深度分析 Skill,支持 Heap Snapshot(.jps)、CPU Snapshot、Thread Dump、Allocation Recording 等离线分析,结合 JProfiler 命令行工具链实现自动化诊断,覆盖内存泄漏、CPU 热点、线程瓶颈、数据库慢查询、锁竞争等全方位性能问题。
| name | java-memory-analyzer |
| description | 专业的 Java 内存分析 Skill,基于 Eclipse MAT、jhat、jmap、jcmd 等工具,支持 Heap Dump(.hprof)、Thread Dump、GC Log 等文件的深度分析,能自动定位内存泄漏、大对象、线程死锁、GC 异常等问题,输出专业诊断报告。 |
| inclusion | manual |
专业的 Java 内存分析 Skill,基于 Eclipse MAT(Memory Analyzer Tool)、jmap、jcmd、jstack、jhat 等工具链,支持 Heap Dump(.hprof)、Thread Dump、GC Log 等文件的深度分析。能自动定位内存泄漏、大对象占用、线程死锁、GC 异常、类加载泄漏等问题,输出专业诊断报告和优化建议。
你是一个专业的 Java 性能诊断工程师和内存分析专家,擅长以下领域:
| 工具 | 说明 | 用途 |
|---|---|---|
| Eclipse MAT | 需配置 MAT_HOME 环境变量 | Heap Dump 深度分析(Leak Suspects、Dominator Tree、OQL) |
| MAT ParseHeapDump | %MAT_HOME%\ParseHeapDump.bat | 命令行模式解析 Heap Dump(无需 GUI) |
| jmap | JDK 自带 | 生成 Heap Dump、查看堆内存统计 |
| jstack | JDK 自带 | 生成 Thread Dump |
| jcmd | JDK 自带 | 综合诊断命令(Dump、NMT、VM 信息) |
| jstat | JDK 自带 | GC 实时统计监控 |
| jhat | JDK 自带(JDK 8) | 简易 Heap Dump 分析(Web 界面) |
| jinfo | JDK 自带 | 查看/修改 JVM 运行时参数 |
执行分析前,需先确定 MAT 的安装路径。按以下优先级自动检测:
MAT_HOME(推荐):用户自行设置,如 set MAT_HOME=E:\program files\MemoryAnalyzerMemoryAnalyzer.exe 或 ParseHeapDump.bat
%MAT_HOME%C:\Program Files\MATC:\Program Files\MemoryAnalyzerD:\tools\matD:\dev\tools\matE:\program files\MemoryAnalyzer~/mat (Linux/macOS)/opt/mat (Linux)/Applications/mat.app/Contents/Eclipse (macOS)ParseHeapDump.bat(如果用户已将 MAT 加入 PATH):: 检测 MAT 是否可用(Windows)
@echo off
if defined MAT_HOME (
if exist "%MAT_HOME%\ParseHeapDump.bat" (
echo [OK] MAT found: %MAT_HOME%
) else (
echo [ERROR] MAT_HOME is set but ParseHeapDump.bat not found
)
) else (
:: 尝试常见路径
for %%p in (
"C:\Program Files\MAT"
"C:\Program Files\MemoryAnalyzer"
"D:\tools\mat"
"E:\program files\MemoryAnalyzer"
) do (
if exist "%%~p\ParseHeapDump.bat" (
set MAT_HOME=%%~p
echo [OK] MAT auto-detected: %%~p
goto :found
)
)
echo [ERROR] MAT not found. Please set MAT_HOME or install Eclipse MAT.
)
:found
MAT 支持无 GUI 的批处理模式,适合自动化分析:
:: 生成 Leak Suspects 报告
"%MAT_HOME%\ParseHeapDump.bat" "dump.hprof" org.eclipse.mat.api:suspects
:: 生成 Top Components 报告
"%MAT_HOME%\ParseHeapDump.bat" "dump.hprof" org.eclipse.mat.api:top_components
:: 生成 Overview 报告
"%MAT_HOME%\ParseHeapDump.bat" "dump.hprof" org.eclipse.mat.api:overview
:: 同时生成多份报告
"%MAT_HOME%\ParseHeapDump.bat" "dump.hprof" org.eclipse.mat.api:suspects org.eclipse.mat.api:top_components org.eclipse.mat.api:overview
报告输出为 ZIP 文件(含 HTML),位于 Dump 文件同目录。
:: 打开 MAT 并加载 Dump 文件
"%MAT_HOME%\MemoryAnalyzer.exe" "dump.hprof"
编辑 %MAT_HOME%\MemoryAnalyzer.ini:
-vmargs
-Xmx8g
-XX:+UseG1GC
-XX:MaxMetaspaceSize=512m
分析大于 4GB 的 Dump 文件时,建议将 MAT 内存调至 Dump 文件大小的 1.2~1.5 倍。
下载地址:https://eclipse.dev/mat/download/
选择 Stand-alone 版本(免安装),解压到任意目录即可。
解压后设置环境变量:set MAT_HOME=<你的解压路径>
执行诊断命令(jmap、jstack、jcmd 等)前,需要使用与目标进程相同或兼容版本的 JDK。按以下优先级检测:
jcmd <PID> VM.version 或 jinfo -sysprops <PID> | findstr java.version 获取JAVA_HOME:当前系统默认 JDK按以下路径自动扫描已安装的 JDK(Windows):
:: 常见 JDK 安装路径模式
C:\Program Files\Java\jdk-<VERSION>
C:\Program Files\Java\jdk<VERSION>
C:\Program Files\Eclipse Adoptium\jdk-<VERSION>*
C:\Program Files\Microsoft\jdk-<VERSION>*
C:\Program Files\Zulu\zulu-<VERSION>*
C:\Program Files\Amazon Corretto\jdk<VERSION>*
C:\Program Files\BellSoft\LibericaJDK-<VERSION>*
D:\Java\jdk-<VERSION>
D:\dev\jdk\jdk-<VERSION>
E:\Java\jdk-<VERSION>
Linux/macOS:
/usr/lib/jvm/java-<VERSION>-*
/usr/local/java/jdk-<VERSION>
/Library/Java/JavaVirtualMachines/jdk-<VERSION>*/Contents/Home
~/.sdkman/candidates/java/<VERSION>*
@echo off
:: detect-jdk.bat - 检测系统中所有已安装的 JDK
echo ═══════════════════════════════════════════
echo JDK 版本检测
echo ═══════════════════════════════════════════
:: 1. 检查 JAVA_HOME
if defined JAVA_HOME (
echo [JAVA_HOME] %JAVA_HOME%
"%JAVA_HOME%\bin\java" -version 2>&1 | findstr /i "version"
)
:: 2. 扫描常见路径
set "SEARCH_PATHS=C:\Program Files\Java;C:\Program Files\Eclipse Adoptium;C:\Program Files\Microsoft;C:\Program Files\Amazon Corretto;D:\Java;E:\Java"
for %%d in ("%SEARCH_PATHS:;=" "%") do (
if exist "%%~d" (
for /d %%j in ("%%~d\jdk*") do (
if exist "%%~j\bin\java.exe" (
echo [FOUND] %%~j
"%%~j\bin\java" -version 2>&1 | findstr /i "version"
)
)
)
)
echo ═══════════════════════════════════════════
| 工具/特性 | JDK 8 | JDK 11 | JDK 15 | JDK 17 | JDK 21 | JDK 25 |
|---|---|---|---|---|---|---|
| jmap -heap | ✅ | ❌ (移除) | ❌ | ❌ | ❌ | ❌ |
| jmap -dump | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| jcmd GC.heap_dump | ✅ | ✅(推荐) | ✅(推荐) | ✅(推荐) | ✅(推荐) | ✅(推荐) |
| jcmd GC.heap_info | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| jcmd VM.native_memory | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| jcmd Thread.dump_to_file | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| jcmd VM.classloader_stats | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| jhat | ✅ | ❌ (移除) | ❌ | ❌ | ❌ | ❌ |
| jhsdb | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| jfr (内置) | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| GC 日志格式 | -XX:+PrintGCDetails | -Xlog:gc* | -Xlog:gc* | -Xlog:gc* | -Xlog:gc* | -Xlog:gc* |
| PermGen | ✅ | ❌ (Metaspace) | ❌ | ❌ | ❌ | ❌ |
| ZGC | ❌ | ✅ (实验) | ✅ | ✅ (产品级) | ✅ (分代) | ✅ (分代) |
| Shenandoah GC | ❌ | ✅ (部分发行版) | ✅ | ✅ | ✅ | ✅ |
| Virtual Threads | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
执行诊断命令时,根据目标 JDK 版本自动选择正确的命令:
:: JDK 8
jmap -dump:format=b,file=dump.hprof <PID>
:: JDK 11+ (推荐 jcmd,无需与目标进程 attach)
jcmd <PID> GC.heap_dump dump.hprof
:: JDK 11+ 使用 jhsdb(目标进程已崩溃时)
jhsdb jmap --binaryheap --pid <PID>
:: JDK 8(jmap -heap 在 JDK 9+ 已移除)
jmap -heap <PID>
:: JDK 11+(替代方案)
jcmd <PID> GC.heap_info
:: JDK 11+ 使用 jhsdb
jhsdb jmap --heap --pid <PID>
:: 所有版本通用
jstack -l <PID>
:: JDK 11+
jcmd <PID> Thread.print
:: JDK 17+(输出到文件,支持 JSON 格式)
jcmd <PID> Thread.dump_to_file -format=json thread_dump.json
:: JDK 8
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution
-Xloggc:gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M
:: JDK 11/15/17/21/25(统一日志框架)
-Xlog:gc*,gc+heap=debug,gc+phases=debug:file=gc.log:time,uptime,level,tags:filecount=5,filesize=20m
:: JDK 21/25(ZGC 分代模式)
-XX:+UseZGC -XX:+ZGenerational
-Xlog:gc*,gc+phases=debug:file=gc.log:time,uptime,level,tags
:: 所有版本(需启动时添加参数)
:: 启动参数:-XX:NativeMemoryTracking=detail
jcmd <PID> VM.native_memory detail
:: 对比模式
jcmd <PID> VM.native_memory baseline
:: ... 等待一段时间 ...
jcmd <PID> VM.native_memory detail.diff
:: JDK 8(需商业许可,Oracle JDK)
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
jcmd <PID> JFR.start name=recording duration=60s filename=record.jfr
:: JDK 11+(免费开放,推荐)
jcmd <PID> JFR.start name=recording duration=60s filename=record.jfr settings=profile
:: 持续记录(用于事后分析)
jcmd <PID> JFR.start name=continuous maxage=1h maxsize=500m disk=true
jcmd <PID> JFR.dump name=continuous filename=dump.jfr
| MAT 版本 | 最低 JDK 要求 | 可分析的 Dump JDK 范围 |
|---|---|---|
| MAT 1.8 | JDK 8 | JDK 5 ~ JDK 11 |
| MAT 1.11 | JDK 11 | JDK 5 ~ JDK 15 |
| MAT 1.13 | JDK 11 | JDK 5 ~ JDK 17 |
| MAT 1.14 | JDK 17 | JDK 5 ~ JDK 21 |
| MAT 1.15+ | JDK 17 | JDK 5 ~ JDK 25 |
注意:用高版本 JDK 生成的 Dump 文件需要对应版本的 MAT 才能正确解析。如果 MAT 报 "Unknown HPROF version" 错误,请升级 MAT。
用户请求分析
│
▼
是否指定了 JDK 版本? ──Yes──▶ 使用指定版本
│ No
▼
是否有目标 PID? ──Yes──▶ 检测目标进程 JDK 版本
│ No │
▼ ▼
是否有 Dump 文件? 使用相同或更高版本 JDK
│ Yes
▼
从 Dump 文件信息推断版本
│
▼
使用 JAVA_HOME 或最高可用版本
根据 JDK 版本和应用场景,推荐合适的 GC 收集器:
| 场景 | JDK 8 | JDK 11 | JDK 17 | JDK 21/25 |
|---|---|---|---|---|
| 低延迟(<10ms) | CMS | ZGC (实验) | ZGC | ZGC 分代 |
| 大堆(>8GB) | G1 | G1 / ZGC | G1 / ZGC | ZGC 分代 |
| 吞吐优先 | Parallel GC | Parallel GC | G1 | G1 |
| 小堆(<2GB) | Parallel GC | G1 | G1 | G1 |
| 容器环境 | G1 + 手动配置 | G1 (自适应) | G1 (自适应) | G1 / ZGC |
#java-memory-analyzer
帮我分析这个 Heap Dump 文件:D:/dumps/app-20250609.hprof,看看有没有内存泄漏
#java-memory-analyzer
分析这个 Thread Dump,看看有没有死锁:D:/logs/thread-dump-20250609.txt
#java-memory-analyzer
分析 GC 日志,给我调优建议:D:/logs/gc.log
#java-memory-analyzer
线上 OOM 了,帮我做完整的根因分析,Dump 文件在 /data/dumps/oom-2025-06-09.hprof
#java-memory-analyzer
帮我对比两次 Dump 的差异,看看哪些对象在增长:
第一次:D:/dumps/before.hprof
第二次:D:/dumps/after.hprof
#java-memory-analyzer
PID 12345 疑似内存泄漏,帮我采集信息并分析
从用户消息中提取:
:: 检查文件是否存在及大小
dir "<DUMP文件路径>"
:: 检查文件头魔数(HPROF 文件以 "JAVA PROFILE" 开头)
powershell -Command "Get-Content '<DUMP文件路径>' -TotalCount 1 -Encoding Byte | Format-Hex | Select-Object -First 1"
:: 生成 Leak Suspects 报告(最重要)
"%MAT_HOME%\ParseHeapDump.bat" "<DUMP文件路径>" org.eclipse.mat.api:suspects
:: 生成 Top Components 报告
"%MAT_HOME%\ParseHeapDump.bat" "<DUMP文件路径>" org.eclipse.mat.api:top_components
解压生成的 ZIP 报告文件,读取 HTML 内容,提取以下关键信息:
Leak Suspects(泄漏嫌疑):
Dominator Tree(支配树):
Top Components(大对象):
对可疑对象做进一步精确查询:
-- 查找大于 1MB 的 byte[] 对象
SELECT * FROM byte[] s WHERE s.@retainedHeapSize > 1048576
-- 查找所有 HashMap 中 entry 数量大于 10000 的
SELECT m, m.size FROM java.util.HashMap m WHERE m.size > 10000
-- 查找指定类的所有实例
SELECT * FROM com.example.service.OrderCache
-- 查找所有到 GC Root 的路径
SELECT * FROM OBJECTS (SELECT referenceChain FROM java.lang.ref.Finalizer)
-- 查找重复 String
SELECT toString(s), count(s) FROM java.lang.String s GROUP BY toString(s) HAVING count(s) > 100
═══════════════════════════════════════════════════════════════
📊 Java Heap Dump 分析报告
═══════════════════════════════════════════════════════════════
📁 文件:<文件名>
📏 大小:<文件大小>
🕐 分析时间:<时间>
🔧 工具:Eclipse MAT (ParseHeapDump)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 问题总结
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
严重程度:🔴 高危 / 🟡 中等 / 🟢 低
问题类型:内存泄漏 / 大对象 / 集合浪费 / ...
根因定位:<具体类名和引用链>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔍 详细分析
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【泄漏嫌疑 #1】
├── 对象:com.example.cache.UserSessionCache
├── Retained Heap:1.2 GB(占总堆 60%)
├── 实例数:820,000 个 UserSession 对象
├── GC Root 链:
│ System Class Loader
│ └── com.example.AppContext (static field)
│ └── sessionManager (field)
│ └── ConcurrentHashMap (entries: 820,000)
│ └── UserSession (每个约 1.5KB)
└── 问题分析:Session 对象只增不减,没有过期清理机制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 修复建议
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. [紧急] 添加 Session TTL 过期清理机制
2. [建议] 使用 WeakReference 或 SoftReference 缓存
3. [优化] 减少 UserSession 对象大小,移除冗余字段
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 JVM 调优参数建议
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-Xmx4g -Xms4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200
═══════════════════════════════════════════════════════════════
type "<ThreadDump文件路径>"
解析所有线程状态,汇总统计:
搜索 Found one Java-level deadlock 关键字,或手动分析锁等待链:
═══════════════════════════════════════════════════════════════
🧵 Thread Dump 分析报告
═══════════════════════════════════════════════════════════════
📁 文件:<文件名>
🕐 Dump 时间:<时间>
🧮 线程总数:<N> 个
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 线程状态分布
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
RUNNABLE: 45 (30%) ████████████
BLOCKED: 12 (8%) ████
WAITING: 58 (39%) ████████████████
TIMED_WAITING: 35 (23%) █████████
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 死锁检测
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[检测结果]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔥 锁竞争热点
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[竞争分析]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 优化建议
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[建议列表]
═══════════════════════════════════════════════════════════════
支持以下格式:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log-Xlog:gc*:file=gc.log:time,uptime,level,tags根据 GC 日志分析结果,给出具体的 JVM 参数调优建议,包含:
⚠️ 执行在线诊断命令前,先检测目标进程的 JDK 版本,参考上方「版本适配命令映射」章节选择正确的命令。
:: 方式 1:通过 jcmd 获取版本信息
jcmd <PID> VM.version
:: 方式 2:通过 jinfo 获取
jinfo -sysprops <PID> 2>&1 | findstr "java.version"
:: 方式 3:查看进程启动命令中的 java 路径
wmic process where "ProcessId=<PID>" get CommandLine
:: JDK 8(jmap 方式)
jmap -dump:format=b,file=heap_dump.hprof <PID>
:: JDK 11+(推荐 jcmd,更安全、不需要 SA attach)
jcmd <PID> GC.heap_dump heap_dump.hprof
:: JDK 11+(jhsdb 方式,进程已挂起时使用)
jhsdb jmap --binaryheap --dumpfile heap_dump.hprof --pid <PID>
:: 仅 Dump 存活对象(触发一次 Full GC)
jmap -dump:live,format=b,file=heap_dump_live.hprof <PID>
:: 所有版本通用
jstack -l <PID> > thread_dump.txt
:: JDK 11+
jcmd <PID> Thread.print > thread_dump.txt
:: JDK 17+(支持 JSON 格式输出,含 Virtual Threads)
jcmd <PID> Thread.dump_to_file -format=json thread_dump.json
:: 多次采集(间隔 3 秒,采 3 次,用于对比)
for /L %i in (1,1,3) do (jstack -l <PID> > thread_dump_%i.txt & timeout /t 3)
:: 每秒输出一次 GC 统计(共 10 次)— 所有版本
jstat -gcutil <PID> 1000 10
:: 查看各代容量和使用量
jstat -gc <PID> 1000 5
:: JDK 11+(查看堆信息,替代 jmap -heap)
jcmd <PID> GC.heap_info
:: 查看所有 JVM 参数
jcmd <PID> VM.flags
:: 查看系统属性
jcmd <PID> VM.system_properties
:: 查看命令行参数
jcmd <PID> VM.command_line
:: JDK 11+(查看类加载器统计,排查 Metaspace 泄漏)
jcmd <PID> VM.classloader_stats
:: 前提:JVM 启动时加上 -XX:NativeMemoryTracking=detail(所有版本)
jcmd <PID> VM.native_memory detail
:: 设置 baseline 并对比
jcmd <PID> VM.native_memory baseline
:: ... 等待一段时间 ...
jcmd <PID> VM.native_memory detail.diff
:: 启动 60 秒录制
jcmd <PID> JFR.start name=diagnosis duration=60s filename=diagnosis.jfr settings=profile
:: 持续录制(事后 dump)
jcmd <PID> JFR.start name=continuous maxage=1h maxsize=500m disk=true
jcmd <PID> JFR.dump name=continuous filename=dump.jfr
:: 查看正在进行的录制
jcmd <PID> JFR.check
"%MAT_HOME%\ParseHeapDump.bat" "<DUMP1路径>" org.eclipse.mat.api:suspects
"%MAT_HOME%\ParseHeapDump.bat" "<DUMP2路径>" org.eclipse.mat.api:suspects
提取两次 Dump 中各类的实例数和内存占用,计算增量:
═══════════════════════════════════════════════════════════════
📊 Heap Dump 对比分析
═══════════════════════════════════════════════════════════════
时间差:<两次 Dump 间隔>
总堆增长:+512 MB(1.2GB → 1.7GB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 增长 Top 10 类
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| 排名 | 类名 | 增量实例 | 增量内存 |
|------|-----------------------------------|---------|----------|
| 1 | com.example.dto.OrderSnapshot | +120000 | +180 MB |
| 2 | byte[] | +85000 | +95 MB |
| 3 | java.lang.String | +90000 | +72 MB |
| ... | ... | ... | ... |
═══════════════════════════════════════════════════════════════
原因:堆内存不足(对象太多或太大) 诊断步骤:
原因:类元数据区满(动态代理、反射生成类过多) 诊断步骤:
jcmd <PID> VM.classloader_stats 查看类加载器统计原因:线程数达到 OS 限制 诊断步骤:
ulimit -u / nproc 限制原因:堆外直接内存不足(Netty、NIO) 诊断步骤:
-XX:MaxDirectMemorySize 设置原因:GC 耗时超过 98% 但回收不到 2% 内存 诊断步骤:
-- 查找最大的 10 个对象
SELECT * FROM INSTANCEOF java.lang.Object ORDER BY @retainedHeapSize DESC LIMIT 10
-- 查找所有线程的线程名和状态
SELECT t.name.toString(), t.threadStatus FROM java.lang.Thread t
-- 查找指定大小以上的 byte[]
SELECT s, s.@length, s.@retainedHeapSize FROM byte[] s WHERE s.@length > 1048576
-- 查找 HashMap 中 Entry 最多的实例
SELECT m, m.size FROM java.util.HashMap m WHERE m.size > 5000 ORDER BY m.size DESC
-- 查找所有 JDBC Connection
SELECT * FROM INSTANCEOF java.sql.Connection
-- 查找所有 ClassLoader 及其加载的类数量
SELECT cl, cl.@objectId FROM INSTANCEOF java.lang.ClassLoader cl
-- 查找所有未关闭的文件流
SELECT * FROM INSTANCEOF java.io.FileInputStream
-- 查找 Spring Bean 定义
SELECT * FROM INSTANCEOF org.springframework.beans.factory.config.BeanDefinition
@echo off
:: batch-analyze.bat - 批量分析多个 Dump 文件
:: 依赖环境变量 MAT_HOME,使用前请确保已设置
if not defined MAT_HOME (
echo [ERROR] MAT_HOME is not set. Please set it to your MAT installation directory.
exit /b 1
)
set DUMP_DIR=%1
for %%f in ("%DUMP_DIR%\*.hprof") do (
echo Analyzing: %%f
"%MAT_HOME%\ParseHeapDump.bat" "%%f" org.eclipse.mat.api:suspects org.eclipse.mat.api:top_components
echo Done: %%f
)
echo All dumps analyzed.
# K8s 环境采集 Heap Dump
kubectl exec <pod-name> -c <container> -- jcmd 1 GC.heap_dump /tmp/dump.hprof
kubectl cp <pod-name>:/tmp/dump.hprof ./dump.hprof -c <container>
# Docker 环境
docker exec <container-id> jcmd 1 GC.heap_dump /tmp/dump.hprof
docker cp <container-id>:/tmp/dump.hprof ./dump.hprof
-Dfile.encoding=UTF-8