是否可以创建堆转储来分析内存泄漏而不进行垃圾回收?

2022-09-02 05:30:28

我们在运行Java应用程序的生产VM上遇到了一些内存泄漏问题,旧一代堆的使用量每天都在快速增长,因此我想创建堆转储来分析它。

但是,我注意到 VisualVM 将在堆转储之前执行完整的 GC,这将清理旧一代,在这种情况下,堆转储将毫无用处。

我还尝试使用以下命令:

jmap -dump:live,format=b,file=heap.bin

它还将触发完整的 GC。

我是否可以问一下,是否有一种方法可以在没有完整GC(或没有GC)的情况下创建堆转储?或者有没有更好的方法来分析内存泄漏?

JDK 版本: 1.7.0_45

谢谢。


答案 1

标记为正确的答案不再正确。正如Sumit所说,只有当使用live选项时(在histo和转储操作中),它才会产生完整的GC。

Java 7Java 8 具有此选项

-历史[:生活]

打印堆的直方图。对于每个 Java 类,将打印对象数、内存大小(以字节为单位)和完全限定的类名。JVM 内部类名打印有星号 (*) 前缀。如果指定了活动子选项,则仅对活动对象进行计数。


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

将 hprof 二进制格式的 Java 堆转储为文件名。活动子选项是可选的,但在指定时,仅转储堆中的活动对象。要浏览堆转储, 您可以使用 jhat(1) 命令来读取生成的文件。

您可以将 jcmd 命令与操作和选项一起使用GC.heap_dump-all

GC.heap_dump

生成 Java 堆的 HPROF 格式转储。

影响:高:取决于 Java 堆大小和内容。请求完整的 GC,除非指定了“-all”选项。

Permission: java.lang.management.ManagementPermission(monitor)

语法 : GC.heap_dump [选项]

参数:

  • 文件名:转储文件的名称(字符串,无默认值)

选项:(必须使用 or = 语法指定选项)

  • -all : [可选] 转储所有对象,包括无法访问的对象(布尔值,false)

例:jcmd 3181 GC.heap_dump -all dump

您可以添加标志以查看完整 GC 是否正在 hapenning。例如,当我使用没有 -all 的 jcmd 时,我会看到类似这样的东西。-XX:+PrintGCDetails

200,658: [完整 GC (堆转储启动的 GC) 200,658: [CMS: 5040K->4158K(18432K), 0,0171885 秒] 11239K->4158K(25856K), [元空间: 18053K->18053K(1064960K)], 0,0173941 秒] [次: user=0,01 sys=0,00, real=0,02 秒]


答案 2

您可以使用 JMX Bean HotSpotDiagnostic 和方法的第二个参数设置为 false 来触发 HeapDump。

有关更详细的响应,请参阅此答案:https://stackoverflow.com/a/35575793/236528


推荐