7.14.6 Explicitメモリブロックの自動解放処理が長時間化した場合の確認と対処
Explicitメモリブロックの自動解放処理が長時間化した場合の確認と対処について説明します。
Explicitメモリブロックの自動解放処理は,GCと同じタイミングで発生し,自動解放処理中はJ2EEサーバの処理が停止します。このため,自動解放処理が長時間化すると,システム上問題となることがあります。
巨大なサイズを持つExplicitメモリブロック(以降,巨大ブロックといいます)が生成されると,自動解放処理に長時間掛かるようになります。巨大ブロックは,アプリケーションの停止まで使用されるオブジェクトなど,FullGCでも回収されないオブジェクトがExplicitヒープに配置されると生成されることがあります。このため,Explicitヒープに配置しないほうがよいオブジェクトはJavaヒープに配置するようにして,巨大ブロックの生成を防止する必要があります。巨大ブロックが生成されて自動解放処理が長時間化してしまう現象については,マニュアル「アプリケーションサーバ 機能解説 拡張編」の「7.10.2 自動解放処理に掛かる時間を短縮する仕組み」,および「付録B.1 Explicitメモリブロックの自動解放処理への影響」を参照してください。
巨大ブロックが生成されているかどうかは,スレッドダンプの内容から調査できます。
巨大ブロックが生成されている場合は,次に示す対処手順に従って,巨大ブロックの要因となるオブジェクトをJavaヒープに配置するように設定してください。
- 対処手順
-
-
Explicitメモリブロックへのオブジェクト移動制御機能の適用
-
明示管理ヒープ機能適用除外クラス指定機能の適用
-
巨大ブロックの要因となるオブジェクトの特定とそのオブジェクトのExplicitヒープへの移動防止
-
Javaヒープ領域およびExplicitヒープ領域の再チューニング
-
ここでは,巨大ブロックが生成されているかどうかの確認方法と,対処方法について説明します。
- 〈この項の構成〉
(1) 巨大ブロックが生成されているがどうかの確認
eheapprofコマンドを実行して,スレッドダンプに出力されたExplicitヒープ情報を確認します。
出力例を次に示します。
"NULL" eid=1(0x1000000000123456)/B, total 112K, used 55K, garbage 0K (49.2% used/total, 0.0% garbage/used, 0 blocks) Enable "NULL" eid=2(0x1000000000223456)/A, total 153744K, used 144766K, garbage 0K (94.2% used/total, 0.0% garbage/used, 0 blocks) Enable "ReferenceExplicitMemory-2" eid=3(0x1000000000323456)/R, total 112K, used 55K, garbage 0K (49.3% used/total, 0.0% garbage/used, 0 blocks) Enable
- 注
-
Explicitメモリブロックの名称の"NULL"は,一度自動解放処理を実施したExplicitメモリブロックであることを示します。
背景色付きの太字で示した「total」の部分がExplicitヒープの確保済みメモリサイズを示します。
この例の場合,各Explicitメモリブロックの「total」に示すメモリサイズは,eid=2のExplicitメモリブロックは153,744キロバイトであり,eid=1やeid=3のExplicitメモリブロックの112キロバイトに比べて,極端に大きなサイズになっています。このことから,巨大ブロックが生成され,それがeid=2のExplicitメモリブロックであることがわかります。
(2) Explicitメモリブロックへのオブジェクト移動制御機能の適用
明示管理ヒープ機能のイベントログでExplicitヒープの利用状況の推移を調査します。Explicitヒープの利用状況の推移の調査方法については,「7.14.2 利用状況の推移の調査」を参照してください。
出力例を次に示します。
[ENS]<Thu Oct 21 14:55:50 2007>[EH: 12672K->172032K(172032K/196608K)][E/F/D: 200/0/0][cause:Full GC][CF: 0] [ENS]<Thu Oct 21 14:55:50 2007>[EH: 172032K->172032K(172032K/196608K), 0.1124626 secs][E/F/D: 200/0/0]\ [DefNew::Eden: 0K->0K(243600K)][DefNew::Survivor: 0K->0K(17400K)][Tenured: 103400K->103400K(556800K)]\ [target:584K/0K/584K][cause:Migrate]
背景色付きの太字で示した「EH:」で始まる部分が,Explicitヒープの利用状況を示します。
この例の場合,「cause:」で始まる部分に示すとおり,1行目はFullGC発生時に出力されたログで,その直後にある2行目はExplicitメモリブロックの自動解放処理(Migrate)時に出力されたログです。このことから,FullGCの直後に自動解放処理が発生したことがわかります。1行目のログの「EH:」で始まる部分から,FullGC発生前のExplicitヒープの利用済みサイズは12,672キロバイト,発生後のExplicitヒープの利用済みサイズは172,032キロバイトであり,Explicitヒープの使用サイズが大幅に増加していることがわかります。なお,このような現象(Explicitヒープの使用サイズの大幅な増加)が発生していない場合は,手順(3)に進んでください。
この例のように,FullGC発生時にExplicitヒープの使用サイズが大幅に増加している場合は,-XX:ExplicitMemoryFullGCPolicyオプションに1を指定して,Explicitメモリブロックへのオブジェクト移動制御機能を適用してください。この機能を適用すると,FullGC発生時に参照関係に基づくオブジェクトをExplicitメモリブロックへ移動しなくなります。Explicitメモリブロックへのオブジェクト移動制御機能については,マニュアル「アプリケーションサーバ 機能解説 拡張編」の「7.10 Explicitメモリブロックの自動解放処理に掛かる時間の短縮」を参照してください。
この機能を適用して,巨大ブロックの生成を防止できるようになった場合は手順(5)に,巨大ブロックがまだ生成されている場合は手順(3)に進んでください。
(3) 明示管理ヒープ機能適用除外クラス指定機能の適用
次の現象が発生している場合は,-XX:+ExplicitMemoryUseExcludeClassオプションを指定して,明示管理ヒープ機能適用除外クラス指定機能を適用してください。
-
自動解放処理直前に実施されたFullGCのExplicitヒープの利用状況で,Explicitヒープの使用サイズに大幅な増加が見られない
-
Explicitメモリブロックへのオブジェクト移動制御機能を適用(手順(2)を実施)しても,巨大ブロックが生成されている
明示管理ヒープ機能適用除外クラス指定機能を適用すると,特定のクラスのオブジェクトをExplicitヒープへ移動させなくなります。特定のクラスのオブジェクトとは,システムで提供している明示管理ヒープ機能適用除外設定ファイル(sysexmemexcludeclass.cfg)に記述されているクラスのオブジェクトのことです。明示管理ヒープ機能適用除外クラス指定機能については,マニュアル「アプリケーションサーバ 機能解説 拡張編」の「7.10 Explicitメモリブロックの自動解放処理に掛かる時間の短縮」を参照してください。
この機能を適用して,巨大ブロックの生成を防止できるようになった場合は手順(5)に,巨大ブロックがまだ生成されている場合は手順(4)に進んでください。
(4) 巨大ブロックの要因となるオブジェクトの特定とそのオブジェクトのExplicitヒープへの移動防止
手順(3)で明示管理ヒープ機能適用除外クラス指定機能を適用しても,巨大ブロックがまだ生成されている場合は,次に示すオブジェクトがExplicitヒープに移動されて,巨大ブロックが生成されていることがあります。これらのオブジェクトのうち生存し続けるオブジェクトは,Explicitメモリブロックの自動解放処理で回収されません。
-
Javaアプリケーション内のユーザ作成クラスのオブジェクト
-
使用しているフレームワークによって自動的に作成されるオブジェクト
このため,これらの一定期間で回収されないオブジェクトをExplicitヒープに配置しても明示管理ヒープ機能の効果がないため,Javaヒープ(Tenured領域)に配置する方が適切です。これらのオブジェクトのうち,巨大ブロックの要因となっているオブジェクトを特定し,Explicitヒープへ移動しないようにします。
巨大ブロックの要因となるオブジェクトを特定する場合,オブジェクト解放率情報を調査します。オブジェクト解放率情報は,Explicitメモリブロックの自動解放処理で解放されたオブジェクトの割合です。eheapprofコマンドに-freeratioオプションを指定して実行すると,スレッドダンプに出力されたExplicitヒープ情報にオブジェクト解放率情報が出力されます。
出力例を次に示します。
"NULL" eid=1(0x1000000000123456)/B, total 112K, used 55K, garbage 0K (49.2% used/total, 0.0% garbage/used, 0 blocks) Enable deployed objects ________________Size__Instances__FreeRatio__Class________________ 49256 10 0 [B 3680 4 20 package1.session.StandardManager 52936 14 total "NULL" eid=2(0x1000000000223456)/A, total 153744K, used 144766K, garbage 0K (94.2% used/total, 0.0% garbage/used, 0 blocks) Enable deployed objects ________________Size__Instances__FreeRatio__Class________________ 77862918 433523 10 [C 52622946 441714 10 java.lang.String 12838192 39462 35 [B 3680 4 20 package1.session.StandardManager 104 4 0 framework.ut.impl.performList 143327840 914707 total "ReferenceExplicitMemory-2" eid=3(0x1000000000323456)/R, total 112K, used 55K, garbage 0K (49.3% used/total, 0.0% garbage/used, 0 blocks) Enable deployed objects ________________Size__Instances__FreeRatio__Class________________ 49256 4 - [B 3416 10 - package3.ajp.RequestHandler 64 2 - java.lang.StringBuffer 64 1 - java.net.SocketInputStream 48 1 - [I 24 1 - [C 52872 19 total
- 注1
-
Explicitメモリブロックの名称の"NULL"は,一度自動解放処理を実施したExplicitメモリブロックであることを示します。
- 注2
-
クラス名の[BはByteクラスの配列型,[CはCharクラスの配列型,[IはIntegerクラスの配列型を示します。
背景色付きの太字で示した「total」の部分がExplicitヒープの確保済みメモリサイズを,「FreeRatio」の部分がオブジェクト解放率情報を示します。
この例の場合,Explicitメモリブロックは,eid=1,eid=2,eid=3の三つがあります。各Explicitメモリブロックの「FreeRatio」に示すオブジェクト解放率情報を見てみると,eid=3のExplicitメモリブロックのオブジェクト解放率情報は「-」で,自動解放処理が実行されなかったことがわかります。
まず,各Explicitメモリブロックの「total」に示すメモリサイズを見てみます。eid=2のExplicitメモリブロックは153,744キロバイトであり,eid=1やeid=3のExplicitメモリブロックの112キロバイトに比べて,極端に大きなサイズになっています。このことから,eid=2のExplicitメモリブロックが巨大ブロックであることがわかります。
次に,巨大ブロック(eid=2)内のオブジェクトのクラスごとに,オブジェクト解放率とExplicitメモリブロック内のサイズを見てみます。この例では,五つのオブジェクトがあり,そのオブジェクトのクラスにはJava SEが提供しているクラス(「[B」,「[C」,「java.lang.String」)も含まれています。ほとんどの場合,Java SEが提供しているクラスは,巨大ブロックの要因となるオブジェクトから参照されてExplicitメモリブロックへ移動します。このため,巨大ブロックの要因となるオブジェクトをExplicitメモリブロックへ移動しないようにすれば,Java SEが提供しているクラスのオブジェクトの移動も防止できます。また,Java SEが提供しているクラスを明示管理ヒープ機能適用除外クラス指定機能の対象にすると,影響範囲が広く,理想的なExplicitメモリブロック上に配置されたオブジェクトにも制約が生じます。そのため,Java SEが提供しているクラスは,明示管理ヒープ機能適用除外クラス指定機能の対象にしないでください(ただし,Java SEが提供しているクラスのオブジェクトすべてをJavaヒープに配置しても問題ない場合は除きます)。
Java SEが提供しているクラス以外のクラスには,「package1.session.StandardManager」と「framework.ut.impl.performList」があります。「package1.session.StandardManager」のオブジェクトはeid=1のExplicitメモリブロックでも使用されていますが,eid=1は巨大ブロックになっていません。このことから,このクラスのオブジェクトは巨大ブロックの要因とならないことがわかります。これによって,「framework.ut.impl.performList」のオブジェクトが,巨大ブロックの要因となるオブジェクトであると特定できます。
巨大ブロックの要因となるオブジェクトを特定したあと,明示管理ヒープ機能適用除外クラス指定機能で使用する設定ファイルに,そのオブジェクトのクラスを記述してください。設定ファイルへの記述方法については,マニュアル「アプリケーションサーバ 機能解説 拡張編」の「7.13.3 設定ファイルを使った明示管理ヒープ機能の適用対象の制御」を参照してください。
(5) Javaヒープ領域およびExplicitヒープ領域の再チューニング
オブジェクト移動制御機能や,明示管理ヒープ機能適用除外クラス指定機能を適用すると,オブジェクトの配置される領域が変わり,JavaヒープおよびExplicitヒープのメモリサイズにも増減が発生します。このため,次の個所で説明している方法を参照して,再度,各領域のメモリサイズをチューニングしてください。