我们在生产中运行Java应用程序的虚拟机上存在一些内存泄漏问题,旧的Gen堆使用量每天都在快速增长,所以我想创建堆转储来分析它。
但是,我注意到VisualVM将在堆转储之前执行完整的GC,这将清除旧的Gen,在这种情况下,堆转储将是无用的。
我也尝试使用以下命令:
jmap -dump:live,format = b,file = heap.bin
它还会触发一个完整的GC。
请问是否有一种方法可以在没有完整GC(或没有GC)的情况下创建堆转储?或者有更好的方法来分析内存泄漏吗?
JDK版本:1.7.0_45
感谢。
答案 0 :(得分:7)
您可以使用JMX bean HotSpotDiagnostic触发HeapDump,将方法的第二个参数设置为false。
请参阅此答案以获取更详细的回复:https://stackoverflow.com/a/35575793/236528
答案 1 :(得分:6)
要创建堆转储,将有一个完整的GC。从堆中创建类直方图时也是如此。
如果您想分析Full GCs之间的内存泄漏,那么使用Java Profiler(Mission Control,jProfiler等)可能内存分析是您唯一的选择。
答案 2 :(得分:5)
标记为正确的答案不再正确。 正如Sumit所说,只有在使用live选项(在histo和dump操作中)时,它才会导致Full GC。
-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。