JVM 进程如何分配内存?
How does a JVM process allocate its memory?
我对 JVM 进程如何分配自己的内存的理解有一点差距。据我所知
RSS = Heap size + MetaSpace + OffHeap size
其中 OffHeap 由线程堆栈、直接缓冲区、映射文件(库和 jar)和 JVM 代码本身组成;
目前我正在尝试分析我的 Java 应用程序(Spring Boot + Infinispan),RSS 是 779M(它运行在docker 容器,所以 pid 1 没问题):
[ root@daf5a5ae9bb7:/data ]$ ps -o rss,vsz,sz 1
RSS VSZ SZ
798324 6242160 1560540
根据jvisualvm
,提交的堆大小为374M
Metasapce 大小为 89M
换句话说,我想解释一下799M - (374M + 89M) = 316M OffHeap内存。
我的应用有(平均)36 个活动线程。
这些线程中的每一个消耗 1M:
[ root@fac6d0dfbbb4:/data ]$ java -XX:+PrintFlagsFinal -version |grep ThreadStackSize
intx CompilerThreadStackSize = 0
intx ThreadStackSize = 1024
intx VMThreadStackSize = 1024
所以,这里我们可以加上36M.
应用程序唯一使用DirectBuffer 的地方是NIO。据我从 JMX 可以看出,它并没有消耗很多资源——只有 98K
最后一步是映射库和罐子。但是根据 pmap
(full output)
[ root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep ".so.*" | awk '{ sum+=} END {print sum}'
12896K
加上
root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep “.jar" | awk '{ sum+=} END {print sum}'
9720K
这里只有20M
因此,我们还要解释316M - (36M + 20M) = 260M :(
有人知道我错过了什么吗?
方法:
您可能想要使用 Java HotSpot Native Memory Tracking (NMT)。
这可能会为您提供 JVM 分配的内存的确切列表,分为不同的区域堆,类,线程,代码,GC,编译器,内部,符号,内存跟踪,池化空闲块, 和 未知。
用法:
您可以使用-XX:NativeMemoryTracking=summary
开始申请。
可以用jcmd <pid> VM.native_memory summary
观察当前堆。
在哪里可以找到 jcmd/pid:
在 Ubuntu 上的默认 OpedJDK 安装上,可以在 /usr/bin/jcmd
找到它。
仅 运行 jcmd
不带任何参数,您将获得 运行 Java 个应用程序的列表。
user@pc:~$ /usr/bin/jcmd
5169 Main <-- 5169 is the pid
输出:
然后您将收到堆的完整概览,如下所示:
Total: reserved=664192KB, committed=253120KB <--- total memory tracked by Native Memory Tracking
Java Heap (reserved=516096KB, committed=204800KB) <--- Java Heap
(mmap: reserved=516096KB, committed=204800KB)
Class (reserved=6568KB, committed=4140KB) <--- class metadata
(classes #665) <--- number of loaded classes
(malloc=424KB, #1000) <--- malloc'd memory, #number of malloc
(mmap: reserved=6144KB, committed=3716KB)
Thread (reserved=6868KB, committed=6868KB)
(thread #15) <--- number of threads
(stack: reserved=6780KB, committed=6780KB) <--- memory used by thread stacks
(malloc=27KB, #66)
(arena=61KB, #30) <--- resource and handle areas
Code (reserved=102414KB, committed=6314KB)
(malloc=2574KB, #74316)
(mmap: reserved=99840KB, committed=3740KB)
GC (reserved=26154KB, committed=24938KB)
(malloc=486KB, #110)
(mmap: reserved=25668KB, committed=24452KB)
Compiler (reserved=106KB, committed=106KB)
(malloc=7KB, #90)
(arena=99KB, #3)
Internal (reserved=586KB, committed=554KB)
(malloc=554KB, #1677)
(mmap: reserved=32KB, committed=0KB)
Symbol (reserved=906KB, committed=906KB)
(malloc=514KB, #2736)
(arena=392KB, #1)
Memory Tracking (reserved=3184KB, committed=3184KB)
(malloc=3184KB, #300)
Pooled Free Chunks (reserved=1276KB, committed=1276KB)
(malloc=1276KB)
Unknown (reserved=33KB, committed=33KB)
(arena=33KB, #1)
这详细概述了 JVM 使用的不同内存区域,还显示了保留 和提交 内存。
我不知道有什么技术可以为您提供更详细的内存消耗列表。
进一步阅读:
您还可以将 -XX:NativeMemoryTracking=detail
与其他 jcmd
命令结合使用。可以在 Java Platform, Standard Edition Troubleshooting Guide - 2.6 The jcmd Utility 找到更详细的解释。您可以通过 "jcmd <pid> help"
检查可能的命令
我对 JVM 进程如何分配自己的内存的理解有一点差距。据我所知
RSS = Heap size + MetaSpace + OffHeap size
其中 OffHeap 由线程堆栈、直接缓冲区、映射文件(库和 jar)和 JVM 代码本身组成;
目前我正在尝试分析我的 Java 应用程序(Spring Boot + Infinispan),RSS 是 779M(它运行在docker 容器,所以 pid 1 没问题):
[ root@daf5a5ae9bb7:/data ]$ ps -o rss,vsz,sz 1
RSS VSZ SZ
798324 6242160 1560540
根据jvisualvm
,提交的堆大小为374M
Metasapce 大小为 89M
换句话说,我想解释一下799M - (374M + 89M) = 316M OffHeap内存。
我的应用有(平均)36 个活动线程。
这些线程中的每一个消耗 1M:
[ root@fac6d0dfbbb4:/data ]$ java -XX:+PrintFlagsFinal -version |grep ThreadStackSize
intx CompilerThreadStackSize = 0
intx ThreadStackSize = 1024
intx VMThreadStackSize = 1024
所以,这里我们可以加上36M.
应用程序唯一使用DirectBuffer 的地方是NIO。据我从 JMX 可以看出,它并没有消耗很多资源——只有 98K
最后一步是映射库和罐子。但是根据 pmap
(full output)
[ root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep ".so.*" | awk '{ sum+=} END {print sum}'
12896K
加上
root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep “.jar" | awk '{ sum+=} END {print sum}'
9720K
这里只有20M
因此,我们还要解释316M - (36M + 20M) = 260M :(
有人知道我错过了什么吗?
方法:
您可能想要使用 Java HotSpot Native Memory Tracking (NMT)。
这可能会为您提供 JVM 分配的内存的确切列表,分为不同的区域堆,类,线程,代码,GC,编译器,内部,符号,内存跟踪,池化空闲块, 和 未知。
用法:
您可以使用
-XX:NativeMemoryTracking=summary
开始申请。可以用
jcmd <pid> VM.native_memory summary
观察当前堆。
在哪里可以找到 jcmd/pid:
在 Ubuntu 上的默认 OpedJDK 安装上,可以在 /usr/bin/jcmd
找到它。
仅 运行 jcmd
不带任何参数,您将获得 运行 Java 个应用程序的列表。
user@pc:~$ /usr/bin/jcmd
5169 Main <-- 5169 is the pid
输出:
然后您将收到堆的完整概览,如下所示:
Total: reserved=664192KB, committed=253120KB <--- total memory tracked by Native Memory Tracking
Java Heap (reserved=516096KB, committed=204800KB) <--- Java Heap
(mmap: reserved=516096KB, committed=204800KB)
Class (reserved=6568KB, committed=4140KB) <--- class metadata
(classes #665) <--- number of loaded classes
(malloc=424KB, #1000) <--- malloc'd memory, #number of malloc
(mmap: reserved=6144KB, committed=3716KB)
Thread (reserved=6868KB, committed=6868KB) (thread #15) <--- number of threads
(stack: reserved=6780KB, committed=6780KB) <--- memory used by thread stacks
(malloc=27KB, #66)
(arena=61KB, #30) <--- resource and handle areas
Code (reserved=102414KB, committed=6314KB)
(malloc=2574KB, #74316)
(mmap: reserved=99840KB, committed=3740KB)
GC (reserved=26154KB, committed=24938KB)
(malloc=486KB, #110)
(mmap: reserved=25668KB, committed=24452KB)
Compiler (reserved=106KB, committed=106KB)
(malloc=7KB, #90)
(arena=99KB, #3)
Internal (reserved=586KB, committed=554KB)
(malloc=554KB, #1677)
(mmap: reserved=32KB, committed=0KB)
Symbol (reserved=906KB, committed=906KB)
(malloc=514KB, #2736)
(arena=392KB, #1)
Memory Tracking (reserved=3184KB, committed=3184KB)
(malloc=3184KB, #300)
Pooled Free Chunks (reserved=1276KB, committed=1276KB)
(malloc=1276KB)
Unknown (reserved=33KB, committed=33KB)
(arena=33KB, #1)
这详细概述了 JVM 使用的不同内存区域,还显示了保留 和提交 内存。
我不知道有什么技术可以为您提供更详细的内存消耗列表。
进一步阅读:
您还可以将 -XX:NativeMemoryTracking=detail
与其他 jcmd
命令结合使用。可以在 Java Platform, Standard Edition Troubleshooting Guide - 2.6 The jcmd Utility 找到更详细的解释。您可以通过 "jcmd <pid> help"