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

Java heap dump and the heap size after the heap analysis differs

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

后漏时,

前泄漏时,

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

对这个问题有什么见解吗?

更新/回答

一些建议是使用 jcmd (https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html),正如网站所说 "Native Memory Tracking"。但是,如果你仔细阅读页面,你会看到

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/

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

jmap -F -dump:live,format=b,file=<file_name.hprof> <process_id> 只会转储活动对象而不是垃圾。

top 和其他 OS 级别的工具显示您的 JVM 进程消耗了多少系统内存。 Java 堆,由 -Xmx 命令行选项定义,只是该内存的一部分。除了堆之外,JVM 本身还需要一些内存。然后是 java 个线程,每个线程都需要一定的内存量。和Metaspace/Permanent代。还有其他几个。您可以阅读 this blog post and 了解更多信息。

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

为了监控本机内存,您需要使用 -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 的内容。

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

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

您要求从 credible/official 来源获取答案图。让我试试看。

1) why is the memory consumed by my JVM process (shown by Top) larger than the heap size?

因为 JVM 进程的总内存消耗包含的不仅仅是 Java 堆。几个例子:

  • 生成的 (JIT:ed) 代码
  • 加载的库(包括 jar 和 class 文件)
  • java 堆的控制结构
  • 线程堆栈
  • 用户本机内存(在 JNI 中进行 malloc:ed)

Credible/official 来源:Run-Time Data Areas and this blog post

2) why is the heap dump size much bigger than what MAT reports?

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

Credible/official 来源:MemoryAnalyzer/FAQ