Native Memory Tracking(NMT)详解

说明

java8给HotSpot VM引入了Native Memory Tracking (NMT)特性,可以用于追踪JVM内部的内存使用情况

使用

开启
1
-XX:NativeMemoryTracking=summary

使用-XX:NativeMemoryTracking=summary可以用于开启NMT,其中该值默认为off,可以设置为summary或者detail来开启;开启的话,大概会增加5%-10%的性能消耗

查看
1
2
# jcmd 1 VM.native_memory summary
# jcmd 1 VM.native_memory summary scale=MB

使用jcmd pid VM.native_memory可以查看,后面可以加summary或者detail,如果是开启summary的,就只能使用summary;其中scale参数可以指定展示的单位,可以为KB或者MB或者GB

创建baseline
1
2
3
# jcmd 1 VM.native_memory baseline
1:
Baseline succeeded

创建baseline之后可以用summary.diff或者detail.diff来对比

查看diff
1
# jcmd 1 VM.native_memory summary.diff

使用summary.diff来查看跟baseline对比的统计信息

shutdown时输出
1
-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

使用上述命令可以在jvm shutdown的时候输出整体的native memory统计

关闭
1
2
3
# jcmd 1 VM.native_memory shutdown
1:
Native memory tracking has been turned off

使用jcmd pid VM.native_memory shutdown可以用于关闭NMT;注意使用jcmd关闭之后貌似没有对应jcmd命令来开启

实例1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# jcmd 1 VM.native_memory summary scale=MB
1:

Native Memory Tracking:

Total: reserved=2506MB, committed=758MB
- Java Heap (reserved=1024MB, committed=512MB)
(mmap: reserved=1024MB, committed=512MB)

- Class (reserved=1104MB, committed=89MB)
(classes #16218)
(malloc=2MB #23616)
(mmap: reserved=1102MB, committed=87MB)

- Thread (reserved=64MB, committed=64MB)
(thread #64)
(stack: reserved=63MB, committed=63MB)

- Code (reserved=249MB, committed=29MB)
(malloc=5MB #9532)
(mmap: reserved=244MB, committed=24MB)

- GC (reserved=3MB, committed=2MB)
(mmap: reserved=3MB, committed=2MB)

- Internal (reserved=35MB, committed=35MB)
(malloc=35MB #20802)

- Symbol (reserved=22MB, committed=22MB)
(malloc=18MB #190356)
(arena=4MB #1)

- Native Memory Tracking (reserved=4MB, committed=4MB)
(tracking overhead=4MB)

- Arena Chunk (reserved=1MB, committed=1MB)
(malloc=1MB)

其中reserved是指总共可用的内存大小, 而commited是指已经使用的内存大小

Java Heap为堆内情况,Class为元数据区已加载的类信息,Thread为当前线程情况,包括程序主线程、Cleaner线程,也包括 GC 等本地线程,Code为codecach相关内容,也就是 JIT compiler 存储编译热点方法等信息的地方,GC为垃圾回收采相关内容,例如G1中的Remembered Set等数据结构占用的就是这里的空间,Internal统计信息包含着Direct Buffer 的直接内存,Native Memory Tracking部分表示该功能自身占用的部分。

实例2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# jcmd 1 VM.native_memory summary.diff scale=MB
1:

Native Memory Tracking:

Total: reserved=2506MB +3MB, committed=758MB +4MB

- Java Heap (reserved=1024MB, committed=512MB)
(mmap: reserved=1024MB, committed=512MB)

- Class (reserved=1104MB +2MB, committed=89MB +1MB)
(classes #16218 +5)
(malloc=2MB #23678 +576)
(mmap: reserved=1102MB +2MB, committed=87MB +1MB)

- Thread (reserved=64MB, committed=64MB)
(thread #64)
(stack: reserved=63MB, committed=63MB)

- Code (reserved=249MB, committed=30MB +3MB)
(malloc=5MB #9582 +760)
(mmap: reserved=244MB, committed=25MB +2MB)

- GC (reserved=3MB, committed=2MB)
(mmap: reserved=3MB, committed=2MB)

- Internal (reserved=35MB, committed=35MB)
(malloc=35MB #20803 +12)

- Symbol (reserved=22MB, committed=22MB)
(malloc=18MB #190357 +39)
(arena=4MB #1)

- Native Memory Tracking (reserved=4MB, committed=4MB)
(tracking overhead=4MB)

- Arena Chunk (reserved=1MB, committed=1MB)
(malloc=1MB)

通过summary.diff命令可以看到两次jcmd之间的变化,每个部分的增减都通过+/-标识了出来。