Java最高

通过。开始使用Spring 5和Spring Boot 2学习的春天课程:

>>查看课程

1.介绍

在本文中,我们将展示用Java捕获堆转储的不同方法。

堆转储是某一时刻JVM内存中所有对象的快照。它们对于排除内存泄漏问题和优化Java应用程序中的内存使用非常有用。

堆转储通常以二进制格式hprof文件存储。我们可以使用jhat或JVisualVM等工具打开和分析这些文件。而且,对于Eclipse用户来说,它是非常常用的

在下一节中,我们将介绍多种生成堆转储的工具和方法,并展示它们之间的主要区别。

2.JDK工具

JDK附带了几个以不同方式捕获堆转储的工具。所有这些工具都在箱子文件夹。因此,只要这个目录包含在系统路径中,我们就可以从命令行启动它们。

在下一节中,我们将展示如何使用这些工具来捕获堆转储。

2.1。jmap

jmap是一种打印运行中的JVM中内存统计信息的工具。金宝搏官网188be我们可以将其用于本地或远程进程。

要使用jmap捕获堆转储,我们需要使用转储选择:

jmap您(生活):格式= b,文件= <文件路径> < pid >

除了这个选项,我们还应该指定几个参数:

  • 生活:如果设置,则只打印具有活动引用的对象,并丢弃准备被垃圾收集的对象。可选参数。
  • 格式= b:表示转储文件为二进制格式。如果不设置,结果是相同的
  • 文件:转储文件要写入的文件
  • pid: Java进程id

例如:

jmap您:生活、格式= b,文件= / tmp /转储。hprof 12587

记住,我们可以很容易得到pid的Java进程的jps命令。

记住jmap是作为一个实验性工具引入JDK的,目前不支持它。因此,在某些情况下,使用其他工具可能更可取。

2.2。jcmd

jcmd是一个非常完整的工具,它通过向JVM发送命令请求来工作。我们必须在运行Java进程的同一台机器上使用它。

它的许多命令之一是GC.heap_dump。可以使用它来获得堆转储,只需指定pid进程和输出文件路径:

jcmd < pid > GC。heap_dump <文件路径>

我们可以使用之前使用的参数来执行它:

jcmd 12587 GC。heap_dump / tmp / dump.hprof

与jmap一样,生成的转储是二进制格式的。

2.3。JVisualVM

JVisualVM是一个带有图形用户界面的工具,可以让我们监视、排除故障和配置Java应用程序。GUI很简单,但非常直观,易于使用。

其中一个选项允许我们捕获堆转储。如果我们右键单击Java进程并选择“堆转储”选项,工具将创建一个堆转储,并在一个新的选项卡中打开它:

请注意,我们可以找到在“基本信息”部分。

从JDK 9开始,Visual VM不包含在Oracle JDK和开放JDK发行版中。因此,如果我们使用Java 9或更新的版本,我们可以从VisualVM的开放源代码中获得JVisualVM项目网站

3.自动捕获堆转储

我们在前面几节中展示的所有工具都旨在在特定时间手动捕获堆转储。在某些情况下,我们希望在ajava.lang.OutOfMemoryError这样就可以帮助我们调查错误。

在这些情况下,Java提供了HeapDumpOnOutOfMemoryError一个命令行选项,当java.lang.OutOfMemoryError抛出:

java - xx: + HeapDumpOnOutOfMemoryError

默认情况下,它将转储存储在java_pid < pid > .hprof文件在我们运行应用程序的目录中。如果我们想指定另一个文件或目录,我们可以在HeapDumpPath选择:

java - xx: + HeapDumpOnOutOfMemoryError - xx: HeapDumpPath = < file-or-dir-path >

当我们的应用程序使用这个选项耗尽内存时,我们将能够在日志中看到创建的文件包含堆转储:

java.lang.OutOfMemoryError:请求的数组大小超过虚拟机限制转储堆到java_pid12587。hprof……java.lang.OutOfMemoryError: Requested array size exceeds VM limit at com.baeldung.heapdump.App.main(App.java:7)金宝搏188体育

在上面的例子中,它被写入java_pid12587.hprof文件。

正如我们所看到的,这个选项非常有用使用此选项运行应用程序时没有任何开销。因此,强烈建议始终使用此选项,特别是在生产环境中。

最后,也可以在运行时使用HotSpotDiagnosticMBean。为此,我们可以使用JConsole并设置HeapDumpOnOutOfMemoryErrorVM选项真正的:

我们可以在这里找到更多关于mbean和JMX的信息金宝搏官网188be文章

4.JMX

本文将介绍的最后一种方法是使用JMX。我们将使用HotSpotDiagnosticMBean我们在上一节简要介绍过的。这个MBean提供了一个dumpHeap方法它接受两个参数:

  • outputFile:转储文件的路径。该文件应该具有hprof扩展名
  • 生活:如果设置为true,则只转储内存中的活动对象,就像我们之前在使用jmap时看到的那样

在下一节中,我们将展示调用该方法以捕获堆转储的两种不同方法。

4.1。JConsole

最简单的使用方法HotSpotDiagnosticMBean是通过使用JMX客户机(如JConsole)来实现的。

如果我们开放JConsole并连接到正在运行的Java进程,我们可以导航到mbean选项卡并找到HotSpotDiagnosticcom.sun.management在操作中,我们可以找到dumpHeap我们之前描述过的方法:

如图所示,我们只需要引入参数outputFile生活p0p1文本字段,以执行dumpHeap操作。

4.2。程序化的方法

另一种使用HotSpotDiagnosticMBean是通过从Java代码以编程方式调用它来实现的。

要做到这一点,我们首先需要MBeanServer实例,以获得在应用程序中注册的MBean。在那之后,我们只需要获取HotSpotDiagnosticMXBean和调用它的dumpHeap方法

让我们看一下代码:

public static void dumpHeap(String filePath, boolean live) throws IOException {MBeanServer server = ManagementFactory.getPlatformMBeanServer();HotSpotDiagnosticMXBean mxBean = ManagementFactory。com.sun newPlatformMXBeanProxy(服务器。”管理:type = HotSpotDiagnostic ", HotSpotDiagnosticMXBean.class);mxBean。转储Heap(filePath, live); }

注意,hprof文件不能被覆盖。因此,在创建打印堆转储的应用程序时,我们应该考虑到这一点。如果没有这样做,就会得到一个异常:

异常的线程“主要”java.io.IOException: sun.management.HotSpotDiagnostic文件存在。在sun.management. hotspotdiagnostic . dumpHeap0(本机方法)

5.结论

在本教程中,我们展示了用Java捕获堆转储的多种方法。

作为一个经验法则,我们应该记住使用HeapDumpOnOutOfMemoryError在运行Java应用程序时始终选择。对于其他用途,只要我们记住jmap不受支持的状态,其他任何工具都可以很好地使用。

与往常一样,示例的完整源代码是可用的在GitHub

Java底部

通过。开始使用Spring 5和Spring Boot 2学习的春天课程:

>>查看课程
本文评论关闭!