読者です 読者をやめる 読者になる 読者になる

見習いプログラミング日記

Java EE を中心に色々なことを考えてみます。目指せ本物のプログラマ。

JDK8(Linux 64bit)のデフォルトヒープサイズ

Java SE OpenJDK

Oracleの公式ドキュメントには、-Xmxが未指定であった場合のエルゴノミクスによる最大ヒープサイズは『32GBを上限として、物理メモリの4分の1』書かれている。32GBは-XX:-UseCompressedOopsにより圧縮Oopを明示的に無効にした場合の最大デフォルトヒープサイズで、何もオプションを付けずに起動した場合は29GBが上限。

ヒープサイズの決定はarguments.cppのArguments::set_heap_size()で計算されている。デフォルトの最大および初期ヒープサイズは、物理メモリ量により異なる。

デフォルト最大ヒープサイズ(-Xmx)

物理メモリが248MB以下の場合

物理メモリの2分の1。
248MBは-XX:MaxHeapSize(デフォルト124MB) x -XX:MinRAMFraction(デフォルト2)の値。

物理メモリが248MBより大きい場合

物理メモリの4分の1。
4分の1というのは-XX:MaxRAMFraction(デフォルト4)の値。例えば以下のようなオプションを指定した場合は、物理メモリの8分の1をエルゴノミクスで決められる最大ヒープサイズとすることが可能。

java -XX:MaxRAMFraction=8 ...

上限値は、デフォルトで29GB。デフォルト有効化されているOop圧縮を-XX:-UseCompressedOopsで明示的に無効化している状況では32GB。

この29GBは、同じargument.cppにあるmax_heap_for_compressed_oops()で計算されたOop圧縮有効時の最大ヒープサイズ(手元の環境では34357641216B/31GB)から、-XX:HeapBaseMinAddress(Linuxはデフォルト2GB)を引いた値。

デフォルト初期ヒープサイズ(-Xms)

物理メモリが384MB以下の場合

6MB。
物理メモリの64分の1の値が-XX:OldSize(デフォルト5MB) + -XX:NewSize(デフォルト1MB)の6MBを下回る場合は、初期ヒープサイズは6MBに設定される。

物理メモリが384MBより大きい場合

物理メモリの64分の1。
MaxRAMFractionと同様に、以下のようにオプション-XX:MinRAMFractionを設定すると、物理メモリの8分の1をエルゴノミクスで決められる初期ヒープサイズにすることが可能。

java -XX:MinRAMFraction=8 ...

ここまでの内容を踏まえて、例えば物理メモリ32GBの場合、何もオプションを指定しないと以下と同等です。思ったより最大ヒープサイズが大きいなと思う方も多いと思います。

java -Xms512m -Xmx8g ...

まとめ

64bitJVMのエルゴノミクスの挙動は、物理メモリ128GBまでは積むほど最大ヒープサイズが大きくなります。WebサーバやDBは、メモリを積むほど動作が軽快になることが多いです。しかし、Javaに限っては-Xms -Xmxが設定されていないと、4多重以上のJavaプロセス起動によりスワップが出続けるようなことが起こり得ます。

特にバッチタスクのように、並行で多数JVMを起動させる場合は注意が必要です。