先决条件
应用程序在带有Java版本"13.0.1“的docker容器中运行,具有以下选项:
-Xmx6G -XX:MaxHeapFreeRatio=30 -XX:MinHeapFreeRatio=10 -XX:+AlwaysActAsServerClassMachine -XX:+UseContainerSupport -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:HeapDumpPath==/.../crush.hprof -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Xlog:gc*:file=/var/log/.../log.gc.log:time::filecount=5,filesize=100000
当我运行jcmd 1 VM.native_memory时,我得到了这样的信息:
Total: reserved=9081562KB, committed=1900002KB
- Java Heap (reserved=6291456KB, committed=896000KB)
(mmap: reserved=6291456KB, committed=896000KB)
- Class (reserved=1221794KB, committed=197034KB)
(classes #34434)
( instance classes #32536, array classes #1898)
(malloc=7330KB #121979)
(mmap: reserved=1214464KB, committed=189704KB)
( Metadata: )
( reserved=165888KB, committed=165752KB)
( used=161911KB)
( free=3841KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=1048576KB, committed=23952KB)
( used=21501KB)
( free=2451KB)
( waste=0KB =0.00%)
- Thread (reserved=456661KB, committed=50141KB)
(thread #442)
(stack: reserved=454236KB, committed=47716KB)
(malloc=1572KB #2654)
(arena=853KB #882)
- Code (reserved=255027KB, committed=100419KB)
(malloc=7343KB #26005)
(mmap: reserved=247684KB, committed=93076KB)
- GC (reserved=316675KB, committed=116459KB)
(malloc=47311KB #70516)
(mmap: reserved=269364KB, committed=69148KB)
- Compiler (reserved=1429KB, committed=1429KB)
(malloc=1634KB #2498)
(arena=18014398509481779KB #5)
- Internal (reserved=2998KB, committed=2998KB)
(malloc=2962KB #5480)
(mmap: reserved=36KB, committed=36KB)
- Other (reserved=446581KB, committed=446581KB)
(malloc=446581KB #368)
- Symbol (reserved=36418KB, committed=36418KB)
(malloc=34460KB #906917)
(arena=1958KB #1)
- Native Memory Tracking (reserved=18786KB, committed=18786KB)
(malloc=587KB #8291)
(tracking overhead=18199KB)
- Shared class space (reserved=11180KB, committed=11180KB)
(mmap: reserved=11180KB, committed=11180KB)
- Arena Chunk (reserved=19480KB, committed=19480KB)
(malloc=19480KB)
- Logging (reserved=7KB, committed=7KB)
(malloc=7KB #271)
- Arguments (reserved=17KB, committed=17KB)
(malloc=17KB #471)
- Module (reserved=1909KB, committed=1909KB)
(malloc=1909KB #11057)
- Safepoint (reserved=8KB, committed=8KB)
(mmap: reserved=8KB, committed=8KB)
- Synchronization (reserved=1136KB, committed=1136KB)
(malloc=1136KB #6628)这里我们可以看到“其他”部分消耗446581 KB,而总提交内存是1900002 KB。
因此,“其他”部分占用了所有已提交内存的23%!
此外,当应用程序运行时,此内存不会被释放。
因此,我将java标志-XX:NativeMemoryTracking=summary更改为-XX:NativeMemoryTracking=detail,以检查内存分配的位置,并获得以下两个奇怪的内存块:
[0x00007f8db4b32bae] Unsafe_AllocateMemory0+0x8e
[0x00007f8da416e7db]
(malloc=298470KB type=Other #286)
[0x00007f8db4b32bae] Unsafe_AllocateMemory0+0x8e
[0x00007f8d9b84bc90]
(malloc=148111KB type=Other #82)分析
我作为代理运行异步分析器,如下所示:
java -agentpath:/async-profiler/build/libasyncProfiler.so=start,event=itimer,Unsafe_AllocateMemory0,file=/var/log/.../unsafe_allocate_memory.html得到了这个火焰仪:https://i.stack.imgur.com/PbE5D.png
此外,我还试图对事件malloc,mmap,mprotect进行分析。malloc显示与事件Unsafe_AllocateMemory0相同的照相图,但mmap和mprotect的照像仪是空的。
我认为这个问题可能与C2编译器有关,并禁用了它,但是重新启动后没有什么改变-“其他”部分仍然占用了大量的内存。而且,这个应用程序寿命很长,我不确定禁用C2是否是一个好主意。
os.malloc。我像这样运行java应用程序:
LD_PRELOAD=/usr/local/lib/libjemalloc.so MALLOC_CONF=prof:true,lg_prof_interval:30,lg_prof_sample:17 exec java -jar /srv/app/myapp.jar在10+分钟之后,我使用了jeprof,得到了以下内容:https://i.stack.imgur.com/45adD.gif
还有两个内存块占用了许多本地内存。
结果
我找不到分配这么多记忆的地方。
也许有人可以推荐如何找出这个问题的根源?我需要采取哪些措施来避免这个问题呢?
更新1
多亏了阿潘金,我终于找到了这个地方,那里占据了那么多的记忆!
它与Redisson/Lettuce有关,它们在引擎盖下使用Netty:火焰仪
我使用了实验性的本机模式并运行java:
java -agentpath:/async-profiler/build/libasyncProfiler.so=start,event=nativemem,file=/var/log/.../profile.jfr -jar /srv/app/myapp.jar 发布于 2022-06-07 00:29:07
你的异步分析器的论点似乎是错的。
将event=itimer,Unsafe_AllocateMemory0更改为event=Unsafe_AllocateMemory0
异步分析器还有一个实验性的nativemem模式,专门用于查找本机内存泄漏。详细信息请参见https://github.com/jvm-profiling-tools/async-profiler/discussions/491。
NMT中的Other部分通常包括与Unsafe.allocateMemory一起分配的堆外内存,特别是直接ByteBuffers.
https://stackoverflow.com/questions/72524403
复制相似问题