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

时间:2014-04-30 16:33:31

标签: java memory-leaks garbage-collection

我们在生产中运行Java应用程序的虚拟机上存在一些内存泄漏问题,旧的Gen堆使用量每天都在快速增长,所以我想创建堆转储来分析它。

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

我也尝试使用以下命令:

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

它还会触发一个完整的GC。

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

JDK版本:1.7.0_45

感谢。

4 个答案:

答案 0 :(得分:7)

您可以使用JMX bean HotSpotDiagnostic触发HeapDump,将方法的第二个参数设置为false。

请参阅此答案以获取更详细的回复:https://stackoverflow.com/a/35575793/236528

答案 1 :(得分:6)

要创建堆转储,将有一个完整的GC。从堆中创建类直方图时也是如此。

如果您想分析Full GCs之间的内存泄漏,那么使用Java Profiler(Mission Control,jProfiler等)可能内存分析是您唯一的选择。

请参阅Java Mission Control Heap Profile的此问答。

答案 2 :(得分:5)

标记为正确的答案不再正确。 正如Sumit所说,只有在使用live选项(在histo和dump操作中)时,它才会导致Full GC。

Java 7Java 8拥有此选项

  

-histo [:live]

     

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


  

-转储:[实时,]格式= b,文件=文件名

     

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

您还可以将jcmd命令与操作GC.heap_dump和选项-all

一起使用

GC.heap_dump 生成Java堆的HPROF格式转储。 影响:高:取决于Java堆的大小和内容。除非指定'-all'选项,否则请求完整的GC。

权限:java.lang.management.ManagementPermission(monitor)

语法:GC.heap_dump [选项]

参数:         filename:转储文件的名称(STRING,没有默认值)

选项:(必须使用or =语法指定选项)         -all:[可选]转储所有对象,包括不可达的对象(BOOLEAN,false)

示例:??

您可以添加jcmd 3181 GC.heap_dump -all dump标志以查看Full GC是否正在暂停。 例如,当我在不使用-all的情况下使用jcmd时,会看到类似这样的内容。

  

200,658:[完整GC(堆转储启动的GC)200,658:[CMS:5040K-> 4158K(18432K),0.0171885秒] 11239K-> 4158K(25856K),[Metaspace:18053K-> 18053K(1064960K) ],0,0173941秒] [时间:用户= 0,01 sys = 0,00,实= 0,02秒]

答案 3 :(得分:2)

只需从选项中删除live即可,你应该很好。当你提供" live" jmap的选项。你强迫JVM运行一个完整的GC并捕获那些应该是" live"。 使用jmap -dump:format = b,file = hd.hprof。