Java 导出 hprof 文件的方式

本文介绍如何导出 hprof 文件

前言

在 Java 应用开发和性能优化中,经常会遇到需要分析堆内存使用情况的需求。堆内存分析工具中,最常用的是 MAT(Memory Analyzer Tool)和 VisualVM。 要使用这两个工具,就需要先生成 hprof 文件。

hprof (Heap Profile):JVM 标准二进制堆转储快照文件,记录某一瞬间 Java 堆内存完整状态,后缀 .hprof,主要用于内存故障排查。

获取 hprof 文件有多种方式,常用的是使用 JDK 自带的工具和第三方工具。但大部分方式都需要提前知晓目标程序的 PID。

获取 PID 的方式有多种,常用的是使用 jps -l 命令,更多方式请参考文章:Java 获取应用 PID

JDK 自带命令行

无需业务代码,运行时手动触发,生产最常用。jmap 是 JDK 1.8 主力,JDK 9+ 推荐使用 jcmd

jmap

1
2
3
4
5
# dump 全部对象(包含待回收垃圾对象,不触发 FullGC)
jmap -dump:format=b,file=/tmp/heap.hprof <PID>

# dump 只存活对象,会 FullGC + STW,文件更小(live)
jmap -dump:live,format=b,file=/tmp/heap-live.hprof <PID>

参数说明:

  • format=b:二进制 hprof 格式,MAT / VisualVM 都可以打开
  • file=/tmp/heap.hprof:输出文件路径
  • <PID>:Java 进程 PID
  • live:执行 Full GC,只导出还存活的对象;会触发 STW,线上高峰期谨慎执行。

jcmd

JDK 9 及以上版本推荐使用。JDK 9+ 文档明确:优先 jcmd,替代 jmap/jstack/jinfo

1
2
3
4
5
# -all:全部对象(不会 FullGC)
jcmd <PID> GC.heap_dump -all /tmp/heap.hprof

# -live:仅存活对象,FullGC + STW
jcmd <PID> GC.heap_dump -live /tmp/heap-live.hprof

JVM 启动参数

OOM 发生时,自动 dump(被动捕获现场,需要重启应用)

1
2
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/dump/heap.hprof
  • 触发时机:抛出 java.lang.OutOfMemoryError 时 JVM 自动写 hprof
  • HeapDumpPath 填写目录,则自动生成 java_pid<PID>.hprof
  • 无需人工值守;适合偶现 OOM,抓崩溃现场
  • 必须重启应用才能生效;只有 OOM 才 dump,不能手动随时 dump

Java 代码 API

HotSpotDiagnosticMXBean 是 JDK 提供的用于获取堆转储的 API,仅 HotSpot 可用,非标准 Java API;需要业务代码执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import com.sun.management.HotSpotDiagnosticMXBean;
import javax.management.MBeanServer;
import java.lang.management.ManagementFactory;

MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
        server,
        "com.sun.management:type=HotSpotDiagnostic",
        HotSpotDiagnosticMXBean.class
);
// 参数:输出文件,live=true代表只dump存活对象(FullGC)
bean.dumpHeap("/tmp/heap-code.hprof", true);

特点:

  • 可以做接口,线上 HTTP 接口触发 dump,不用登录服务器
  • 依赖 com.sun.*,非标准 API; JDK 9+ 模块化需要开放模块
  • live=true 依然 FullGC、STW;权限需要 ManagementPermission("monitor")

第三方工具推荐

注意事项

  1. 权限问题:jmap/jcmd 必须和 Java 进程使用同一操作系统用户。root 去 dump 普通用户 Java 进程会失败。
  2. 磁盘空间:hprof 文件大小接近当前堆最大占用,要保证磁盘剩余空间大于堆内存,避免磁盘打满。
  3. STW:带 live 参数会触发 Full GC,堆越大停顿时间越长,高峰期尽量避开
  4. 容器环境:docker / K8s 中,需要宿主机/容器内 JDK 版本尽量匹配;需要 PID namespace 共享;可以在容器内使用 jmap/jcmd
  5. JDK 9 以后,jmap 部分功能逐步迁移到 jcmd,高版本 JDK 优先使用 jcmd
  6. -XX:+HeapDumpOnOutOfMemoryError 不会捕获系统 OOM-killer 杀死进程场景,仅 Java 层 OOM 异常

如果本文对您有所帮助,欢迎打赏支持作者!

Licensed under CC BY-NC-SA 4.0
最后更新于 2026-08-20 15:38
使用 Hugo 构建
主题 StackJimmy 设计