フォーラム » つれづれ Java編 »
Linux上のJavaプロセスの仮想メモリサイズ
JavaのプロセスをLinuxで動かしている環境で、topコマンドを見るとVIRT(仮想メモリ)が著しく大きなプロセスとして悪目立ちします。
CentOS 6.8(64bit)上でOpenJDK 1.8.0_91 64bit VMの場合の例を次に示します。
top - 09:44:01 up 41 days, 21:31, 3 users, load average: 0.49, 0.51, 0.44 Tasks: 115 total, 1 running, 114 sleeping, 0 stopped, 0 zombie Cpu(s): 0.7%us, 0.3%sy, 0.0%ni, 99.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1020132k total, 845956k used, 174176k free, 30296k buffers Swap: 2064380k total, 13904k used, 2050476k free, 493900k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 10558 gitbucke 20 0 2523m 143m 9792 S 0.7 14.4 0:56.25 java 11049 root 20 0 15024 1268 960 R 0.3 0.1 0:00.01 top 1 root 20 0 23500 1104 908 S 0.0 0.1 0:00.68 init
VIRTサイズが2.4GBとなってびっくりします。物理メモリ使用量は、143MBとまあ妥当なところなのですが。
ヒープサイズを小さくすればいいのでは?と思い、-Xmx512m
を入れてもこの値は変わりません(少し減るかも)。
VIRT(仮想メモリサイズ)なので気にすることはない、という意見もあり(賛同)、ほっといてもいいのですが、Javaを知らないLinux管理者からチクチク言われることになるかもしれません。
この件について少ししらべると、次のブログが見つかりました。
Java 8 and Virtual Memory on Linux
ヒープサイズ(-Xmx)を指定してもtopコマンドのVIRTサイズは遥かに大きい値を示す。
glibc 2.10以降で arena 機能が導入され、それが影響している。
64bit OSではMALLOC_ARENA_MAXのデフォルト値が128(64MBのブロックを最大で128個取るので、128スレッドがmallocしたときで8GBの仮想メモリを使用)。
arena 機能は多数のスレッドがメモリ確保する際の性能を高めるが、JavaではJava側でメモリ管理しているのでarena機能はほぼ不要。
Java 8からPermGenが無くなってMetaspaceが導入、これはネイティブヒープなのでmallocが多数使われ、arena機能の影響をより大きく受けるようになった。
環境変数 MALLOC_ARENA_MAX に小さな値(2とか3とか)を設定することで緩和は可能。