Java 为什么JVM的本机内存跟踪报告会报告线程中竞技场区域的内存使用率如此之高

Java 为什么JVM的本机内存跟踪报告会报告线程中竞技场区域的内存使用率如此之高,java,memory-management,Java,Memory Management,我遇到了一个问题,我有一个java应用程序,它在内存耗尽后偶尔会被linux中的oom杀手杀死。我已经监控了堆,但它没有增长。事实上,它甚至从未通过Xmx达到允许的最大值,即768MB 因此,我通过-XX:NativeMemoryTracking=summary启用了本机内存跟踪。然后,我运行我的应用程序,获取一个基线,然后等待它开始消耗内存,在这一点上,我使用jcmd VM.native_memory detail.diff生成以下报告 Native Memory Tracking: Tot

我遇到了一个问题,我有一个java应用程序,它在内存耗尽后偶尔会被linux中的oom杀手杀死。我已经监控了堆,但它没有增长。事实上,它甚至从未通过
Xmx
达到允许的最大值,即
768MB

因此,我通过
-XX:NativeMemoryTracking=summary
启用了本机内存跟踪。然后,我运行我的应用程序,获取一个基线,然后等待它开始消耗内存,在这一点上,我使用
jcmd VM.native_memory detail.diff
生成以下报告

Native Memory Tracking:

Total: reserved=16894180KB +14703341KB, committed=15330936KB +14896985KB

-                 Java Heap (reserved=786432KB, committed=450048KB +129536KB)
                            (mmap: reserved=786432KB, committed=450048KB +129536KB)

-                     Class (reserved=1185329KB +110708KB, committed=156657KB +128180KB)
                            (classes #23288 +19829)
                            (malloc=11825KB +2164KB #27117 +23990)
                            (mmap: reserved=1173504KB +108544KB, committed=144832KB +126016KB)

-                    Thread (reserved=16825159KB +16803246KB, committed=16825159KB +16803246KB)
                            (thread #47 +24)
                            (stack: reserved=47288KB +25472KB, committed=47288KB +25472KB)
                            (malloc=153KB +82KB #240 +120)
                            (arena=16777717KB +16777692 #92 +48)

-                      Code (reserved=260509KB +9756KB, committed=63625KB +56100KB)
                            (malloc=10909KB +9756KB #14012 +11850)
                            (mmap: reserved=249600KB, committed=52716KB +46344KB)

-                        GC (reserved=39135KB +15KB, committed=37831KB +307KB)
                            (malloc=10399KB +15KB #629 +478)
                            (mmap: reserved=28736KB, committed=27432KB +292KB)

-                  Compiler (reserved=890284KB +890139KB, committed=890284KB +890139KB)
                            (malloc=55KB +41KB #334 +258)
                            (arena=890229KB +890098 #8 +5)

-                  Internal (reserved=13299KB +3377KB, committed=13299KB +3377KB)
                            (malloc=13267KB +3377KB #26649 +21418)
                            (mmap: reserved=32KB, committed=32KB)

-                    Symbol (reserved=32729KB +27117KB, committed=32729KB +27117KB)
                            (malloc=28565KB +24400KB #285695 +250801)
                            (arena=4163KB +2717 #1)

-    Native Memory Tracking (reserved=13011KB +12136KB, committed=13011KB +12136KB)
                            (malloc=367KB +241KB #5803 +3803)
                            (tracking overhead=12644KB +11895KB)

-               Arena Chunk (reserved=18014398506330278KB -3153154KB, committed=18014398506330278KB -3153154KB)
                            (malloc=18014398506330278KB -3153154KB)
从报告中,我可以看到使用的内存量显著增加
committed=15330936KB+14896985KB
,但这不在堆中

这似乎发生在线程使用的内存中。堆栈本身看起来很正常,因为每个线程堆栈应该是
1024KB
,因此
47288KB
对于47个线程来说是合理的

Thread (reserved=16825159KB +16803246KB, committed=16825159KB +16803246KB)
                            (thread #47 +24)
                            (stack: reserved=47288KB +25472KB, committed=47288KB +25472KB)
                            (malloc=153KB +82KB #240 +120)
                            (arena=16777717KB +16777692 #92 +48) 
特别是,它报告说竞技场增加了
+16777692
。这可能是什么原因造成的?为什么?或者这不是一个问题?从我在网上看到的其他报告(包括其他stackoverflow问题)来看,arena的内存使用率从未像现在这样高

此外,竞技场区块本身就保留的大小而言是巨大的。这正常吗?如果不正常,是什么导致这种异常


下面的OpenJDK错误似乎报告了JVM本身的内存泄漏,所以我可能遇到了这个错误吗?

我们遇到了类似的问题,这个问题仍然存在,并且还在调查中。你可以看到下面的链接

但我还是要在这里分享我的分析

1) 此竞技场增加未映射到堆。因此,这显然不是java代码的问题。从这个角度看,它看起来像是JNI代码问题或JavaAPI内部的本机泄漏。 因此,跟踪您的JNI代码,看看您是否正在关闭所有malloc调用,并对所有本机java对象使用deleteLocalRef和deleteGlobalRef

2) 检查是否只有在java更新之后才出现此问题。如果是,则检查代码中使用的jni.h和相关文件。它来自java8吗

3) 如果仍然不走运,那么使用像Jemalloc这样的工具,它可以告诉您导致max泄漏的方法名称。这似乎是linux最好的工具

查看此链接:

4) 您可以使用像VADump这样的工具来查看哪个dll消耗最多内存


我们的调查还在进行中,如果有任何结果,我会及时通知你。请您在此更新您的进度。

只是一个观察-荒谬的“竞技场区块”在2^63/2^64处生效。这可能是一个溢出错误,但同样也可能只是某种深层机制,它被告知有整个地址空间可供使用。

另请参见快速更新,我不知道线程为什么开始占用竞技场的大量内存,但是我运行的是OpenJDK1.8.0_u144,我更新到了1.8.0_u151,到目前为止,我还没有再次遇到这个问题。