简体   繁体   English

JVM进程如何分配内存?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM