1. 现象
最近发现线上机器 java 8 进程的 VIRT 虚拟内存使用达到了 11G+:
2. 不管用的 -Xmx
首先第一想到的当然使用 java 的 -Xmx 去限制堆的使用。但是无论怎样设置,都没有什么效果。没办法,只好开始苦逼的研究。
3. 什么是 VIRT
现代操作系统里面分配虚拟地址空间操作不同于分配物理内存。在64位操作系统上,可用的最大虚拟地址空间有16EB,即大概180亿GB。那么在一台只有16G的物理内存的机器上,我也能要求获得4TB的地址空间以备将来使用。例如:
void *mem = mmap(0, 4ul * 1024ul * 1024ul * 1024ul * 1024ul,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
-1, 0);
当使用 mmap 并设置 MAP_NORESERVE 标志时,并不会要求实际的物理内存和swap空间存在。所以上述代码可以在top中看到使用了 4096g 的 VIRT 虚拟内存,这当然是不可能的,它只是表示使用了 4096GB 的地址空间而已。
4. 为什么会用这么多地址空间
那 Java 程序为什么会使用这么多的地址空间呢?使用“pmap -x”来查看一下:
…
00007ff638021000 65404 0 0 ----- [ anon ]
00007ff63c000000 132 36 36 rw--- [ anon ]
00007ff63c021000 65404 0 0 ----- [ anon ]
00007ff640000000 132 28 28 rw--- [ anon ]
00007ff640021000 65404 0 0 ----- [ anon ]
00007ff644000000 132 8 8 rw--- [ anon ]
00007ff644021000 65404 0 0 ----- [ anon ]
00007ff648000000 184 184 184 rw--- [ anon ]
00007ff64802e000 65352 0 0 ----- [ anon ]
00007ff64c000000 132 100 100 rw--- [ anon ]
00007ff64c021000 65404 0 0 ----- [ anon ]
00007ff650000000 132 56 56 rw--- [ anon ]
00007ff650021000 65404 0 0 ----- [ anon ]
00007ff654000000 132 16 16 rw--- [ anon ]
00007ff654021000 65404 0 0 ----- [ anon ]
…
发现有很多奇怪的64MB的内存映射,查资料发现这是 glibc 在版本 2.10 引入的 arena 新功能导致。CentOS 6/7 的 glibc 大都是 2.12/ 2.17 了,所以都会有这个问题。这个功能对每个线程都分配一个分配一个本地arena来加速多线程的执行。
在 glibc 的 arena.c 中使用的 mmap() 调用就和之前的示例代码类似:
p2 = (char *)mmap(aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
MAP_NORESERVE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)
之后,只有很小的一部分地址被映射到了物理内存中:
mprotect(p2, size, PROT_READ | PROT_WRITE)
因此在一个多线程程序中,会有相当多的 64MB 的 arena 被分配。这个可以用环境变量 MALLOC_ARENA_MAX 来控制。在64位系统中的默认值为 128。
5. Java 的特殊性
Java 程序由于自己维护堆的使用,导致调用 glibc 去管理内存的次数较少。更糟的是 Java 8 开始使用 metaspace 原空间取代永久代,而元空间是存放在操作系统本地内存中,那线程一多,每个线程都要使用一点元空间,每个线程都分配一个 arena,每个都64MB,就会导致巨大的虚拟地址被分配。
6. 结束语
总结一下:
<!--[if !supportLists]-->· <!--[endif]-->VIRT高是因为分配了太多地址空间导致。
<!--[if !supportLists]-->· <!--[endif]-->一般来说不用太在意VIRT太高,因为你有16EB的空间可以使用。
<!--[if !supportLists]-->· <!--[endif]-->如果你实在需要控制VIRT的使用,设置环境变量MALLOC_ARENA_MAX,例如hadoop推荐值为4,因为YARN使用VIRT值监控资源使用。
y原源文地址:http://www.cnblogs.com/seasonsluo/p/java_virt.html
相关推荐
Virt-manager虚拟化技术介绍.pdf
Linux中的top, htop资源管理器命令中的VIRT列和RES列的...Linux运维都知道,VIRT是虚拟内存,RES是物理内存 但是如何在VIRT中申请内存,如何在RES中申请内存,你知道吗?你以为只是malloc,new这么简单吗? 奉上我作的实验总结
VIRT:进程占用的虚拟内存 RES:进程占用的物理内存 SHR:进程使用的共享内存 S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数 %CPU:进程占用CPU的使用率 %...
phys_to_virt 一个简单的 Windows 驱动程序,用于将(或“映射”)物理内存地址转换为调用进程虚拟地址空间。 这将很快支持更多操作。 包含一个用户模式应用程序来演示如何使用它。关于这主要是为了教育目的和发现。...
Virt-manager虚拟化技术介绍.pptx
virt-viewer-x64-0.5.7
[ NOTE: The virt_to_bus() and bus_to_virt() functions have beensuperseded by the
virt-manager是用于管理KVM虚拟环境的主要工具,virt-manager默认设置下需要使用root用户才能够使用该工具。当你想在KVM hypervisor服务器上托管虚拟机,由最终用户而非root用户访问这些虚拟机时并不总是很便利。
使用virt-manager创建和管理虚拟机 1.使用VNC Viewer连接进入虚拟化平台主机 2.打开终端输入virt-manager命令启动virt-manager虚拟机管理界面 #virt-manager 3.通过virt-manager安装CentOS 6.6的虚拟机 点击如...
virt-manager linux虚拟机管理图型界面
windows下的virt-viewer工具,可以在windows下连接kvm虚拟机
virt-viewer-0.6.0 云计算 virt-viewer。
VIRT:进程占用的虚拟内存值。 RES:进程占用的物理内存值。 SHR:进程使用的共享内存值。 S:进程的状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值是负数。 %CPU:该进程占用的CPU使用率...
使用secureCRT运行virt-manager显示虚机,要在secureCRT上打开X11功能
上课整理自用
xdisp_virt-master_h264远程桌面_xdisp_virt_xdisp_opera_远程桌面.zip
目录1. 需要桥接的应用场景2. 环境3. 配置步骤3.1 在宿主机中搭建网桥3.2 将网桥配置至虚拟机3.3 在虚拟机中配置网络4. 在终端中同时连接宿主机和虚拟机参考资源 1. 需要桥接的应用场景 假设一场景:在一运行Ubuntu...
virt2phys内核驱动安装与下载
下载源地址:http://linuxsoft.cern.ch/cern/updates/slc63/x86_64/RPMS/repoview/virt-manager.html,qq电脑管家安全扫描无毒,解决CentOS 6.5 Virt-Manager启动出错:unsupported format character ‘��0...