JVM 使用内存分析
目录
要全面查看一个 Java 应用的实际内存占用,需要从 JVM 内存区域、系统进程内存 和 堆外内存 三个维度综合分析。以下是详细方法和工具指南:
JVM 内存分析
1. 使用 jcmd + Native Memory Tracking (NMT)
# 启动应用时开启NMT监控
java -XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -jar your-app.jar
# 查看详细内存分布(运行后执行)
jcmd <PID> VM.native_memory detail
输出示例:
Native Memory Tracking:
Total: reserved=12GB, committed=10GB
- Java Heap: reserved=8GB, committed=7GB # -Xmx控制的堆内存
- Class: reserved=2GB, committed=1.5GB # 类元数据(Metaspace)
- Thread: reserved=0.5GB, committed=0.3GB # 线程栈(线程数 × -Xss)
- Code: reserved=1GB, committed=0.8GB # JIT编译代码缓存
- GC: reserved=1.5GB, committed=1GB # 垃圾回收器占用
- Internal: reserved=0.5GB, committed=0.3GB # 直接内存(Direct Buffer)等
- Other: reserved=0.2GB, committed=0.1GB # 其他JVM内部开销
📌 reserved vs committed 解析
reserved:JVM 向操作系统预先保留的虚拟内存总量(堆+非堆),但尚未全部占用物理内存。
committed:JVM 实际向操作系统申请并使用的物理内存(堆+非堆),这部分是真实开销。
实际测试:

2. 使用 jstat 监控堆内存分区
jstat -gc <PID> 1s 5 # 每1秒采样1次,共5次
关键列:
S0C/S1C:Survivor区容量EU/OU:Eden/老年代使用量MC/MU:Metaspace容量/使用量CCSC/CCSU:压缩类空间
系统级内存分析
1. 查看进程物理内存(RES)
top -p <PID> # 关注RES列
或
ps -p <PID> -o rss,vsz # RSS=物理内存, VSZ=虚拟内存
2. 使用 pmap 分析内存映射
pmap -x <PID> | sort -n -k3 # 按内存占用排序
输出重点:
[anon]:堆和堆外内存[stack]:线程栈- 共享库(如
libjvm.so)
3. 检查共享内存(SHR)
smem -P java # 显示USS/PSS/RSS(需安装smem)
- USS:进程独占内存(最真实占用)
- PSS:共享内存按比例分配后的值
堆外内存专项检查
1. 直接内存(Direct Buffer)
jcmd <PID> VM.native_memory summary | grep "Internal"
或
jmap -histo:live <PID> | grep "DirectByteBuffer"
2. JNI/Native 库内存
valgrind --tool=massif --pages-as-heap=yes java -jar app.jar # 深度分析(Linux)
3. 内存映射文件(MMAP)
pmap <PID> | grep "mmap"
浙公网安备 33010602011771号