2.2.5 Javaヒープ内に一定期間存在するオブジェクトの扱いの検討
これまでの説明は,オブジェクトの寿命に応じて,それぞれの領域に次のように格納することを前提としてきました。
-
アプリケーションの動作に必要な寿命の長いオブジェクトは,Tenured領域に格納する。
-
リクエスト処理やレスポンス処理などの寿命の短いオブジェクトは,New領域に格納する。
しかし,寿命が中間的な一定期間使用されるオブジェクトがあります。このようなオブジェクトは,寿命は長くありませんが,何回かのCopyGCの対象になります。
メモリサイズの見積もりでは,これらのオブジェクトを,New領域,Tenured領域のどちらかに格納することを前提として,見積もりをする必要があります。
ここでは,それぞれの特徴を示します。アプリケーションの種類や目的に応じて,どちらかのメモリサイズを増加させるように見積もりをしてください。
(1) Javaヒープ内のNew領域に格納する方法
一定期間存在するオブジェクトをNew領域で管理する方法です。New領域のメモリサイズに,これらの一定期間存在するオブジェクト分のメモリサイズを追加して見積もります。
New領域サイズを大きくしてオブジェクトのTenured領域への移動を抑止することによって,FullGCの発生も抑止できます。ただし,CopyGC実行時にNew領域内にある使用中オブジェクトの数が増えるため,New領域内でのコピー処理に時間が掛かり,1回当たりのCopyGC実行時間は長くなります。CopyGCの実行時間がFullGC実行時間よりも長くなるような場合は,メモリサイズの再見積もりが必要です。また,メモリ空間のサイズ設定によっては,本来CopyGCで回収されるはずの寿命の短いオブジェクトが使用する領域が不足して,Tenured領域への退避が発生するおそれがあります。この場合は,最終的にはFullGCが発生してしまいます。
なお,一定期間存在するオブジェクトをNew領域で管理できているかどうかは,拡張verbosegc情報で確認できます。実際にアプリケーションを動作させて,出力された拡張verbosegc情報で,CopyGC発生後のTenured領域のメモリサイズが大幅に増えていないことを確認してください。
New領域での管理に失敗している場合,システムの処理性能が大幅に低下していることがあります。また,New領域で管理できるオブジェクトの最大の年齢には限界があります(限界はプラットフォームやバージョンによって異なります。詳細は,マニュアル「uCosminexus Application Runtime ユーザーズガイド」を参照し,Java HotSpot VMの-XX:MaxTenuringThreshold=<value>オプションのデフォルト値に関する説明を確認してください)。New領域で管理できていないことが分かった場合は,一定期間存在するオブジェクトは,Tenured領域に格納して管理することを検討してください。Tenured領域で管理する方法については,「2.2.5(2) Javaヒープ内のTenured領域に格納する方法」を参照してください。
(2) Javaヒープ内のTenured領域に格納する方法
New領域で管理するオブジェクトの最大の年齢は,-XX:MaxTenuringThreshold=<value>オプションで指定できます。例えば,「-XX:MaxTenuringThreshold=2」を指定しておけば,3回目のCopyGCの対象になったオブジェクトは,すべてTenured領域に移動します。
この方法を使用すると,CopyGCの対象になるオブジェクトが少なくなり,実行時間が短縮できます。ただし,多くのオブジェクトがTenured領域に移動するため,Tenured領域がいっぱいになった段階でFullGCが発生します。システムを安定して動作させるためには,システムに掛かる負荷が低いときなどに,FullGCを強制的に発生させてください。FullGCを強制的に発生させるには,次の方法があります。
-
プログラム内でSystem.gc()メソッドを呼び出す
-
javagcコマンドを実行する
javagcコマンドの詳細については,「javagc(GCの強制発生)」を参照してください。