gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-28 23:29:01 25 4
gpt4 key购买 nike

当运行启用了 native 内存跟踪的 Java 应用程序(在 YARN 中)时(-XX:NativeMemoryTracking=detail 参见 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/nmt-8.htmlhttps://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     cachedMem:        129180      99348      29831          0       2689      73024-/+ buffers/cache:      23633     105546Swap:        15624          0      15624

为什么只驻留 1.6GB 内存时 JVM 指示已提交 2.7GB 内存?剩下的都去哪儿了?

最佳答案

I'm beginning to suspect that stack memory (unlike the JVM heap) seems to be precommitted without becoming resident and over time becomes resident only up to the high water mark of actual stack usage.

是的,除非另有说明,否则至少在 linux mmap 上是惰性的。匿名页面仅在写入后才由物理内存支持(由于 zero-page optimization 导致读取不足)

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

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


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

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

Committed-but-not-backed-by-storage 内存已映射 - 例如 - PROT_READ | PROT_WRITE但访问它仍然会导致页面错误。但是该页面错误由内核静默处理,方法是使用实​​际内存支持它并返回执行,就好像什么都没发生一样。
即这是流程本身不会注意到的实现细节/优化。


对概念进行分解:

Used Heap:事件对象根据上次GC占用的内存量

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

保留:已通过 mmap 预先映射的总地址范围对于特定的内存池。
保留 - 已提交 差异包括 PROT_NONE映射,保证不受物理内存支持

驻留:当前在物理内存中的页面。这意味着代码、堆栈、已提交内存池的一部分以及最近访问的映射文件的一部分以及 JVM 无法控制的分配。

虚拟:所有虚拟地址映射的总和。涵盖已提交、保留的内存池以及映射文件或共享内存。这个数字很少能提供信息,因为 JVM 可以提前保留非常大的地址范围或 mmap 大文件。

关于linux - 为什么 JVM 报告的已提交内存比 linux 进程驻留集大小更多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31173374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com