如何使用jmap命令导出内存快照并分析大对象的占用链

轻强同学_5830

轻强同学_5830

2026-04-04

1001人浏览

原创

必须用 jmap -dump:format=b,file=路径.pid 导出内存快照,-histo 和 -finalizerinfo 无法分析对象引用链;导出后须用 MAT 查 Dominator Tree 和 Path to GC Roots 定位泄漏根因。

如何使用jmap命令导出内存快照并分析大对象的占用链

导出内存快照必须用 -dump,别碰 -histo 或 -finalizerinfo

很多人误以为 jmap -histo 能查大对象引用链,其实它只统计类实例数量和浅堆大小,完全不包含对象间的引用关系。真正能用于分析“谁持有了大对象”的,只有 jmap -dump 生成的 .hprof 文件。

正确命令是:

jmap -dump:format=b,file=/tmp/heap.hprof <pid></pid>

注意几个关键点:

  • format=b 是必须的,表示二进制格式;省略会失败或输出无效内容
  • 路径要有写权限,/tmp 最稳妥;不要写成 ./heap.hprof(可能因 JVM 工作目录不可写而静默失败)
  • JDK 8 及以前默认使用 Serial GC 时,该命令会触发 Full GC;JDK 11+ 的 ZGC/Shenandoah 下仍可工作,但部分老版本 ZGC 不支持 —— 若卡住无响应,先 jstat -gc 确认 GC 类型
  • 生产环境慎用:导出过程会暂停应用(STW),10GB 堆可能停顿 20 秒以上

jmap -dump 后必须用 MAT 或 JProfiler 打开,jhat 已淘汰且不支持引用链深度分析

jhat 虽然能启动 Web 页面查看堆,但它无法计算“支配树(Dominator Tree)”,也查不出某个 byte[] 是被哪个 HashMap、再被哪个 CacheService 持有 —— 这正是定位内存泄漏的关键路径。

推荐直接用 Eclipse MAT(Memory Analyzer Tool):

  • 下载 standalone 版(无需 Eclipse IDE),解压即用
  • 打开 heap.hprof 后,点 “Dominator Tree” 视图,默认按“Retained Heap”倒序排列,顶部就是最可疑的大对象组
  • 右键任意对象 → “Path to GC Roots” → 勾选 “with all references”,就能看到完整持有链(注意:若显示 “not all paths found”,说明对象已被回收或 dump 时已不可达)
  • 如果对象是 char[] 或 byte[],MAT 会自动关联到其字符串内容(需开启 “Parse String Values” 选项)

分析时重点看 “Retained Heap” 而非 “Shallow Heap”,否则会漏掉间接引用膨胀

比如一个 ConcurrentHashMap 实例本身 Shallow Heap 只有 80 字节,但它存了 5 万个 ResponseDTO,每个 DTO 持有一个 1MB 的 byte[] —— 此时它的 Retained Heap 接近 50GB。只看 Shallow Heap 会完全错过这个根因。

MAT 中容易忽略的细节:

  • “Group by Package” 或 “Group by Class Loader” 能快速识别第三方组件是否异常囤积对象(比如某 SDK 的静态缓存没清理)
  • “Leak Suspects Report” 自动报告不一定准,尤其在多模块共用线程池场景下,得人工交叉验证 “Path to GC Roots” 和代码逻辑
  • 如果发现大量 java.lang.ref.Finalizer 占用 Retained Heap,不是 Finalizer 队列本身大,而是它背后挂了一堆待销毁资源 —— 此时要查 finalize() 方法里是否持有大缓冲区

线上不能跑 MAT?用 jcmd + jdk.jfr 替代 jmap 做轻量级采样

有些容器环境禁止 jmap(如 OpenShift 默认禁用 ptrace),或堆太大导出失败。这时可用 JDK 自带的飞行记录器做低开销采样:

jcmd <pid> VM.native_memory summary scale=MB<br>jcmd <pid> VM.native_memory detail scale=MB</pid></pid>

更进一步,启用堆分配采样(JDK 11+):

jcmd <pid> VM.native_memory summary scale=MB<br>jcmd <pid> VM.unlock_commercial_features<br>jcmd <pid> VM.native_memory summary scale=MB</pid></pid></pid>

不过真正替代 jmap -dump 的是:

jcmd <pid> VM.native_memory summary scale=MB<br>jcmd <pid> VM.unlock_commercial_features<br>jcmd <pid> VM.native_memory summary scale=MB</pid></pid></pid>

实际建议组合使用:

  • 先用 jstat -gc 看老年代增长趋势
  • 再用 jcmd VM.native_memory summary 判断是否为 native 内存问题(如 Netty Direct Buffer 泄漏)
  • 确认是 Java 堆后,才用 jmap -dump;若不可行,改用 jcmd VM.native_memory summary + jstack 交叉分析线程局部缓存行为

大对象占用链的根因往往藏在“看似合理”的缓存逻辑里,比如用了 WeakReference 却忘了清除 key,或者 ThreadLocal 在线程池中长期存活 —— 这些在 MAT 的 “Path to GC Roots” 里会暴露得非常直白,但前提是 dump 文件本身得真实反映那一刻的引用状态。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

60

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

40

15

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

2026.10.28

120

10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

140

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

120

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

80

15

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

2026.10.22

40

10

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

2026.10.22

80

25

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

2026.10.22

40

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习