堆堆分析后的Java堆转储和堆大小不同

时间:2016-12-12 14:36:06

标签: java eclipse memory-leaks jvm heap-dump

我遇到内存泄漏,这里有一些细节。

At the time of after-leak, 
   - top shows 50GB memory as residential
   - heap dump file size is 25GB
   - eclipse MAT analyzer tells me the heap size is 10GB

At the time of before-leak, 
   - top shows 30GB memory as residential
   - heap dump file size is 20GB
   - eclipse MAT analyzer tells me the heap size is 10GB

我很惊讶top,dump-dump大小和实际堆大小之间的差异。 我猜测顶部和堆之间的区别是垃圾收集器堆和本机堆区域的可能性。 但是,为什么堆转储文件大小和实际堆大小(来自eclipse MAT分析器)可能会有所不同?

对此问题的任何见解?

更新/答案

一些建议是使用jcmd(https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html),因为该网站告诉“本机内存跟踪”。但是,如果您仔细阅读该页面,您将看到

Since NMT doesn't track memory allocations by non-JVM code,
you may have to use tools supported by the operating system
to detect memory leaks in native code.

因此,如果本机库中存在泄漏,则jcmd不是一个选项。

在对互联网进行数天爬行并尝试各种分析器之后,对此问题最有效的方法是使用 jemalloc 分析器。

这页帮助了我很多! https://gdstechnology.blog.gov.uk/2015/12/11/using-jemalloc-to-get-to-the-bottom-of-a-memory-leak/

5 个答案:

答案 0 :(得分:3)

useFactory和其他操作系统级工具显示您的JVM进程消耗了多少系统内存。由top命令行选项定义的Java堆只是该内存的一部分。除了堆JVM需要一些内存。然后是java线程,每个线程都需要一定的内存。和Metaspace / Permanent Generation。还有其他几个。您可以阅读this blog postthis SO answer了解详情。

关于转储文件的大小和实际堆大小@ arnab-biswas的答案肯定是正确的。 MAT报告活动对象消耗的实际使用堆的大小。但堆转储包含整个堆,包括垃圾。

答案 1 :(得分:2)

我遇到过类似的情况。差异(HPROF文件大小 - MAT指示的堆的大小)实际上是垃圾(无法访问的对象)。无法到达的对象MAT中的直方图应该有帮助。

swap只会转储活动对象而不是垃圾。

答案 2 :(得分:0)

要监控本机内存,您需要使用-XX:NativeMemoryTracking=summary-XX:NativeMemoryTracking=detail启动应用程序。请注意,存在性能损失,因此在生产之前请三思而后行。

当内存跟踪处于活动状态时,您可以使用jcmd <pid> VM.native_memory summary。还有其他命令可用,请检查https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html或搜索本机内存跟踪。

编辑:在回答之前我没有关注这些链接,您可能正在寻找类似https://github.com/jeffgriffith/native-jvm-leaks的内容。

答案 3 :(得分:0)

堆转储: 堆转储是特定时间点Java进程内存的快照。持久化此数据有不同的格式,并且根据格式可能包含不同的信息,但通常快照包含有关触发快照时堆中的Java对象和类的信息。通常在写入堆转储之前触发完整的GC,因此它包含有关剩余对象的信息。

有关 MAT 的信息,请参阅http://help.eclipse.org/neon/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html

答案 4 :(得分:0)

您要求从可靠/官方来源获取答案。让我试一试。

  

1)为什么我的JVM进程(由Top显示)占用的内存大于堆   大小

因为JVM进程的总内存消耗比Java堆更多。几个例子:

monitor-dashboard

可信/官方消息来源:Run-Time Data Areasthis blog post

  

2)为什么堆转储大小比MAT报告大得多?

因为MAT没有显示完整的堆。在索引创建期间,Memory Analyzer会删除无法访问的对象,因为各种垃圾收集器算法往往会留下一些垃圾。

可靠/官方消息来源:MemoryAnalyzer/FAQ

相关问题