java – 为什么JVM的本机内存跟踪报告会报告线程内竞技场区域的高内存使用率

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

因此,我通过-XX:NativeMemoryTracking = summary启用了本机内存跟踪.然后我运行我的应用程序,取一个基线,然后等到它开始吃内存的点,此时我使用了jcmd< pid> 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)

从报告我可以看出,使用的内存量已大幅增加= 15330936KB 14896985KB,但这不在堆中.

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

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 Chunk本身在保留的大小方面是巨大的.这是正常的,如果不是,可能导致这种异常吗?

以下打开的JDK错误JDK-8164293似乎报告了JVM本身的内存泄漏,所以我是否会遇到此错误?

最佳答案 我们有类似的问题,这是开放的,仍在调查中.你可以看到下面的链接

private bytes increase for a javaw process in java 8

但我仍然会在这里分享我的分析.

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

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

3)如果仍然没有运气,那么使用像Jemalloc这样的工具,它可以告诉你导致最大泄漏的方法名称.看来这是linux的最佳工具.

看看这个链接:https://gdstechnology.blog.gov.uk/2015/12/11/using-jemalloc-to-get-to-the-bottom-of-a-memory-leak/

4)你可以使用像VADump这样的工具来查看哪个dll占用了大部分内存.

我们的调查仍在进行中,如果得到任何结果,我会更新一次.请您在此处更新您的进度.

点赞