前言
在 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
|
|
参数说明:
format=b:二进制 hprof 格式,MAT / VisualVM 都可以打开file=/tmp/heap.hprof:输出文件路径<PID>:Java 进程 PIDlive:执行 Full GC,只导出还存活的对象;会触发 STW,线上高峰期谨慎执行。
jcmd
JDK 9 及以上版本推荐使用。JDK 9+ 文档明确:优先 jcmd,替代 jmap/jstack/jinfo。
|
|
JVM 启动参数
OOM 发生时,自动 dump(被动捕获现场,需要重启应用)
|
|
- 触发时机:抛出
java.lang.OutOfMemoryError时 JVM 自动写 hprof - HeapDumpPath 填写目录,则自动生成
java_pid<PID>.hprof - 无需人工值守;适合偶现 OOM,抓崩溃现场
- 必须重启应用才能生效;只有 OOM 才 dump,不能手动随时 dump
Java 代码 API
HotSpotDiagnosticMXBean 是 JDK 提供的用于获取堆转储的 API,仅 HotSpot 可用,非标准 Java API;需要业务代码执行。
|
|
特点:
- 可以做接口,线上 HTTP 接口触发 dump,不用登录服务器
- 依赖
com.sun.*,非标准 API; JDK 9+ 模块化需要开放模块 live=true依然 FullGC、STW;权限需要ManagementPermission("monitor")
第三方工具推荐
注意事项
- 权限问题:
jmap/jcmd必须和 Java 进程使用同一操作系统用户。root 去 dump 普通用户 Java 进程会失败。 - 磁盘空间:hprof 文件大小接近当前堆最大占用,要保证磁盘剩余空间大于堆内存,避免磁盘打满。
- STW:带
live参数会触发 Full GC,堆越大停顿时间越长,高峰期尽量避开 - 容器环境:docker / K8s 中,需要宿主机/容器内 JDK 版本尽量匹配;需要 PID namespace 共享;可以在容器内使用
jmap/jcmd。 - JDK 9 以后,
jmap部分功能逐步迁移到jcmd,高版本 JDK 优先使用jcmd -XX:+HeapDumpOnOutOfMemoryError不会捕获系统 OOM-killer 杀死进程场景,仅 Java 层 OOM 异常