0

我有一个 Java 应用程序使用大量堆外内存,超出预期。本机内存跟踪表明该应用程序使用了14 GB,但从top应用程序获得的信息来看,它使用了25.6 GB的虚拟内存。造成这种差异的原因是什么?

> jcmd 1 VM.native_memory summary
1:

Native Memory Tracking:

Total: reserved=14160512KB, committed=12564552KB
-                 Java Heap (reserved=10485760KB, committed=10485760KB)
                            (mmap: reserved=10485760KB, committed=10485760KB) 
 
-                     Class (reserved=1169595KB, committed=134571KB)
                            (classes #18900)
                            (  instance classes #17854, array classes #1046)
                            (malloc=2235KB #47971) 
                            (mmap: reserved=1167360KB, committed=132336KB) 
                            (  Metadata:   )
                            (    reserved=118784KB, committed=118088KB)
                            (    used=115663KB)
                            (    free=2425KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=14248KB)
                            (    used=13795KB)
                            (    free=453KB)
                            (    waste=0KB =0.00%)
 
-                    Thread (reserved=269333KB, committed=27681KB)
                            (thread #261)
                            (stack: reserved=268244KB, committed=26592KB)
                            (malloc=420KB #1567) 
                            (arena=669KB #520)
 
-                      Code (reserved=253419KB, committed=97975KB)
                            (malloc=5735KB #26933) 
                            (mmap: reserved=247684KB, committed=92240KB) 
 
-                        GC (reserved=347341KB, committed=183501KB)
                            (malloc=19653KB #50171) 
                            (mmap: reserved=327688KB, committed=163848KB) 
 
-                  Compiler (reserved=1788KB, committed=1788KB)
                            (malloc=2020KB #2691) 
                            (arena=18014398509481751KB #5)
 
-                  Internal (reserved=5265KB, committed=5265KB)
                            (malloc=5233KB #3983) 
                            (mmap: reserved=32KB, committed=32KB) 
 
-                     Other (reserved=1589357KB, committed=1589357KB)
                            (malloc=1589357KB #49387) 
 
-                    Symbol (reserved=29460KB, committed=29460KB)
                            (malloc=26703KB #274450) 
                            (arena=2757KB #1)
 
-    Native Memory Tracking (reserved=7838KB, committed=7838KB)
                            (malloc=502KB #7072) 
                            (tracking overhead=7336KB)
 
-               Arena Chunk (reserved=865KB, committed=865KB)
                            (malloc=865KB) 
 
-                   Logging (reserved=5KB, committed=5KB)
                            (malloc=5KB #191) 
 
-                 Arguments (reserved=18KB, committed=18KB)
                            (malloc=18KB #487) 
 
-                    Module (reserved=259KB, committed=259KB)
                            (malloc=259KB #2307) 
 
-              Synchronizer (reserved=205KB, committed=205KB)
                            (malloc=205KB #1651) 
 
-                 Safepoint (reserved=4KB, committed=4KB)
                            (mmap: reserved=4KB, committed=4KB) 

和顶部

> top
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s): 16.5 us,  4.1 sy,  0.0 ni, 79.1 id,  0.0 wa,  0.0 hi,  0.4 si,  0.0 st
MiB Mem :  64432.6 total,  36088.6 free,  24722.6 used,   3621.5 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.  38616.4 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                                          
    1 loro      20   0   25.6g  12.2g  22144 S 509.8  19.4   2066:35 java                                                                                                                                                             
 2350 root      20   0    5748   3596   3068 S   0.0   0.0   0:00.06 bash                                                                                                                                                             
 2926 loro      20   0    9804   3540   3052 R   0.0   0.0   0:00.03 top  

该应用程序在 jdk11 上运行

java;-server;-XX:+UnlockExperimentalVMOptions;-XX:+UseShenandoahGC;-XX:ShenandoahGCHeuristics=compact;-XX:+AlwaysPreTouch;-XX:+UseNUMA;-XX:-UseBiasedLocking;-Xms10G;-Xmx10G;-XX:+DoEscapeAnalysis;-XX:+PrintConcurrentLocks;-verbose:gc;-XX:+PrintGCDetails;-XX:NativeMemoryTracking=detail;-XX:+UseContainerSupport;-XshowSettings:vm;-XX:MaxRAMPercentage=90;-XX:InitialRAMPercentage=50;-XX:+PrintFlagsFinal;-jar;/home/loro/service.jar

4

1 回答 1

0

这看起来不是问题。我已经看到很多次了,在我职业生涯的初期,我也曾经担心过。当涉及到内存消耗时,您应该检查的字段称为 RES,因为它表示您的进程占用的实际物理内存量。

此行为在 RedHat https://access.redhat.com/solutions/296313提供的本文中被描述为预期的行为。我有一个免费帐户,所以我可以阅读它,如果你没有,我在这里引用这个。

在顶部的手册页中,VIRT 是任务使用的虚拟内存总量。它包括所有代码、数据和共享库以及已换出的页面。VIRT 还包括已分配但尚未用于任何用途的页面。处于此状态的任何页面都映射到内核零页面,因此它显示在 VIRT 中,但实际上并不消耗任何内存。

要检查进程实际使用的物理内存,请检查 Top 输出中的 RES 字段而不是 VIRT。

它更多的是内核行为,并且每当系统需要内存时,都可以通过释放缓存的内存来使用它。

我希望这可以帮助你解决这个令人困惑的事情。

于 2020-08-10T20:24:59.137 回答