JVM进程如何分配内存?

时间:2016-02-19 09:57:24

标签: java linux memory-leaks spring-boot jvm

我在理解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 enter image description here

Metasapce大小 89M
enter image description here

换句话说,我想解释 799M - (374M + 89M)= 316M 的OffHeap内存。

我的应用(平均) 36个在线活动enter image description here

这些线程中的每一个都消耗1M:

[ root@fac6d0dfbbb4:/data ]$ java -XX:+PrintFlagsFinal -version |grep ThreadStackSize    
intx CompilerThreadStackSize                   = 0
intx ThreadStackSize                           = 1024
intx VMThreadStackSize                         = 1024

所以,在这里我们可以添加 36M

应用程序使用DirectBuffer的唯一地方是NIO。据JMX所见,它不会消耗大量资源 - 只有 98K enter image description here

最后一步是映射libs和jar。但根据pmapfull output

[ root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep ".so.*" | awk '{ sum+=$3} END {print sum}'

12896K

root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep “.jar" | awk '{ sum+=$3} END {print sum}'

9720K

我们这里只有 20M

因此,我们仍需要解释 316M - (36M + 20M)= 260M :(

有没有人知道我错过了什么?

1 个答案:

答案 0 :(得分:7)

<强>方法

您可能想要使用Java HotSpot Native Memory Tracking (NMT)

这可能会为您提供JVM分配的精确内存列表,分为不同的区域堆,类,线程,代码,GC,编译器,内部,符号,内存跟踪,池化空闲块,< / em>和未知

<强>用法

  • 您可以使用-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

<强>输出

然后,您将收到有关堆的完整概述,如下所示:

  

总计:保留= 664192KB,已提交= 253120KB&lt; ---本地内存跟踪跟踪的总内存

     
      
  • Java堆(保留= 516096KB,已提交= 204800KB)&lt; --- Java堆

         

    (mmap:reserved = 516096KB,已提交= 204800KB)

  •   
  • (保留= 6568KB,已提交= 4140KB)&lt; ---类元数据

         

    (类#665)&lt; ---已加载类的数量

         

    (malloc = 424KB,#1000)&lt; --- malloc&#39;内存,#malloc的数量

         

    (mmap:reserved = 6144KB,已提交= 3716KB)

  •   
  • 主题(保留= 6868KB,已提交= 6868KB)                           (线程#15)&lt; ---线程数

         

    (stack:reserved = 6780KB,committed = 6780KB)&lt; ---线程堆栈使用的内存

         

    (malloc = 27KB,#66)

         

    (竞技场= 61KB,#30)&lt; ---资源和处理区域

  •   
  • 代码(保留= 102414KB,已提交= 6314KB)

         

    (malloc = 2574KB,#74316)

         

    (mmap:reserved = 99840KB,已提交= 3740KB)

  •   
  • GC (保留= 26154KB,已提交= 24938KB)

         

    (malloc = 486KB,#110)

         

    (mmap:保留= 25668KB,已提交= 24452KB)

  •   
  • 编译器(保留= 106KB,已提交= 106KB)

         

    (malloc = 7KB,#90)

         

    (竞技场= 99KB,#3)

  •   
  • 内部(保留= 586KB,已提交= 554KB)

         

    (malloc = 554KB,#1677)

         

    (mmap:保留= 32KB,已提交= 0KB)

  •   
  • 符号(保留= 906KB,已提交= 906KB)

         

    (malloc = 514KB,#2736)

         

    (竞技场= 392KB,#1)

  •   
  • 内存跟踪(保留= 3184KB,已提交= 3184KB)

         

    (malloc = 3184KB,#300)

  •   
  • 汇总免费大奖(保留= 1276KB,已提交= 1276KB)

         

    (malloc的= 1276KB)

  •   
  • 未知(保留= 33KB,已提交= 33KB)

         

    (竞技场= 33KB,#1)

  •   

这详细介绍了JVM使用的不同内存区域,还显示了保留提交的内存。

我不知道哪种技术可以为您提供更详细的内存消耗列表。

进一步阅读:

您还可以将-XX:NativeMemoryTracking=detail与其他jcmd命令结合使用。更详细的解释可以在Java Platform, Standard Edition Troubleshooting Guide - 2.6 The jcmd Utility找到。您可以通过"jcmd <pid> help"

检查可能的命令