📜  如何生成 JVM 堆内存转储?

📅  最后修改于: 2022-05-13 01:54:35.766000             🧑  作者: Mango

如何生成 JVM 堆内存转储?

Java堆转储是在某个时间点存在于 JVM( Java虚拟机)中的所有Java对象的快照。 JVM 为堆内存中的类实例或数组的对象分配内存。当不再需要或不再引用这些对象时,垃圾收集器会运行并回收这些对象占用的内存空间。

堆转储采用二进制格式,扩展名为 .hprof 。可以使用 JVisualVM 和 Eclipse MAT(内存分析器工具)等应用程序打开和分析它。我们生成Java内存堆转储来识别内存泄漏等问题并优化应用程序中的内存使用。

方法:

生成Java内存堆转储的不同方式。 JDK 提供了各种用于生成堆转储的工具。这些工具位于JDK主目录下的bin文件夹中。让我们讨论如何生成JVM Heap Dump,如下所示:

  1. 使用 jmap 命令
  2. 在终端上使用 jcmd 命令
  3. 使用 JVisualVM 工具
  4. 识别 HeapDumpOnOutOfMemory
  5. 使用 JMX 控制台
  6. 通过编写程序使用 HotSpotDiagnosticMBean

方法一:使用map命令



jmap 是在 JDK 主目录的 bin 文件夹中运行的命令。它提供有关内存使用情况的统计信息。结构如下:

例子

jmap -dump:[live],format=b,file= 

live:- This parameter is optional. If set, it prints all those objects that 
have active references.

format = b , which means the heap dump file is in binary format. It is not necessary 
to set this parameter.

file = indicates where the heap dump file will be generated.

 :- process id of the java process

现在,为了获取正在运行的Java进程的进程 ID,可以使用以下定义的选项之一:

1.1

jps

我们从安装了 JDK 的 Unix 终端或 Windows 命令提示符键入此命令。它给出了正在运行的Java进程的进程 ID

jps 命令

1.2

ps -eaf| grep java

这给出了所有正在运行的Java进程的进程 ID。它仅适用于 Unix 终端



ps -eaf |Java

1.3在 windows 操作系统中使用任务管理器应用程序。

方法二:在终端上使用 jcmd 命令

此命令发送 一种 请求 JVM 生成堆转储。它的参数之一是 GC.heap_dump。如下图所示:

jcmd  GC.heap_dump 
 - Process id of java process
 - Path where the heap dump is to be generated

jcmd

方法三:使用JVisualVM工具

这是一个打包在 JDK 中的工具。它有助于监视和排除Java应用程序的故障。它具有简单直观的图形用户界面。我们在开始菜单中输入jvisualvm ,或者在Unix下通过命令提示符或终端窗口进入JDK主目录的bin目录,输入jvisualvm

它启动一个Java Visual VM 应用程序。左侧显示当前运行的Java进程。右键单击要生成其堆转储的进程 ID。当我们点击 heap dump 时,它会为选定的进程生成 heap dump。在基本信息下,它显示生成堆转储的文件路径。

方法 4:识别 HeapDumpOnOutOfMemory

当应用程序遇到Java.lang.OutOfMemoryError 时,捕获堆转储是理想的选择。堆转储有助于识别内存中的活动对象及其占用的内存百分比。

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=

在设置此系统属性的情况下运行Java应用程序时,JVM 会在遇到 OutOfMemoryError 时获取堆转储的快照。

方法五: 使用 JMX 控制台



有一个具有堆转储操作的热点诊断 MBean。我们使用jmx客户端(如jconsole)来调用MBean操作。通过 JConsole,我们可以通过指定主机和端口号以及用户名/密码来连接到本地Java进程或远程进程。一旦我们连接到进程 ID,jconsole 应用程序就会打开多个选项卡。概览选项卡显示堆内存使用情况、线程、类、CPU 使用情况

Jconsole – 新连接

Jconsole – MBean 选项卡

方法六:通过编写程序使用HotSpotDiagnosticMBean

我们使用 HotSpotDiagnosticMBean 来调用堆转储操作。我们从 MBean 平台服务器获取 MBean 对象。在下面的示例中,我们使用反射来调用 MBean 对象的heapDump()方法。

例子

Java
// Java Program Invoking heapDump() Method of MBean Object
 
// Importing input output classes
import java.io.*;
 
// Main class
class GFG {
 
    // Custom string passed as input
    private static final String HOTSPOT_BEAN
        = "com.sun.management:type=HotSpotDiagnostic";
 
    // Private member variable of this class
    private static volatile Object hotSpotMBean;
 
    // Invoke this method when heap dump is to be generated
    // @param fileName - name of the heap dump file
    // @param live - indicates if only live objects are to
    // be included in the heap dump
 
    // Method 1
    // To generate heap dumps
    static void generateHeapDump(String fileName,
                                 boolean live)
    {
        initHotspotMBean();
 
        // Try block to check if any exceptions occurs
        try {
 
            Class clazz = Class.forName(
                "com.sun.management.HotSpotDiagnosticMXBean");
            Method m = clazz.getMethod(
                "dumpHeap", String.class, boolean.class);
            m.invoke(hotSpotMBean, fileName, live);
        }
 
        // Catch block handling runtime exceptions
        catch (RuntimeException re) {
            throw re;
        }
        catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }
 
    // Method 2
    private static void initHotspotMBean()
    {
 
        if (hotSpotMBean == null) {
            synchronized (JavaHeapDump.class)
            {
 
                if (hotSpotMBean == null) {
                    hotSpotMBean = getHotSpotMbean();
                }
            }
        }
    }
 
    // Method 3
    // To get the HOtSpotBean from the MBean server
    private static Object getHotSpotMbean()
    {
 
        Object hotspotBean = null;
 
        // Try block tocheck for exceptions
        try {
 
            // Loading using .forName() method
            Class clazz = Class.forName(
                "com.sun.management.HotSpotDiagnosticMXBean");
 
            MBeanServer mbeanServer
                = ManagementFactory
                      .getPlatformMBeanServer();
 
            hotspotBean
                = ManagementFactory.newPlatformMXBeanProxy(
                    mbeanServer, HOTSPOT_BEAN, clazz);
 
            return hotspotBean;
        }
 
        // Catch block 1
        // Handling exceptions if class not found
        catch (ClassNotFoundException e) {
 
            // Printthe exception along with line number
            // using printStackTrace() method
            e.printStackTrace();
        }
 
        // Catch block 2
        // Handling basic I/O exceptions
        catch (IOException e) {
 
            // Printthe exception along with line number
            // using printStackTrace() method
            e.printStackTrace();
        }
 
        return hotspotBean;
    }
 
    // Method 4
    // Main driver method
    public static void main(String[] args)
    {
 
        // File taken as an input
        String fileName
            = "/home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/JavaHeapDumpGenerator/src/heap1.hprof";
 
        // Flag variable set to true
        boolean live = true;
 
        // Switch case
        switch (args.length) {
        case 2:
            live = args[1].equals("true");
        case 1:
            fileName = args[0];
        }
 
        // Calling Method 1 in main() method to
        // generate heap dumps
        generateHeapDump(fileName, live);
    }
}



使用 MAT 进行堆转储分析

  • 现在最后让我们在 JVisualVM 的帮助下分析堆转储文件。
  • 生成堆转储文件后,我们使用 JVisualVM 之类的工具来分析该文件。当您打开堆转储时, Java VisualVM 默认显示摘要视图。 “摘要”视图显示进行堆转储的运行环境和其他系统属性。
  • 在 JvisualVM 中,我们转到File -> Load并选择生成“.hprof 文件”的文件夹位置,下面以图形方式提供帮助,以便对其有一个公平的理解。

堆转储文件分析 - 摘要选项卡

堆转储分析——类选项卡