7.14.5 Explicitメモリブロック明示解放処理時にJavaヒープへのオブジェクト移動が発生した場合の確認と対処
Explicitメモリブロック明示解放処理時に,解放対象のExplicitヒープ内のオブジェクトに対する参照があると,参照されているオブジェクトおよびそのオブジェクトから直接または間接的に参照されているオブジェクトがJavaヒープに移動します。オブジェクトは,Tenured領域に優先的に移動されます。このため,移動が多いとTenured領域の利用済みサイズが増加して,FullGC発生の要因となってしまいます。
Javaヒープへの移動が発生したかどうかは,JavaVMログファイルの拡張verbosegc情報または明示管理ヒープイベントログで調査できます。
(1) 拡張verbosegc情報を使用した確認
明示管理ヒープ機能を利用しない場合,Tenured領域の利用済みサイズの増加は,CopyGCだけで発生します。このため,N回目のCopyGC終了後のTenured領域利用済みサイズは,N+1回目のCopyGC開始前のTenured領域利用済みサイズと一致します。
これに対して,ExplicitヒープからJavaヒープへのオブジェクトの移動が発生した場合は,Explicitヒープ解放時にTenured領域の利用済みサイズが増加します。この差分から,Explicitメモリブロック明示解放処理時にオブジェクトの移動が発生したことが確認できます。
N回目のCopyGC終了後のExplicitメモリブロック明示解放処理時にJavaヒープに移動したオブジェクトのサイズは,次の式で算出できます。
ExplicitヒープからJavaヒープに移動したオブジェクトのサイズ =N+1回目のCopy GC前のTenured領域利用済みサイズ -N回目のCopy GC後のTenured領域利用済みサイズ
(2) 明示管理ヒープのイベントログを使用した確認
JavaVMの-XX:HitachiExplicitMemoryLogLevelオプションに「none」以外を指定した場合,Explicitメモリブロックの明示解放処理についてのログが出力されます。このログでは,Explicitメモリブロック明示解放処理時のTenured領域利用済みサイズの増加を直接確認できます。
出力例を次に示します。
[ENS]<Tue Jul 24 01:23:51 2007>[EH: 12800K->11776K(11776K/65536K), 0.1129602 secs][E/F/D: 523/0/0]\ [DefNew::Eden: 0K->0K(243600K)][DefNew::Survivor: 0K->0K(17400K)][Tenured: 103400K->103464K(556800K)][cause:Reclaim]
背景色付きの太字で示した部分のうち,[cause:Reclaim]は,Explicitメモリブロック明示解放処理時に出力された情報であることを示します。また,[DefNew::Eden: 0K->0K(243600K)][DefNew::Survivor: 0K->0K(17400K)][Tenured: 103400K->103464K(556800K)]の部分は,Explicitメモリブロック明示解放処理時のJavaヒープの変化を示しています。この例の場合は,Tenured領域のメモリサイズが103,400キロバイトから103,464キロバイトに,64キロバイト分増えています。このことから,Explicitメモリブロックの明示解放処理で,64キロバイトのオブジェクトがJavaヒープに移動していることがわかります。
また,JavaVMの-XX:HitachiExplicitMemoryLogLevelオプションに「verbose」を指定した場合,解放されたExplicitメモリブロックについての情報も出力されます。これによって,どのExplicitメモリブロックの解放でTenured領域利用済みサイズが増加したかを確認できます。
出力例を次に示します。
[ENS]<Tue Jul 24 01:23:51 2007>[EH: 12800K->11776K(11776K/65536K), 0.1129602 secs][E/F/D: 523/0/0]\ [DefNew::Eden: 0K->0K(243600K)][DefNew::Survivor: 0K->0K(17400K)][Tenured: 103400K->103464K(556800K)][cause:Reclaim] [EVS]["REM2" eid=2/R: 320K]["BEM3" eid=5/B: 320K]["BEM1" eid=7/B: 384K]
背景色付きの太字で示した部分が,解放されたExplicitメモリブロックを示しています。出力内容から,Javaヒープに移動した64キロバイトのオブジェクトが,「REM2」「BEM3」「BEM1」のどれかのExplicitメモリブロックから移動したことがわかります。
さらに,JavaVMの-XX:HitachiExplicitMemoryLogLevelオプションに「debug」を指定した場合,明示解放処理をしたときに解放対象Explicitヒープ内のオブジェクトを参照していたオブジェクトが確認できます。
出力例を次に示します。
[EDO][eid=3: Reference to ClassZ(0x1234680), total 64K] [EDO] ClassU(0x1233468)(Tenured)
[eid=3: Reference to ClassZ(0x1234680), total 64K]の部分から,次のことがわかります。
-
Javaヒープへ移動したオブジェクトは"ClassZ"のインスタンスである。
-
"ClassZ"のインスタンスから参照されていることによってJavaヒープに移動したオブジェクトの合計サイズは64キロバイトである。
また,「ClassU(0x1233468)(Tenured)」の部分から,"ClassZ"のインスタンスを参照しているオブジェクトが"ClassU"のインスタンスであることがわかります。
これらの情報を基に,Explicitメモリブロック明示解放処理時にそのExplicitメモリブロック内のオブジェクトへの参照をなくすように,Javaプログラムを修正してください。