____M________________________ referenced,uptodate,dirty,lru,active,mmap
0x0000000000005868 10415 40 ___U_lA____Ma_b_____________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x0000000000405868 29 0 ___U_lA____Ma_b_______t_____________ uptodate,lru,active,mmap,anonymous,swapbacked,thp
0x000000000000586c 5 0 __RU_lA____Ma_b_____________________ referenced,uptodate,lru,active,mmap,anonymous,swapbacked
0x0000000000005878 356 1 ___UDlA____Ma_b_____________________ uptodate,dirty,lru,active,mmap,anonymous,swapbacked
total 26325 102
Jdk8及之前加载jar也是使用mmap的方式
在验证了jdk9加载lib/modules 之后,随便检查了下jdk8的进程,发现在加载jar包时,也是使用mmap的方式。
一个tomcat进程的map信息如下:
$ pmap -x 27226 | grep jar
...
00007f42c00d4000 16 16 0 r--s- tomcat-dbcp.jar
00007f42c09b7000 1892 1892 0 r--s- rt.jar
00007f42c45e5000 76 76 0 r--s- catalina.jar
00007f42c45f8000 12 12 0 r--s- tomcat-i18n-es.jar
00007f42c47da000 4 4 0 r--s- sunec.jar
00007f42c47db000 8 8 0 r--s- websocket-api.jar
00007f42c47dd000 4 4 0 r--s- tomcat-juli.jar
00007f42c47de000 4 4 0 r--s- commons-daemon.jar
00007f42c47df000 4 4 0 r--s- bootstrap.jar
可以发现一些有意思的点:
- 所有jar包的
Kbytes 和 RSS(resident set size) 是相等的,也就是说整个jar包都被加载到共享内存里了
- 从URLClassLoader的实现代码来看,它在加载资源时,需要扫描所有的jar包,所以会导致整个jar都要被加载到内存里
- 对比jdk9里的
modules ,它的RSS 并不是很高,原因是JImage的格式设计合理。所以jdk9后,jvm占用真实内存会降低。
jdk8及之前的 sun.zip.disableMemoryMapping 参数
总结
- linux下可以用pmap来获取进程mmap信息
- 通过读取
/proc/$pid/pagemap 可以获取到内存页的信息,并可以把虚拟地址转换为物理地址
- jdk9把类都打包到
lib/modules ,也就是JImage格式,可以减少真实内存占用
- jdk9多个jvm可以共用
lib/modules 映射的内存
- 默认情况下jdk8及以前是用mmap来加载jar包
|