当运行一个启用了本机内存跟踪(-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)的Java应用程序(in-Thread)时,我可以看到JVM在不同类别中使用了多少内存.

我在jdk 1.8.045上的应用程序显示:

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时,它只显示RES/rss个驻留内存中的1.6GB.勾选swap表示无正在使用:

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内存?其他人go 哪儿了?

推荐答案

我开始怀疑堆栈内存(与JVM堆不同)似乎是在没有成为常驻内存的情况下预先提交的,随着时间的推移,它只会成为常驻内存,直到达到实际堆栈使用的最高水位.

是的,至少在linux上,mmap是懒惰的,除非另有说明.匿名页面只有在写入后才由物理内存支持(由于zero-page optimization位用户,读取是不够的)

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

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


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

这一点很重要,可以为将来的使用提供连续的地址范围,从而简化指针算法.

已提交但未由存储内存支持的内存已映射到(例如)PROT_READ | PROT_WRITE,但访问它仍会导致页面错误.但是,这个页面错误是由内核通过使用实际内存来支持它,并像什么都没发生一样返回到执行状态来默默地处理的.


要对这些概念进行细分:

Used Heap:根据上一次GC,活动对象占用的内存量

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

Reserved:特定内存池通过mmap预先映射的总地址范围

Resident:当前在物理ram中的页面.这意味着代码、堆栈、提交内存池的一部分,以及最近被访问的mmaped文件的一部分,以及JVM无法控制的分配.

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

Linux相关问答推荐

C++ kill()使Linux崩溃到登录屏幕

git别名函数可以用单引号写吗?

我想强调某些条件是否与Linux中的全部输出匹配

AWK打印到文件正在追加,而不是覆盖

Linux-如何区分目录中名称相同但扩展名不同的所有文件

从 MariaDB 连接到 Oracle 时出现错误消息libsqora.so.11.1:找不到文件

未找到 SDL_Vertex 和 SDL_RenderGeometry

如何删除文件中不需要的字符(使用 shell 脚本)

用户级线程如何与内核级线程对话

根据外部请求在 Netbeans 中启动 XDebug

为什么在 find 命令中使用 dirname 会 for each 匹配项提供点?

sed: -i 不能与 Mac OS X 上的标准输入一起使用

如何在 Linux 中设置目录大小限制?

如何将输出从 grep 传送到 cp?

在 bash 中检测公共 IP 地址的方法

NGINX:connect() 到 unix:/var/run/php7.0-fpm.sock 失败(2:没有这样的文件或目录)

在Linux中使用空格设置环境变量

用curl编译php,curl安装在哪里?

如何将初始输入通过管道传输到随后将是交互式的进程中?

在我的 index.php 中加载 CSS 和 JS 等资源时出现错误 403