当前位置: 首页 > 面试题库 >

为什么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 <mypid>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

为什么当仅驻留1.6GB时,JVM会指示已分配2.7GB内存?剩下的去了哪里?


问题答案:

我开始怀疑堆栈内存(与JVM堆不同)似乎是预先提交的,而没有驻留,并且随着时间的流逝,驻留内存仅达到实际堆栈使用率的最高水位。

是的,除非另有说明,至少在Linux上,mmap是懒惰的。页面仅在写入后才由物理内存支持(由于零页面优化,因此读取不足)

GC堆内存有效地被复制收集器或预调零(-XX:+AlwaysPreTouch)所触及,因此它将始终处于驻留状态。线程堆栈otoh不受此影响。

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

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

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

例如,已提交但未由存储支持的内存已映射- PROT_READ | PROT_WRITE但访问它仍会导致页面错误。但是,该页面错误由内核静默处理,方法是将其与实际内存一起备份,并像没有任何反应一样返回执行
也就是说,这是一个实现细节/优化,流程本身不会注意到。

细分概念:

Used Heap :根据最后一个GC,活动对象占用的内存量

提交 :已使用除PROT_NONE之外的其他内容映射的地址范围。由于延迟分配和分页,它们可能会或可能不会由物理或交换支持。

保留 :已mmap为特定内存池预先映射的总地址范围。
预留-致力于 差由PROT_NONE映射,这是保证不被物理存储器被备份

常驻
:当前处于物理内存中的页面。这意味着代码,堆栈,已提交的内存池的一部分,以及最近已被访问的mmaped文件的一部分,以及JVM控制范围之外的分配。

虚拟
:所有虚拟地址映射的总和。涵盖已提交,保留的内存池,还包括映射文件或共享内存。这个数字很少提供信息,因为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在不

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

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

  • 场景: 我有一个在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总提

  • 我们将和设置为1536m。现在,如果我理解正确的话,j-xmx表示堆的最大大小。 本系统采用4核15GB ram进程。 但是,当我检查正在运行的Java进程的RSS(使用top)时,我看到它使用的值比大,大约。 对于来说,有4个内核和15GB RAM的理想设置是什么(假设除了Java应用程序之外,系统中没有其他进程在运行)

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