在排查 Java 应用运行缓慢、内存占用高这类问题时,堆内存 dump 是个实用的工具。它能记录某一时刻 JVM 堆中所有对象的状态,帮助我们分析内存使用情况,找出潜在的内存泄漏或大对象占用。
什么时候需要生成堆 dump
比如你部署了一个后台服务,发现服务器内存一路飙升,重启后又慢慢上来,这时候光看日志可能看不出什么。通过生成堆 dump 文件,就能用工具(如 Eclipse MAT、VisualVM)打开分析,看看是哪些对象一直在堆积。
使用 jmap 命令生成 dump
最常用的方法是 JDK 自带的 jmap 工具。假设你的 Java 进程 PID 是 12345,可以在终端执行:
jmap -dump:format=b,file=heap.hprof 12345
这条命令会把当前堆内存快照写入当前目录下的 heap.hprof 文件。文件大小通常和堆使用量成正比,几百 MB 到几个 GB 都有可能,注意磁盘空间。
通过 JMX 远程触发
如果应用跑在内网服务器上,不能直接登录操作,可以通过 JMX 方式远程连接。先确保启动 Java 程序时开启了 JMX 支持:
java -Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-jar your-app.jar
然后在本地用 VisualVM 或 JConsole 连接上去,找到“堆 Dump”按钮一点就行。这种方式适合调试线上环境的问题,尤其是配合内网穿透工具暴露 JMX 端口的时候。
代码中主动触发 dump
有时候你想在特定条件下自动生成 dump,比如某个接口调用后怀疑有内存泄漏,可以在代码里加个临时逻辑:
import java.lang.management.ManagementFactory;
import com.sun.management.HotSpotDiagnosticMXBean;
public class HeapDumper {
private static final String HOTSPOT_BEAN_NAME =
"com.sun.management:type=HotSpotDiagnostic";
public static void dumpHeap(String filePath) {
try {
HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
ManagementFactory.getPlatformMBeanServer(),
HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap(filePath, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
调用 HeapDumper.dumpHeap("/tmp/heap.hprof") 就能生成文件。上线前记得删掉这类代码,避免被误用。
小技巧:设置 OOM 时自动导出
如果问题是出现在内存溢出(OutOfMemoryError)时,可以提前加参数让 JVM 自动保存 dump:
java -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/data/dumps \
-jar app.jar
这样一旦发生 OOM,JVM 会自动把堆信息写进去指定目录,省得错过时机。
生成 dump 只是第一步,后续还得用分析工具打开看具体对象分布。不过对于定位内存问题来说,这一步已经迈出了最关键的那一下。