https://bbs.huaweicloud.com/forum/thread-0211103793043202049-1-1.html
从前面几篇文章,我们了解了 NMT 的基础知识以及 NMT 追踪区域分析的相关内容,本篇文章将为大家介绍一下使用 NMT 协助排查内存问题的案例。
我们在搞清楚 NMT 追踪的 JVM 各部分的内存分配之后,就可以比较轻松的协助排查定位内存问题或者调整合适的参数。
可以在 JVM 运行时使用 jcmd VM.native_memory baseline
创建基线,经过一段时间的运行后再使用 jcmd VM.native_memory summary.diff/detail.diff
命令,就可以很直观地观察出这段时间 JVM 进程使用的内存一共增长了多少,各部分使用的内存分别增长了多少,可以很方便的将问题定位到某一具体的区域。
比如我们看到 MetaSpace 的内存增长异常,可以结合 MAT 等工具查看是否类加载器数量异常、是否类重复加载、reflect 的 inflation 参数设置是否合理;如果 Symbol 内存增长异常,可以查看项目 String.intern 是否使用正常;如果 Thread 使用内存过多,考虑是否可以适当调整线程堆栈大小等等。
我们还记得前文(NMT 内存 & OS 内存概念差异性章节)中使用 top 命令查看启动的 JVM 进程,仔细观察会发现一个比较虚高的 VIRT 内存(10.7g),我们使用 NMT 追踪的 Total: reserved 才 2813709KB(2.7g),这多出来的这么多虚拟内存是从何而来呢?
top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27420 douyiwa+ 20 0 10.7g 697560 17596 S 100.0 0.3 0:18.79 java
Native Memory Tracking:
Total: reserved=2813077KB, committed=1496981KB
复制
使用 pmap -X
观察内存情况:
27420: java -Xmx1G -Xms1G -XX:+UseG1GC -XX:MaxMetaspaceSize=256M -XX:MaxDirectMemorySize=256M -XX:ReservedCodeCacheSize=256M -XX:NativeMemoryTracking=detail -jar nmtTest.jar
Address Perm Offset Device Inode Size Rss Pss Referenced Anonymous LazyFree ShmemPmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked Mapping
c0000000 rw-p 00000000 00:00 0 1049088 637236 637236 637236 637236 0 0 0 0 0 0 0
100080000 ---p 00000000 00:00 0 1048064 0 0 0 0 0 0 0 0 0 0 0
aaaaea835000 r-xp 00000000 fd:02 45613083 4 4 4 4 0 0 0 0 0 0 0 0 java
aaaaea854000 r--p 0000f000 fd:02 45613083 4 4 4 4 4 0 0 0 0 0 0 0 java
aaaaea855000 rw-p 00010000 fd:02 45613083 4 4 4 4 4 0 0 0 0 0 0 0 java
aaab071af000 rw-p 00000000 00:00 0 304 108 108 108 108 0 0 0 0 0 0 0 [heap]
fffd60000000 rw-p 00000000 00:00 0 132 4 4 4 4 0 0 0 0 0 0 0
fffd60021000 ---p 00000000 00:00 0 65404 0 0 0 0 0 0 0 0 0 0 0
fffd68000000 rw-p 00000000 00:00 0 132 8 8 8 8 0 0 0 0 0 0 0
fffd68021000 ---p 00000000 00:00 0 65404 0 0 0 0 0 0 0 0 0 0 0
fffd6c000000 rw-p 00000000 00:00 0 132 4 4 4 4 0 0 0 0 0 0 0
fffd6c021000 ---p 00000000 00:00 0 65404 0 0 0