当前位置: 首页 > 知识库问答 >
问题:

为什么JVM报告的提交内存比linux进程驻留集的大小多?

卫志泽
2023-03-14

当运行启用了本机内存跟踪的Java应用程序(在YARN中)(-xx:nativeMemoryTracking=detail请参见https://docs.oracle.com/javase/8/docs/technotes/guides/vm/nmt-8.html和https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html)时,我可以看到JVM在不同类别中使用了多少内存。

jdk 1.8.0_45上的我的应用程序显示:

Native Memory Tracking:

Total: reserved=4023326KB, committed=2762382KB
-                 Java Heap (reserved=1331200KB, committed=1331200KB)
                            (mmap: reserved=1331200KB, committed=1331200KB) 

-                     Class (reserved=1108143KB, committed=64559KB)
                            (classes #8621)
                            (malloc=6319KB #17371) 
                            (mmap: reserved=1101824KB, committed=58240KB) 

-                    Thread (reserved=1190668KB, committed=1190668KB)
                            (thread #1154)
                            (stack: reserved=1185284KB, committed=1185284KB)
                            (malloc=3809KB #5771) 
                            (arena=1575KB #2306)

-                      Code (reserved=255744KB, committed=38384KB)
                            (malloc=6144KB #8858) 
                            (mmap: reserved=249600KB, committed=32240KB) 

-                        GC (reserved=54995KB, committed=54995KB)
                            (malloc=5775KB #217) 
                            (mmap: reserved=49220KB, committed=49220KB) 

-                  Compiler (reserved=267KB, committed=267KB)
                            (malloc=137KB #333) 
                            (arena=131KB #3)

-                  Internal (reserved=65106KB, committed=65106KB)
                            (malloc=65074KB #29652) 
                            (mmap: reserved=32KB, committed=32KB) 

-                    Symbol (reserved=13622KB, committed=13622KB)
                            (malloc=12016KB #128199) 
                            (arena=1606KB #1)

-    Native Memory Tracking (reserved=3361KB, committed=3361KB)
                            (malloc=287KB #3994) 
                            (tracking overhead=3075KB)

-               Arena Chunk (reserved=220KB, committed=220KB)
                            (malloc=220KB) 

这显示了2.7GB的提交内存,包括1.3GB的分配堆和几乎1.2GB的分配线程堆栈(使用许多线程)。

但是,当运行ps ax-o pid、rss grep top时,它只显示1.6GB的res/rss驻留内存。检查交换显示无正在使用:

free -m
             total       used       free     shared    buffers     cached
Mem:        129180      99348      29831          0       2689      73024
-/+ buffers/cache:      23633     105546
Swap:        15624          0      15624

为什么JVM指示提交2.7GB内存,而只有1.6GB内存是驻留的?剩下的去哪儿了?

共有1个答案

孔君浩
2023-03-14

我开始怀疑堆栈内存(与JVM堆不同)似乎是预先提交的,而没有成为驻留内存,并且随着时间的推移,只有到实际堆栈使用的最高水位时才成为驻留内存

是的,至少在linux上mmap是懒惰的,除非另有说明。匿名页在写入后仅由物理内存支持(由于零页优化,读取是不够的)

GC堆内存会被复制收集器或预置零(-xx:+alwayspretouch)有效地触及,因此它始终是驻留的。线程堆栈不受此影响。

为了进一步确认,您可以使用pmap-x 并将各种地址范围的RSS与来自NMT的虚拟内存映射的输出交叉引用。

保留内存已用prot_none进行mmaped。这意味着虚拟地址空间范围在内核的vma结构中有条目,因此不会被其他mmap/malloc调用使用。但它们仍然会导致页面错误作为SIGSEGV转发到进程,即访问它们是一个错误。

这对于具有可供将来使用的连续地址范围是很重要的,这反过来又简化了指针算术。

committ-burn-back-by-storage内存已与例如prot_readprot_write映射,但访问它仍然会导致页面错误。但是,内核通过使用实际内存支持页面错误,并像什么都没发生一样返回到执行状态来静默地处理页面错误。
即。这是一个实现细节/优化,流程本身不会注意到。

对概念进行细分:

Committed:已与PROT_NONE以外的内容映射的地址范围。由于延迟分配和分页,它们可能由物理或交换支持,也可能不支持。

reserved:已通过mmap为特定内存池预映射的总地址范围。
reserved–committed差异由prot_none映射组成,这些映射保证不受物理内存的支持

常驻:当前在物理RAM中的页面。这意味着代码、堆栈、部分提交的内存池以及最近被访问和分配到JVM控制之外的部分mmaped文件。

virtual:所有虚拟地址映射的总和。包括提交的、保留的内存池,但也包括映射文件或共享内存。这个数字很少能提供信息,因为JVM可以预先保留非常大的地址范围或mmap大型文件。

 类似资料:
  • 问题内容: 在启用了本机内存跟踪的Java应用程序(在YARN中)运行时(请参阅https://docs.oracle.com/javase/8/docs/technotes/guides/vm/nmt-8.html和https:// docs。 oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html ),我

  • 下面是一些使用的JVM标志, -xmx3500m -XMS3500M -xx:maxmetaspacesize=400m -xx:compressedclassspacesize=35m 注意:线程堆栈的大小(1MB)和代码缓存(240MB)是默认的,JDK版本是1.8.0_252。 甚至由“jcmd pid vm.native_memory summary”输出产生的总和也是5.0GB,甚至不是

  • 我是java内存问题的新手,在调试java进程的内存使用时遇到了问题,需要你的帮助。根据“the java进程占用8G常驻内存和9.4G虚拟内存。这对于这个进程来说太多了,我想检查一下为什么它会吃掉内存。所以我使用jmap进行了一次堆转储(没有使用‘live’选项,因为它可能会触发GC ),发现只有100MB的活动对象,还有1.5G的不可达对象。那么剩下的6G内存去哪了?我应该检查哪些其他类型的非

  • 场景: 我有一个在docker容器中运行的JVM。我使用两个工具做了一些内存分析:1)Top2)Java本地内存跟踪。 问题: 给docker容器的总内存=2 GB Java最大堆=1 GB 提交总量(JVM)=始终小于800 MB 使用的堆(JVM)=始终小于200 MB 未使用堆(JVM)=始终小于100 MB。 RSS=约1.1GB. 那么,1.1 GB(RSS)和800 MB(Java总提

  • 我正在Windows 8.1 64位上开发java swing应用程序,带有4GB内存和JDK版本8u20 64位。 问题是当我使用带有监视器选项的Netbeans profiler启动应用程序时。 加载第一个Jframe时,应用程序Memory Heap约为18mb,JVM进程大小约为50mb(Image1)。 然后,当我启动另一个Jframe时,它包含一个带有webView的JFxPanel,

  • 我有一个问题,我有一个java应用程序,偶尔会在运行内存溢出后被linux中的oom杀手杀死。我已经监控了堆,它不会增长。事实上,它甚至从来没有通过达到允许的最大值,这是。 因此,我通过启用了本机内存跟踪。然后我运行我的应用程序,取一个基线,然后等到它开始吞噬内存的时候,这时我使用了