dump heap是诊断与内存相关的问题的重要手段,例如:内存泄漏、垃圾回收问题和java.lang.OutOfMemoryError。同时也是优化内存消耗的重要手段。有非常多的工具可以dump heap,以及分析转储文件,例如:visualVM、Eclipse MAT和 Heap Hero等等。本文介绍7种dump heap的方式。
1、jmap:
jmap是jdk自带的工具,可以dump heap到文件。例如:
jmap -dump:format=b,file=/opt/tmp/heapdump.bin 37320
注意:可以添加“live”选项,仅将内存中的活动对象写入堆转储文件。如果未通过此选项,则所有对象,即使是准备好进行垃圾回收的对象也会打印在堆转储文件中。它将大大增加堆转储文件的大小。这也将使分析变得乏味。要解决内存问题或优化内存,仅需使用“ live”选项即可。
jmap -dump:live,format=b,file=myjmapfile.txt 19570
2、HeapDumpOnOutOfMemoryError
当应用程序遇到java.lang.OutOfMemoryError时,最好在此时捕获堆转储以诊断问题,因为您想知道java.lang.OutOfMemoryError发生时内存中有哪些对象以及它们占用的内存百分比。但是,大多数情况下IT /运营团队会忘记捕获堆转储。不仅如此,他们还重新启动了应用程序。如果不及时捕获堆转储,就很难诊断出任何内存问题。这就是该选项非常方便的地方。在应用程序启动期间传递“ -XX:+ HeapDumpOnOutOfMemoryError”系统属性时,JVM会在JVM遇到OutOfMemoryError时立即捕获堆转储。
例如:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tmp/heapdump.bin
E-Creativity最佳实践:始终保持在所有应用程序中配置此属性,因为您永远不知道何时会发生OutOfMemoryError。
3、jcmd
jcmd也是jdk自带的工具,可以过jcmd命令发送诊断(diagnostic)命令到JVM.
jcmd 37320 GC.heap_dump /opt/tmp/heapdump.bin
4、JVisualVM
jvisualVM也是jdk自带的一个工具,JVisualVM是一个比较全面的问题诊断工具,可以用来dump heap,也可以对转储的文件进行分析。
5、JMX
com.sun.management:type=HotSpotDiagnostic MBean 这个MBean具有“ dumpHeap”操作,调用此操作将捕获堆转储。 “ dumpHeap”操作采用两个输入参数:
- outputFile:应将堆转储写入的文件路径
- live: true时,仅捕获堆中的活跃对象
您可以使用JMX客户端(例如JConsole,jmxsh,Java Mission Control)来调用此MBean操作。如下图是使用JMC(java Mission Control)

6、通过编程的方式获取
通过调用com.sun.management:type=HotSpotDiagnostic MBean 来在代码中dump heap。虽然我们通常是使用jmap的方式dump heap,但是通过编程方式从应用程序中转储堆,可以实现在不同的时间点从应用程序中转储多个堆快照,然后使用jhat离线分析这些快照。代码如下:
import javax.management.MBeanServer;
import java.lang.management.ManagementFactory;
import com.sun.management.HotSpotDiagnosticMXBean;
public class HeapDumper {
// This is the name of the HotSpot Diagnostic MBean
private static final String HOTSPOT_BEAN_NAME =
"com.sun.management:type=HotSpotDiagnostic";
// field to store the hotspot diagnostic MBean
private static volatile HotSpotDiagnosticMXBean hotspotMBean;
/\*\*
\* Call this method from your application whenever you
\* want to dump the heap snapshot into a file.
\*
\* @param fileName name of the heap dump file
\* @param live flag that tells whether to dump
\* only the live objects
\*/
static void dumpHeap(String fileName, boolean live) {
// initialize hotspot diagnostic MBean
initHotspotMBean();
try {
hotspotMBean.dumpHeap(fileName, live);
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
// initialize the hotspot diagnostic MBean field
private static void initHotspotMBean() {
if (hotspotMBean == null) {
synchronized (HeapDumper.class) {
if (hotspotMBean == null) {
hotspotMBean = getHotspotMBean();
}
}
}
}
// get the hotspot diagnostic MBean from the
// platform MBean server
private static HotSpotDiagnosticMXBean getHotspotMBean() {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean bean =
ManagementFactory.newPlatformMXBeanProxy(server,
HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
return bean;
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
public static void main(String[] args) {
// default heap dump file name
String fileName = "heap.bin";
// by default dump only the live objects
boolean live = true;
// simple command line options
switch (args.length) {
case 2:
live = args[1].equals("true");
case 1:
fileName = args[0];
}
// dump the heap
dumpHeap(fileName, live);
}
}
说明:虽然可以从应用程序中转储多个堆快照,但不能将多个转储中的对象关联起来。 jmap工具使用对象地址作为对象标识符-在垃圾回收之间有所不同[请注意,GC可能会移动更改对象地址的对象]。但是,您可以通过汇总统计数据(例如直方图等)进行关联。
参考:https://blogs.oracle.com/sundararajan/programmatically-dumping-heap-from-java-applications
7、IBM Administrative Console
如果您的应用程序在IBM Websphere Application Server上运行,则可以使用管理控制台来生成堆。步骤;
- 启动管理控制台
- 在导航窗格中,单击故障排除> Java转储和核心
- 选择要为其生成堆转储的server_name
- 单击“堆转储”以生成指定服务器的堆转储。
- 您还可以使用wsadmin生成堆转储。
即使本文为您提供了捕获堆转储的多个选项,但前三个选项是业内最常用的选项。
参考:https://dzone.com/articles/how-to-capture-java-heap-dumps-7-options