Java Native Memory Tracking 追踪 JVM 内存使用情况
NMT JVM Java About 8,639 words开启 NMT
-XX:NativeMemoryTracking=off
:NMT
默认关闭,需在启动时开启。-XX:NativeMemoryTracking=summary
: 开启NMT
。-XX:NativeMemoryTracking=detail
: 开启NMT
,比summary
级别统计更详细,内存占用更多。
备注
文章中的1
是进程ID
。
关闭 NMT
jcmd 1 VM.native_memory shutdown
使用 NMT
jcmd 1 VM.native_memory
对比
开启基线
jcmd 1 VM.native_memory baseline
查看差异
jcmd 1 VM.native_memory summary.diff
示例信息
bash-4.4$ jcmd 1 VM.native_memory
1:
Native Memory Tracking:
(Omitting categories weighting less than 1KB)
Total: reserved=1040798KB, committed=701478KB
malloc: 42678KB #386484
mmap: reserved=998120KB, committed=658800KB
- Java Heap (reserved=512000KB, committed=512000KB)
(mmap: reserved=512000KB, committed=512000KB)
- Class (reserved=83129KB, committed=8633KB)
(classes #13125)
( instance classes #12273, array classes #852)
(malloc=1209KB #23704)
(mmap: reserved=81920KB, committed=7424KB)
( Metadata: )
( reserved=65536KB, committed=49920KB)
( used=49570KB)
( waste=350KB =0.70%)
( Class space:)
( reserved=81920KB, committed=7424KB)
( used=7059KB)
( waste=365KB =4.92%)
- Thread (reserved=26869KB, committed=3541KB)
(thread #48)
(stack: reserved=26744KB, committed=3416KB)
(malloc=72KB #286)
(arena=53KB #92)
- Code (reserved=249313KB, committed=23753KB)
(malloc=1625KB #7902)
(mmap: reserved=247688KB, committed=22128KB)
- GC (reserved=69379KB, committed=69379KB)
(malloc=17479KB #8391)
(mmap: reserved=51900KB, committed=51900KB)
- GCCardSet (reserved=140KB, committed=140KB)
(malloc=140KB #1735)
- Compiler (reserved=340KB, committed=340KB)
(malloc=175KB #801)
(arena=165KB #5)
- Internal (reserved=461KB, committed=461KB)
(malloc=457KB #11216)
(mmap: reserved=4KB, committed=4KB)
- Other (reserved=112KB, committed=112KB)
(malloc=112KB #21)
- Symbol (reserved=12518KB, committed=12518KB)
(malloc=11295KB #311929)
(arena=1223KB #1)
- Native Memory Tracking (reserved=6331KB, committed=6331KB)
(malloc=292KB #4176)
(tracking overhead=6039KB)
- Shared class space (reserved=12288KB, committed=11968KB)
(mmap: reserved=12288KB, committed=11968KB)
- Arena Chunk (reserved=197KB, committed=197KB)
(malloc=197KB)
- Tracing (reserved=32KB, committed=32KB)
(arena=32KB #1)
- Module (reserved=84KB, committed=84KB)
(malloc=84KB #1357)
- Safepoint (reserved=8KB, committed=8KB)
(mmap: reserved=8KB, committed=8KB)
- Synchronization (reserved=137KB, committed=137KB)
(malloc=137KB #1475)
- Serviceability (reserved=17KB, committed=17KB)
(malloc=17KB #14)
- Metaspace (reserved=65775KB, committed=50159KB)
(malloc=239KB #102)
(mmap: reserved=65536KB, committed=49920KB)
- String Deduplication (reserved=1635KB, committed=1635KB)
(malloc=1635KB #13216)
- Unknown (reserved=32KB, committed=32KB)
(mmap: reserved=32KB, committed=32KB)
显示单位为MB
bash-4.4$ jcmd 1 VM.native_memory summary scale=MB
1:
Native Memory Tracking:
Total: reserved=4817MB, committed=1139MB
- Java Heap (reserved=3288MB, committed=971MB)
(mmap: reserved=3288MB, committed=971MB)
- Class (reserved=1066MB, committed=47MB)
(classes #10170)
( instance classes #9495, array classes #675)
(malloc=2MB #27171)
(mmap: reserved=1064MB, committed=45MB)
( Metadata: )
( reserved=40MB, committed=39MB)
( used=37MB)
( free=1MB)
( waste=0MB =0.00%)
( Class space:)
( reserved=1024MB, committed=6MB)
( used=5MB)
( free=1MB)
( waste=0MB =0.00%)
含义
Total
总的统计信息。
Java Heap
堆内存使用情况,堆内存通过mmap
的方式申请。
基于节省内存资源还可以启用uncommit
机制等。
通过设置-Xmx
限制最大的堆内存占用。
通过设置-Xms
限制最小的堆内存占用。
Class
类元数据使用的内存空间,加载的类与方法信息,即虚拟机规范中规定的方法区。
其实就是metaspace
,包含两部分: 一是Metadata
,另外是Class space
。
JVM C++
层面的内存占用。
在JDK8
之后StringTable
就被移入Heap
,NMT
中StringTable
所使用的内存被单独统计到了Symbol
中。
通过设置-XX:MaxMetaspaceSize
限制Metadata
所使用的内存大小。
通过设置-XX:CompressedClassSpaceSize
限制Class space
所使用的内存大小。
Thread
线程与线程栈占用内存。
在aarch64
平台下默认为2M
。
在x86
平台下默认为1M
。
通过设置-Xss
/-XX:ThreadStackSize
限制每个线程栈占用的内存,总大小没有限制。
Code
Code Cache
存放native code
,这些native code
由动态生成的解释器循环、JNI
、即时编译器(JIT
)编译Java
方法产生。
JIT
生成的native code
占用了Code Cache
的绝大部分空间。
通过设置-XX:ReservedCodeCacheSize
限制Code
的最大内存。
GC
4)GC:垃圾回收占用内存,例如垃圾回收需要的 CardTable,标记数,区域划分记录,还有标记 GC Root 等等,都需要内存。这个不受限制,对于吞吐量优先的GC,例如 ParallelGC,不会很大,对于延迟优先的,例如 ZGC 会非常大(而且目前 ZGC 还是不分代,就更大了)。对于均衡型,例如 G1GC,可能会有几百兆 这个不受限制,一般不会很大,但也有例外,图3是27G的堆内存,使用G1垃圾回收器,你能看到GC区居然占用了3.8G的内存;
GCCardSet
只有G1GC
才有这个分类,统计Remember Sets
记忆集数据占用的大小。(Java 18
开始NMT
才从GC
分类中独立出来统计)
Compiler
JIT
编译器本身占用的空间,C1
、C2
编译器本身的代码和标记占用的内存,不受限制,一般不会很大。
通过设置-XX:CICompilerCount
指定编译线程的数量,限制Compiler
部分所使用的内存(当然这部分内存比较小)。
编译线程也是线程,所以还可以通过-XX:CompilerThreadStackSize
设置一个更小的值来节省此部分内存,但是削减虚拟机线程的堆栈大小是危险的操作,并不建议去因为此设置这个参数。
Internal
包含命令行解析器使用的内存、JVMTI
(JVM Tool Interface
)、PerfData
以及Unsafe
分配的内存等等。这个不受限制,一般不会很大的。
命令行解释器就是在初始化创建虚拟机时对 JVM 的命令行参数加以解析并执行相应的操作,如对参数-XX:NativeMemoryTracking=detail
进行解析。
如果使用了像是Skywalking
这种基于agent的,那么可能会很大,有几百兆。
Other
JVM
内部不属于其他类的占用就会归到这一类,不是JVM
本身而是操作系统的某些系统调用导致额外占的空间,一般不会很大的。
Symbol
字符串常量池占用的大小。
C++
字符串占用空间(不是Java
字符串)
-XX:StringTableSize
并不是来限制StringTable
最大申请的内存大小,而是用来限制StringTable
的表的长度。
StringTable
在HotSpot
中是以HashTable
的形式存储的,所以-XX:StringTableSize
参数设置的其实是HashTable
的长度,如果该值设置的过小的话,即使HashTable
进行rehash
,hash
冲突也会十分频繁,会造成性能劣化并有可能导致进入SafePoint
的时间增长。
总内存大小不受限制。
Native Memory Tracking
内存采集本身占用的内存大小,如果没有打开采集,就不会占用,总内存大小不受限制,一般不会很大。
Shared class space
共享类空间占用的内存。
可以通过-Xshare:off
关闭类共享空间,默认开启。
Arena Chunk
统计的Arena
与Chunk
,是HotSpot
自己定义的Arena
、Chunk
,而不是Glibc
中相关的Arena
与Chunk
的概念。总内存大小不受限制,一般不会很大。
Tracing
包括JVM perf
以及JFR
占用的空间。
如果开启了JFR
则主要是JFR
占用的内存。总内存大小不受限制,一般不会很大,也可能因为JFR
配置占用几百兆。
Module
Java 9
模块化后,模块占用的内存。
Safepoint
JVM
安全点占用内存,不会随着JVM
运行时的内存占用而变化。
Synchronization
Java
同步机制(例如synchronized
,还有AQS
的基础LockSupport
)底层依赖的C++
的数据结构,系统内部的mutex
等占用的内存。
Serviceability
JVM TI
(Java Virtual Machine Tool Interface
)占用的内存。
Metaspace
Class
中的MetaChunk
(除了malloc
的部分)
String Deduplication
Java
字符串去重占用内存,去重机制可以减少应用程序中字符串对象的内存占用。
这个机制一直在某些GC
下表现不佳,尤其是G1GC
以及ZGC
中,所以默认是关闭的。
可以通过-XX:+UseStringDeduplication
来启用。
Unknown
Unknown
有几种情况;
- 当内存类别无法确定时;
- 当
Arena
用作堆栈或值对象时; - 当类型信息尚未到达时。
参考
全网最硬核 JVM 内存解析 - 1.从 Native Memory Tracking 说起 https://juejin.cn/post/7225871227743043644
官方文档
https://docs.oracle.com/en/java/javase/17/vm/native-memory-tracking.html
https://docs.oracle.com/en/java/javase/17/troubleshoot/diagnostic-tools.html
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓