2.2.3 Javaヒープ内のTenured領域のメモリサイズの見積もり
SerialGC使用時のTenured領域のメモリサイズの見積もりについて説明します。
Tenured領域のメモリサイズは,次のように見積もります。
Tenured領域のメモリサイズ =アプリケーションで必要なメモリサイズ+New領域のメモリサイズ
ここでは,アプリケーションで必要なメモリサイズの算出方法について説明します。また,見積もったメモリサイズにNew領域のメモリサイズを追加する理由についても説明します。
(1) アプリケーションで必要なメモリサイズの算出
Tenured領域のメモリサイズは,アプリケーションが最低限必要とするメモリサイズから見積もります。必要なメモリサイズが確保できない場合,OutOfMemoryErrorが発生してJavaVMが停止します。
アプリケーションが必要とするメモリサイズは,FullGC実行時の拡張verbosegc情報で,FullGC実行後に使用しているメモリサイズを確認することで判断できます。これは,FullGC実行後にJavaヒープ全体から不要なオブジェクトをすべて削除した状態のメモリサイズが,アプリケーションが必要とするメモリサイズに近いと考えられるためです。
FullGC実行時の拡張verbosegc情報の出力例を次に示します。
… [VGC]<Wed May 11 23:12:05 2005>[Full GC 31780K->30780K(32704K), 0.2070500secs][DefNew::Eden: 3440K->1602K(3456K)][DefNew::Survivor:58K->0K(64K)][Tenured: 28282K->29178K(29184K)][Metaspace:3634K(4492K, 4492K)->3634K(4492K, 4492K)][class space: 356K(388K, 388K)->356K(388K, 388K)][cause:ObjAllocFail][User: 0.0156250 secs][Sys: 0.0312500 secs] …
「Full GC」に続いて出力されている情報のうち,GCの実行後の情報「->30780K」を確認します。ここでは,FullGC実行後に,30,780キロバイトのメモリサイズを必要としていることが分かります。
何回分かのFullGCの拡張verbosegc情報を集め,GC実行後のメモリサイズがいちばん大きい情報を,アプリケーションが必要とするメモリサイズであると判断してください。
(2) Javaヒープ内のNew領域のメモリサイズを追加する理由
Tenured領域のメモリサイズには,アプリケーションが最低限必要とするメモリサイズに,New領域分のメモリサイズを追加することをお勧めします。これは,Tenured領域の未使用メモリサイズがNew領域の使用メモリサイズを下回ることによって,FullGCが頻発するのを防ぐためです。
通常,Eden領域がいっぱいになると,CopyGCが発生します。このとき,Eden領域とSurvivor領域のFrom空間に存在する使用中のJavaオブジェクトが,Survivor領域のTo空間に移動しようとします。このとき,Tenured領域の未使用領域がEden領域とSurvivor領域で使用中のメモリサイズよりも小さいと,New領域のすべてのJavaオブジェクトが昇格した場合に,JavaオブジェクトをTenured領域に移動できなくなります。そこでJavaVMは,FullGCを発生させ,Tenured領域の未使用メモリサイズを増やそうとします。
これを防ぐために,Tenured領域には,アプリケーションが必要とするメモリサイズに加えて,New領域分のメモリサイズを追加してください。
考え方を次の図に示します。
|
-
オブジェクトが昇格できないおそれがあるためFullGCが発生する例
Tenured領域のメモリの空き領域(アプリケーションで必要なメモリ領域以外の領域)がNew領域のメモリサイズよりも小さいため,Eden領域およびFrom空間からの移動オブジェクトが多い場合,オブジェクトの昇格に対応できないおそれがあります。この場合,FullGCが発生します。
-
オブジェクトが確実に昇格できる例
Tenured領域のメモリの空き領域(アプリケーションで必要なメモリ領域以外の領域)がNew領域と同じサイズ分確保してあるため,Eden領域およびFrom空間からの移動オブジェクトが多い場合も,オブジェクトの昇格に対応できます。
なお,New領域のメモリサイズの見積もりについては,「2.2.4 Javaヒープ内のNew領域のメモリサイズの見積もり」で説明します。
- ヒント
-
拡張verbosegc情報などで確認したときに,CopyGCが発生しないでFullGCが頻発している場合,New領域からの退避オブジェクトに対してTenured領域のメモリサイズが小さいことが考えられます。New領域のサイズを増やした場合などにこの状態になることがあります。必要に応じて,Tenured領域のメモリサイズを見直してください。また,New領域内のEden領域とSurvivor領域の関係もあわせて見直してください。