[英]How does a JVM process allocate its memory?
I have a little gap in understanding how a JVM process allocates its own memory. 我在理解JVM进程如何分配自己的内存方面有一点差距。 As far as I know
我所知道的
RSS = Heap size + MetaSpace + OffHeap size
where OffHeap consists of thread stacks, direct buffers, mapped files (libraries and jars) and JVM code itself; 其中OffHeap由线程堆栈,直接缓冲区,映射文件(库和jar)和JVM代码本身组成;
At the moment I'm trying to analyze my Java application (Spring Boot + Infinispan) which RSS is 779M (it runs in a docker container, so pid 1 is ok): 目前我正在尝试分析我的Java应用程序(Spring Boot + Infinispan),其中RSS为779M (它在docker容器中运行,因此pid 1可以):
[ root@daf5a5ae9bb7:/data ]$ ps -o rss,vsz,sz 1
RSS VSZ SZ
798324 6242160 1560540
According to jvisualvm
, committed Heap size is 374M 根据
jvisualvm
,承诺的堆大小为374M
Metasapce size is 89M Metasapce大小为89M
In other words, I want to explain 799M - (374M + 89M) = 316M of OffHeap memory. 换句话说,我想解释799M - (374M + 89M)= 316M的OffHeap内存。
My app has (in average) 36 live threads . 我的应用程序(平均)有36个活动主题 。
Each of these threads consumes 1M: 每个线程消耗1M:
[ root@fac6d0dfbbb4:/data ]$ java -XX:+PrintFlagsFinal -version |grep ThreadStackSize
intx CompilerThreadStackSize = 0
intx ThreadStackSize = 1024
intx VMThreadStackSize = 1024
So, here we can add 36M . 所以,在这里我们可以添加36M 。
The only place where the app uses DirectBuffer is NIO. 应用程序使用DirectBuffer的唯一地方是NIO。 As far as I can see from JMX, it doesn't consume a lot of resources - only 98K
据我所知,从JMX可以看出,它不会消耗大量资源 - 只有98K
The last step is mapped libs and jars. 最后一步是映射libs和jar。 But according to
pmap
( full output ) 但是根据
pmap
( 完整输出 )
[ root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep ".so.*" | awk '{ sum+=$3} END {print sum}'
12896K
plus 加
root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep “.jar" | awk '{ sum+=$3} END {print sum}'
9720K
we only have 20M here. 我们这里只有20M 。
Hence, we still have to explain 316M - (36M + 20M) = 260M :( 因此,我们仍然需要解释316M - (36M + 20M)= 260M :(
Does anyone have any idea what I missed? 有谁知道我错过了什么?
Approach: 做法:
You may want to use Java HotSpot Native Memory Tracking (NMT) . 您可能希望使用Java HotSpot本机内存跟踪(NMT) 。
This may give you an exact list of memory allocated by the JVM, splitted up into the different areas heap, classes, threads, code, GC, compiler, internal, symbols, memory tracking, pooled free chunks, and unknown . 这可能会为您提供JVM分配的精确内存列表,分为不同区域堆,类,线程,代码,GC,编译器,内部,符号,内存跟踪,池化空闲块和未知 。
Usage : 用法 :
You can start your application with -XX:NativeMemoryTracking=summary
. 您可以使用
-XX:NativeMemoryTracking=summary
启动应用程序。
Observations of the current heap can be done with jcmd <pid> VM.native_memory summary
. 可以使用
jcmd <pid> VM.native_memory summary
对当前堆进行观察。
Where to find jcmd / pid : 在哪里可以找到jcmd / pid :
On a default OpedJDK installation on Ubuntu this can be found at /usr/bin/jcmd
. 在Ubuntu上的默认OpedJDK安装上,可以在
/usr/bin/jcmd
。
By just running jcmd
without any parameter, you get a list of running Java applications. 通过运行不带任何参数的
jcmd
,您将获得正在运行的Java应用程序的列表。
user@pc:~$ /usr/bin/jcmd
5169 Main <-- 5169 is the pid
Output : 输出 :
You will then receive a complete overview over your heap, looking something like the following: 然后,您将收到有关堆的完整概述,如下所示:
Total: reserved=664192KB, committed=253120KB <--- total memory tracked by Native Memory Tracking
总计:保留= 664192KB,已提交= 253120KB <---本机内存跟踪跟踪的总内存
Java Heap (reserved=516096KB, committed=204800KB) <--- Java Heap
Java堆 (保留= 516096KB,已提交= 204800KB)<--- Java堆
(mmap: reserved=516096KB, committed=204800KB)
(mmap:保留= 516096KB,已提交= 204800KB)
Class (reserved=6568KB, committed=4140KB) <--- class metadata
类 (保留= 6568KB,已提交= 4140KB)<---类元数据
(classes #665) <--- number of loaded classes
(类#665)<---加载类的数量
(malloc=424KB, #1000) <--- malloc'd memory, #number of malloc
(malloc = 424KB,#1000)<--- malloc'd memory,#malloc的数量
(mmap: reserved=6144KB, committed=3716KB)
(mmap:保留= 6144KB,已提交= 3716KB)
Thread (reserved=6868KB, committed=6868KB) (thread #15) <--- number of threads
线程 (保留= 6868KB,已提交= 6868KB)(线程#15)<---线程数
(stack: reserved=6780KB, committed=6780KB) <--- memory used by thread stacks
(stack:reserved = 6780KB,committed = 6780KB)<---线程堆栈使用的内存
(malloc=27KB, #66)
(malloc = 27KB,#66)
(arena=61KB, #30) <--- resource and handle areas
(竞技场= 61KB,#30)<---资源和处理区域
Code (reserved=102414KB, committed=6314KB)
代码 (保留= 102414KB,已提交= 6314KB)
(malloc=2574KB, #74316)
(malloc = 2574KB,#74316)
(mmap: reserved=99840KB, committed=3740KB)
(mmap:reserved = 99840KB,已提交= 3740KB)
GC (reserved=26154KB, committed=24938KB)
GC (保留= 26154KB,已提交= 24938KB)
(malloc=486KB, #110)
(malloc = 486KB,#110)
(mmap: reserved=25668KB, committed=24452KB)
(mmap:保留= 25668KB,已提交= 24452KB)
Compiler (reserved=106KB, committed=106KB)
编译器 (保留= 106KB,已提交= 106KB)
(malloc=7KB, #90)
(malloc = 7KB,#90)
(arena=99KB, #3)
(竞技场= 99KB,#3)
Internal (reserved=586KB, committed=554KB)
内部 (保留= 586KB,已提交= 554KB)
(malloc=554KB, #1677)
(malloc = 554KB,#1677)
(mmap: reserved=32KB, committed=0KB)
(mmap:保留= 32KB,已提交= 0KB)
Symbol (reserved=906KB, committed=906KB)
符号 (保留= 906KB,已提交= 906KB)
(malloc=514KB, #2736)
(malloc = 514KB,#2736)
(arena=392KB, #1)
(竞技场= 392KB,#1)
Memory Tracking (reserved=3184KB, committed=3184KB)
内存跟踪 (保留= 3184KB,已提交= 3184KB)
(malloc=3184KB, #300)
(malloc = 3184KB,#300)
Pooled Free Chunks (reserved=1276KB, committed=1276KB)
汇总免费大块 (保留= 1276KB,承诺= 1276KB)
(malloc=1276KB)
(malloc的= 1276KB)
Unknown (reserved=33KB, committed=33KB)
未知 (保留= 33KB,已提交= 33KB)
(arena=33KB, #1)
(竞技场= 33KB,#1)
This gives a detailed overview of the different memory areas used by the JVM, and also shows the reserved and commited memory. 这给出了JVM使用的不同内存区域的详细概述,还显示了保留和提交的内存。
I don't know of a technique that gives you a more detailed memory consumption list. 我不知道一种技术可以为您提供更详细的内存消耗列表。
Further reading: 进一步阅读:
You can also use -XX:NativeMemoryTracking=detail
in combination with further jcmd
commands. 您还可以将
-XX:NativeMemoryTracking=detail
与其他jcmd
命令结合使用。 A more detailed explaination can be found at Java Platform, Standard Edition Troubleshooting Guide - 2.6 The jcmd Utility . 可以在Java平台,标准版故障排除指南 - 2.6 jcmd实用程序中找到更详细的说明。 You can check possible commands via
"jcmd <pid> help"
您可以通过
"jcmd <pid> help"
检查可能的命令
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.