系统的故障诊断是一个一步一步排除可能疑点找到问题所在的过程。今天测者和你一起学习JVM内存的故障排查方法。
系统的故障诊断是一个一步一步排除可能疑点找到问题所在的过程。今天测者和你一起学习JVM内存的故障排查方法。
Native Memory Tracking (NMT) 是Java Hotspot VM的一个功能。用来跟踪Java 内存的使用情况,NMT可以追踪到堆内内存、code区域、通过unsafe.allocateMemory和DirectByteBuffer申请的内存,NMT不能跟踪C代码的申请的堆外内存的情况,因此有些时候需要配合操作系统级的内存检测工具使用。
NMT的使用是通过配置JVM启动参数来设置的,具体如下:
-XX:NativeMemoryTracking=[off | summary | detail]
# off: 默认关闭
# summary: 只统计各个分类的内存使用情况.
# detail: Collect memory usage by individual call sites.
参数说明如下:
参数 | 说明 |
---|---|
off | 默认是off,关闭NMT |
summary | 只收集汇总信息 |
detail | 收集全部信息 |
特别提醒:开启NMT后,性能会有5%-10%的损耗,因此,在发现有内存问题后,才能使用该工具,没有发现问题的时候,尽量使其关闭。
JDK提供了jcmd工具查看NMT的监控结果,具体格式如下:
jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]
参数说明:
参数 | 说明 |
---|---|
summary | 只打印按照分类汇总信息 |
detail | 打印按类别汇总的内存使用情况、打印虚拟内存映射、打印由呼叫站点聚合的内存使用情况 |
baseline | 创建内存快照,以比较不同时间的内存差异 |
summary.diff | 打印自上次baseline到现在的内存差异,显示汇总信息 |
detail.diff | 打印自上次baseline到现在的内存差异, 显示详细信息 |
shutdown | 关闭NMT功能 |
其中,scale 指定内存单位,默认为KB
-XX:+PrintNMTStatistics -XX:+UnlockDiagnosticVMOptions
当NMT发现系统资源不足的时候,自行关闭。很多时候你并不希望这样,因此需要现实的告诉NMT不能关闭:
-XX:-AutoShutdownNMT
###现象 JVM启动参数中设置:
-Xmx=6G
测试过程总,发现服务器内存不断增大,通过如下命令:
user@hostxxx> prstat -p 2780
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP
2780 user 11G 11G sleep 59 0 44:16:39 0.0% java/196
user@hostxxx> /opt/jdk1.8.0_40/bin/jstat -gcutil 2780
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 100.00 90.60 46.80 98.02 97.10 11323 4049.745 11 225.345 4275.090
有上看到-Xmx=6G,但是RSS在运行过程中11G,怀疑存在堆外泄露。
加入 -XX:NativeMemoryTracking=summary启动参数后,重启。查看NMT报告如下(重点关注committed大小,这个是实际使用的内存大小):
7740: #进程ID
Native Memory Tracking:
Total: reserved=6478032KB, committed=5440716KB
- Java Heap (reserved=4104204KB, committed=4194304KB)
(mmap: reserved=4194304KB, committed=4194304KB)
通过报告发现实际占committed大于物理内存,因此可以怀疑存在内存泄露问题。