- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个问题,我有一个 java 应用程序,在内存不足后偶尔会被 linux 中的 oom killer 杀死。我监视了堆,它没有增长。事实上,它甚至从未达到 Xmx
允许的最大值这是768MB
.
因此我通过 -XX:NativeMemoryTracking=summary
启用了 native 内存跟踪.然后我运行我的应用程序,获取基线,然后等到它开始占用内存的时间点,此时我使用 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)
从报告中我可以看到内存使用量明显增加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 Chunk 本身是巨大的。这是正常的吗?如果不是,是什么导致了这种异常?
以下打开JDK bug JDK-8164293似乎报告了 JVM 本身的内存泄漏,所以我会遇到这个错误吗?
最佳答案
我们遇到了类似的问题,该问题仍在调查中。你可以看到下面的链接 private bytes increase for a javaw process in java 8
但我仍然会在这里分享我的分析。
1) 这个竞技场增加没有映射到堆上。所以很明显不是java代码的问题。看看这个,它看起来像是 JNI 代码问题或 java api 内部的 native 泄漏。因此,跟踪您的 JNI 代码并查看您是否正在关闭所有 malloc 调用并为所有 native 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 占用的内存最多。
我们的调查仍在进行中,如果有任何结果,我会及时通知您。请您也在这里更新您的进度。
关于java - 为什么 JVM 的 native 内存跟踪报告会报告线程内竞技场区域的内存使用率如此之高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46937641/
我正在阅读一本关于内存作为编程概念的书。在后面的一章中,作者大量使用了arena这个词,但从未定义它。我搜索了这个词的含义以及它与内存的关系,但一无所获。以下是作者使用该术语的一些上下文: "The
我是一名优秀的程序员,十分优秀!