jvm heap dump的7种方式

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,也可以对转储的文件进行分析。

Heapdump1

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)

Heap2

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上运行,则可以使用管理控制台来生成堆。步骤;

  1. 启动管理控制台
  2. 在导航窗格中,单击故障排除> Java转储和核心
  3. 选择要为其生成堆转储的server_name
  4. 单击“堆转储”以生成指定服务器的堆转储。
  5. 您还可以使用wsadmin生成堆转储。

即使本文为您提供了捕获堆转储的多个选项,但前三个选项是业内最常用的选项。

参考:https://dzone.com/articles/how-to-capture-java-heap-dumps-7-options

猜你喜欢

转载自blog.csdn.net/liuxiao723846/article/details/114295862
今日推荐