Hitachi

uCosminexus Application Runtime - Cosminexus Developer's Kit for Java 機能解説・リファレンス


2.3.1 G1GCの仕組み

G1GCの仕組みを説明します。

〈この項の構成〉

(1) G1GCの概要

GCは,プログラムが使用し終わったメモリ領域を自動的に回収して,ほかのプログラムが利用できるようにするための技術です。

GCの実行中は,プログラムの処理が停止します。このため,GCを適切に実行できるかどうかが,システムの処理性能に大きく影響します。

プログラムの中でnewによって作成されたJavaオブジェクトは,JavaVMが管理するメモリ領域に格納されます。Javaオブジェクトが作成されてから不要になるまでの期間を,Javaオブジェクトの寿命といいます。

Javaオブジェクトには,寿命の短いオブジェクトと寿命の長いオブジェクトがあります。サーバサイドで動作するJavaアプリケーションの場合,リクエストやレスポンス,トランザクション管理などで,多くのJavaオブジェクトが作成されます。これらのJavaオブジェクトは,その処理が終わると不要になる,寿命が短いオブジェクトです。一方,アプリケーションの動作中使用され続けるJavaオブジェクトは,寿命が長いオブジェクトです。

効果的なGCを実行するためには,寿命の短いオブジェクトに対してGCを実行して,効率良くメモリ領域を回収することが必要です。また,繰り返し使用される寿命の長いオブジェクトに対する不要なGCを抑止することが,システムの処理性能の低下防止につながります。これを実現するのが,世代別GCです。

世代別GCでは,Javaオブジェクトを,寿命が短いオブジェクトが格納されるNew領域と,寿命が長いオブジェクトが格納されるTenured領域に分けて管理します。New領域はさらに,newによって作成されたばかりのオブジェクトが格納されるEden領域と,1回以上のGCの対象になり,回収されなかったオブジェクトが格納されるSurvivor領域に分けられます。New領域内で一定回数以上のGCの対象になったJavaオブジェクトは,長期間必要なJavaオブジェクトと判断され,Tenured領域に移動します。

世代別GCで管理するメモリ空間とJavaオブジェクトの概要を次の図に示します。

図2‒12 世代別GCで管理するメモリ空間とJavaオブジェクトの概要

[図データ]

G1GCの世代別GCで実行されるGCには,次の3種類があります。

一般的に,YoungGCとMixedGCの方が,FullGCよりも短い時間で処理できます。

次に,GCの処理について,あるJavaオブジェクト(オブジェクトA)を例にして説明します。

Eden領域で実行される処理

オブジェクトAの作成後,1回目のYoungGCまたはMixedGCが実行された時点で使用されていない場合,オブジェクトAは破棄されます。

1回目のYoungGCまたはMixedGCが実行された時点で使用されていた場合,オブジェクトAはEden領域からSurvivor領域に移動します。

Survivor領域で実行される処理

Survivor領域に移動したオブジェクトAは,そのあと何回かYoungGCまたはMixedGCが実行されると,Survivor領域からTenured領域に移動します。移動する回数のしきい値は,JavaVMオプションやJavaヒープの利用状況によって異なります。「図2-12」では,しきい値をn回としています。

Survivor領域への移動後,n回目未満のYoungGCまたはMixedGCが実行された時点でオブジェクトAが使用されていなかった場合,オブジェクトAはそのYoungGCまたはMixedGCで破棄されます。

Tenured領域で実行される処理

オブジェクトAがTenured領域に移動した場合,そのあとのYoungGCでオブジェクトAが破棄されることはありません。YoungGCは,Eden領域とSurvivor領域だけを対象としているためです。MixedGCが発生した場合は,Tenured領域内の一部のオブジェクトが破棄されます。

MixedGCで破棄されるオブジェクトの数よりも,Tenured領域に移動するオブジェクトの数が多い場合,Tenured領域の使用サイズは増加します。新たにTenured領域を確保できなくなると,FullGCが発生します。

JavaVMのチューニングでは,JavaVMオプションでそれぞれのメモリ空間のサイズや割合を適切に設定することで,不要なオブジェクトがTenured領域に移動することを抑止します。これによって,FullGCが頻発することを防ぎます。

(2) オブジェクトの寿命と年齢の関係

オブジェクトがYoungGCまたはMixedGCの対象になった回数をオブジェクトの年齢といいます。

オブジェクトの寿命と年齢の関係を次の図に示します。

図2‒13 オブジェクトの寿命と年齢の関係

[図データ]

アプリケーションが開始して初期化処理が完了したあとで,何度かのYoungGCまたはMixedGCが実行されると,長期間必要になる寿命の長いオブジェクトはTenured領域に移動します。このため,アプリケーションの開始後しばらくすると,Javaヒープの状態は安定し,作成されるJavaオブジェクトとしては,寿命が短いオブジェクトが多くなります。特に,New領域のチューニングが適切にできている場合,Javaヒープが安定したあとの大半のオブジェクトは,1回目のYoungGCまたはMixedGCで回収される,寿命が短いオブジェクトになります。

(3) New領域を対象としたGCの仕組み

JavaVMでは,YoungGCまたはMixedGCの対象になるNew領域のメモリ空間を,Eden領域,Survivor領域に分けて管理します。さらに,Survivor領域は,From空間とTo空間に分けられます。From空間とTo空間は,同じメモリサイズです。

New領域の構成を次の図に示します。

図2‒14 New領域の構成

[図データ]

Eden領域は,newによって作成されたオブジェクトが最初に格納される領域です。プログラムでnewが実行されると,Eden領域のメモリが確保されます。

Eden領域がいっぱいになると,YoungGCまたはMixedGCが実行され,次の処理が実行されます。

  1. Eden領域およびSurvivor領域のFrom空間にあるJavaオブジェクトのうち,使用中のJavaオブジェクトが,Survivor領域のTo空間にコピーされます。使用されていないJavaオブジェクトは破棄されます。

  2. Survivor領域のTo空間とFrom空間が入れ替わります。

この結果,Eden領域とTo空間は空になり,使用中のオブジェクトはFrom空間に存在することになります。

YoungGCまたはMixedGC実行時に発生するオブジェクトの移動を次の図に示します。

図2‒15 CopyGC実行時に発生するオブジェクトの移動

[図データ]

このようにして,使用中のオブジェクトは,YoungGCまたはMixedGCが発生するたびに,From空間とTo空間を行ったり来たりします。ただし,寿命の長いオブジェクトを行き来させ続けると,移動処理の負荷などが問題になります。これを防ぐために,From空間とTo空間でJavaオブジェクトを入れ替える回数にしきい値を設定して,年齢がしきい値に達したJavaオブジェクトはTenured領域に移動させるようにします。

(4) オブジェクトの退避

年齢がしきい値に達していないJavaオブジェクトがTenured領域に移動することを,退避といいます。退避は,YoungGCまたはMixedGC実行時にEden領域およびFrom空間で使用中のオブジェクトが多くなり,移動先であるTo空間のメモリサイズが不足する場合に発生します。この場合,To空間に移動できなかったオブジェクトが,Tenured領域に移動します。

図2‒16 オブジェクトの退避

[図データ]

オブジェクトの退避が発生した場合,Tenured領域に本来格納されないはずの寿命の短いオブジェクトが格納されます。これが繰り返されると,YoungGCまたはMixedGCで回収されるはずのオブジェクトがメモリ空間に残っていくため,Javaヒープのメモリ使用量が増加していき,最終的にはFullGCが発生します。

オブジェクトの退避が発生した場合のメモリ使用量の変化について,次の図に示します。

図2‒17 オブジェクトの退避が発生した場合のメモリ使用量の変化

[図データ]

FullGCでは,システムが数秒から数十秒停止することがあります。

したがって,メモリ空間の構成とメモリサイズを検討するときには,オブジェクトの退避が発生しないように,Eden領域とSurvivor領域のバランスを検討する必要があります。

(5) メモリ空間とリージョンの関係

G1GCで管理するJavaヒープ領域は,オブジェクトの寿命が短いオブジェクトが格納されるNew領域と,寿命が長いオブジェクトが格納されるTenured領域に分けて管理します。このうちNew領域はさらに2つの領域に分けて管理されており,作成されたばかりのオブジェクトが格納されるEden領域と,1回以上のGCの対象になり,回収されなかったオブジェクトが格納されるSurvivor領域に分けられます。New領域内で一定回数以上のGCの対象になったオブジェクトは,寿命が長いオブジェクトと判断され,Tenured領域に移動します。

アプリケーション実行中のG1GCで管理するメモリ空間の構成を次の図に示します。なお,Eden領域,Survivor領域,Tenured領域,Free領域を合わせた領域をJavaヒープ領域といいます。

図2‒18 アプリケーション実行中のG1GCで管理するメモリ空間の構成

[図データ]

G1GCでは,Tenured領域があらかじめ割り当てられていません。Tenured領域にオブジェクトを移動させる場合,Free領域のリージョンをTenured領域に割り当ててオブジェクトを移動します。また,G1GCではGC後にNew領域に対して拡張や縮小をします(以降,リサイズと表記します)。リサイズでNew領域を拡張する場合は,Free領域のリージョンに割り当て,縮小する場合はNew領域のリージョンを回収し,Free領域に割り当てます。サイズの大きなオブジェクトを作成する場合は,Humongous領域にオブジェクトが格納されます。

各領域の用途を次に示します。

図2-18」はJavaヒープ領域の各領域を連続領域として表現していますが,実際には各領域は連続領域として確保されていません。G1GCではJavaヒープ領域をリージョンと呼ばれるブロック単位で管理しており,次の図のように領域が分散して確保されています。

図2‒19 実際のメモリ空間の構造

[図データ]

ここではそれぞれの領域のリージョンを領域名+リージョンと表記します。例えば,Eden領域のリージョンをEdenリージョン,New領域のリージョンはNewリージョンと表記します。

(6) リージョンの使われ方

オブジェクトが作成されると,最初にEdenリージョンに格納されます。1つのオブジェクトのサイズが,リージョンサイズの半分を超えている大きいオブジェクトの場合は,1つのオブジェクトに対し,連続した複数のリージョンが割り当てられ格納されます。連続した複数のリージョンはFree領域から確保され,Humongous領域に割り当てられます。Humongous領域はFullGCまたはConcurrent Cleanupでだけ回収の対象となるため,サイズの大きなオブジェクトが多数作成されるような場合には,G1GCは不向きとなります。詳細については,「2.3.2(3)(a) FullGCの発生を抑止する考え方」を参照してください。

また,1つのリージョンのサイズは,起動時にJavaヒープ領域の初期サイズの比率から求められ,起動中は固定です。1つのリージョンの最小サイズは1MBであり,最大サイズは32MBです。

注※

ここでいうサイズの大きな1つのオブジェクトとは,多数のインスタンスフィールドを持つオブジェクトや長大な配列を持つオブジェクトのことを指します。リージョンのサイズが1MBの場合,512KBを超えるようなオブジェクトを指し,例えば約13万個のint型のインスタンスフィールドを持つようなオブジェクトや約50万個の要素数のバイト配列を持つオブジェクトなどが当てはまります。

リージョンの使用から回収までの流れを次の図に示します。

図2‒20 リージョンの使われ方

[図データ]

この図はリージョンの使われ方を示した図です。図の1.〜4.の処理の詳細を次に示します。

  1. オブジェクト作成時

    オブジェクトが作成される場合,Edenリージョンにオブジェクトを格納します。サイズの大きなオブジェクトを作成する場合は,FreeリージョンをHumongousリージョンに割り当てオブジェクトを格納します。Edenリージョンに空き領域がなくなると,新しいEdenリージョンにオブジェクトを格納し,Humongousリージョンに空き領域がなくなると,新たにFreeリージョンからHumongousリージョンを割り当て,オブジェクトを格納します。

  2. GC時の選択処理

    GCの要件を満たすと,実行するGC方式の基準に従って,対象とするリージョンを選択します。

  3. GC時のEvacuation

    回収の対象となったリージョン内で使用中のオブジェクトは,ほかのリージョンにコピーされます。この処理をEvacuationといいます。Evacuation後のリージョンは,使用済みのオブジェクトとコピー済みである不要となったオブジェクトだけ格納されているため,リージョン単位で回収されます。

  4. GC後

    回収されたリージョンはFreeリージョンとなり,再利用されます。

(7) G1GCで実行されるGC

G1GCの世代別GCで実行されるGCには,次の3種類があります。

  1. YoungGC

    New領域を対象とするGCです。YoungGCにはYoungGC(normal)とYoungGC中にマーキングをするYoungGC(initial-mark)があります。詳細については,「(8) YoungGC」を参照してください。なお,単にYoungGCと表記した場合,YoungGC(normal)とYoungGC(initial-mark)の両方に当てはまる事項となります。また,YoungGC(normal)とYoungGC(initial-mark)を区別して表す場合は,“(normal)”と“(initial-mark)”を明記します。ただし,ログファイルのGC種別にはYoungGC(normal)はYoungGCという種別で出力します。YoungGCはJavaオブジェクトの作成によって,Eden領域を使い切ると発生します。

  2. MixedGC

    New領域とTenured領域を対象とするGCです。Tenuredリージョンは目標停止時間に合わせて部分的な範囲を対象とします。詳細については,「(10) MixedGC」を参照してください。MixedGCはYoungGC同様,Javaオブジェクトの作成によって,Eden領域を使い切ると発生しますが,Concurrent Markingと呼ばれるオブジェクトが使用中かどうかの解析処理の結果に基づいて発生します。詳細については,「2.3.1(9) Concurrent Marking(CM)」を参照してください。そのため,解析が十分にされていない場合や解析の結果MixedGCの効果が低いと予測される場合は,YoungGC(normal)が発生します。

  3. FullGC

    Tenured領域やMetaspace領域,Humongous領域を含む,JavaVM固有領域全体を対象にしたGCです。詳細については,「(11) FullGC」を参照してください。Tenured領域やMetaspace領域,Humongous領域を確保できなかった場合に発生します。

それぞれのGCが対象とする領域をまとめると次の図となります。

図2‒21 各GCの対象範囲

[図データ]

また,各GCの状態遷移図を次の図に示します。

図2‒22 各GCの状態遷移図

[図データ]

  1. YoungGC(normal)実行後,Concurrent Marking(CM)が実行されておらず,Tenured領域の使用率がJavaヒープ領域の45%を超えた場合は,次のGCではYoungGC(initial-mark)を実行する状態に遷移します。

  2. YoungGC(normal)実行後,CMが実行されておらず,Tenured領域の使用率がJavaヒープ領域の45%以下の場合は,次のGCもYoungGC(normal)を実行する状態のままです。

  3. YoungGC(initial-mark)実行後,次のGCではYoungGC(normal)とCMを並行して実行する状態に遷移します。

  4. CMが実行中の場合は,YoungGC(normal)を実行する状態のままです。

  5. CM終了直後のYoungGC(normal)で予測回収率が10%を超えている場合,次のGCではMixedGCを実行する状態に遷移します。

  6. 予測回収率が10%以下の場合,次のGCもYoungGC(normal)を実行する状態のままです。

  7. MixedGC実行後,予測回収率が10%を超えている場合,次のGCではMixedGCを実行する状態のままです。

  8. MixedGC実行後,予測回収率が10%以下の場合,次のGCではYoungGC(normal)を実行する状態に遷移します。

ただし,次の場合GCの状態に関係なく,条件を満たすと対応するGCを実行します。

次に,G1GCの処理の流れについて,Javaオブジェクトを例にして説明します。

図2‒23 G1GCの流れ

[図データ]

  1. YoungGC

    この図のようにNew領域に割り当てたリージョンに空きがなくなるとYoungGCが発生します。YoungGCでは使用中のオブジェクトはSurvivor領域に割り当てたリージョンに移動し,使用済みのオブジェクトはリージョンごと解放します。また,SerialGCのCopyGCと同様,YoungGC発生時に使用中のオブジェクトはSurvivor領域に割り当てたリージョン間を移動し続け,ある一定の回数を移動するとTenured領域に割り当てたリージョンに移動します。YoungGC後,上の図のようにGCに掛かった時間から,次のGCに掛かる時間を予測し,New領域のサイズを変更します。この図の場合は,予測した時間よりGCに掛かる時間が長いため,New領域を縮小した場合の例です。

  2. MixedGC

    Tenured領域の使用率が増加すると,MixedGCが発生します。MixedGCではNew領域に割り当てたリージョンに加えて,目標停止時間内に収まる範囲で,一部のTenured領域に割り当てたリージョンをGCの対象とします。この一部のTenured領域に割り当てたリージョンは,アプリケーションと並行して実行しているオブジェクトが使用中かどうかの解析情報に基づき,解放されるサイズが大きいと予測されるリージョンから優先してGCの対象となります。そのため,オブジェクトの情報解析が十分にされていない場合や解析の結果MixedGCの効果が低い場合は,MixedGCは発生しません。

  3. FullGC

    Javaヒープ内のリージョンに空きがなくなり,MixedGCが発生しない場合,Javaヒープ全体を対象としてFullGCが発生します。

(8) YoungGC

YoungGCの流れを次の図に示します。

図2‒24 YoungGCの流れ

[図データ]

(a) 実行契機

  1. YoungGC(normal)

    Eden領域にオブジェクトを確保できなかった場合に発生します。また,サイズの大きなオブジェクトをHumongous領域に確保できなかった場合にも発生します。

  2. YoungGC(initial-mark)

    直前に実行されたYoungGC(normal)終了時に,Tenured領域の使用サイズがJavaヒープ領域の45%を超えていた場合,1.の実行契機を満たすとYoungGC(initial-mark)が実行されます。また,サイズの大きなオブジェクトを確保時,Tenured領域の使用サイズとオブジェクトの確保サイズの合計サイズがJavaヒープ領域の45%を超えた場合,YoungGC(initial-mark)が実行されます。

(b) 対象範囲

New領域

(c) 処理内容

  • YoungGCが発生するとシングルスレッドでリージョンの選択処理をし,そのあとマルチスレッドでEvacuationをします。

  • YoungGCのEvacuationではEden領域とFrom空間内の使用中オブジェクトをTo空間またはTenured領域に移動し,Eden領域とFrom空間を回収します。移動や回収の仕組みはCopyGCの仕組みと同じです。CopyGCの詳細については,「2.2.1(3) CopyGCの仕組み」を参照してください。

  • YoungGCでは,これまでに発生したGCのGC停止時間の統計から予測をし,次回のGCの予測停止時間が目標停止時間内に収まるようにNew領域のサイズを変更します。

  • New領域は最小サイズと最大サイズが存在し,その範囲内でリサイズをします。New領域は全GCで対象となるため,GC停止時間はNew領域が最小サイズの場合に掛かるGC停止時間より短くすることはできません。

  • CMが終了後のYoungGCでは,予測回収サイズがJavaヒープ領域の10%を超えていた場合,次回のGCをMixedGCにするか判定します。次回のGCにMixedGCが選択された場合,Tenuredリージョンを多く対象とするように予測してNew領域のサイズを変更します。

  • YoungGC(initial-mark)のEvacuationではEvacuation中にローカル変数や使用中のオブジェクトから直接参照されているオブジェクトにマーク付けをします。このマーキングの結果は,Concurrent Markingに利用されます。Concurrent Markingの処理の詳細については,「(9) Concurrent Marking(CM)」を参照してください。

(d) 処理結果

Eden領域:オブジェクトが回収され,空になります。GC後リサイズされます。

Survivor領域:From空間のオブジェクトが回収され,空になります。GC後リサイズされます。

Tenured領域:長期間必要と判断されたオブジェクトがTenured領域に移動します。

Humongous領域:変化はありません。

Metaspace領域:変化はありません。

Free領域:GC後のリサイズによって,増減します。

(e) アプリケーションの停止の有無

停止します。

(f) ほかのGCとの関係

CM:YoungGC中に実行されません。

MixedGC:YoungGC中に実行されません。

FullGC:YoungGC中に実行要件を満たすと,YoungGCを中止して実行されます。

(g) 補足

  • 関連オプション

    Evacuationをするスレッド数は-XX:ParallelGCThreadsオプションで変更できます。スレッド数を増やすとYoungGCに掛かる時間が小さくなります。また,オプションを指定しない場合,スレッド数は-XX:ParallelGCThreadsオプションのデフォルト値が用いられます。-XX:ParallelGCThreadsオプションについては,「5.4 日立JavaVMで指定できるJava HotSpot VMのオプション」の「表5-9 指定できるJava HotSpot VMのオプション」にある「-XX:ParallelGCThreads」を参照してください。

  • 確認方法

    YoungGCの確認はログ上のGCの種別が“YoungGC”または“YoungGC(initial-mark)”であることから確認できます。また,New領域のリサイズはEden領域のサイズ変化とSurvivor領域のサイズ変化から確認できます。

    [VG1]<Wed Jun 12 11:21:10 2013>[Young GC 899070K/899072K(1048576K)->501755K/501760K(1048576K), 0.0931560 secs][Status:-][G1GC::Eden: 389120K(389120K)->0K(397312K)][G1GC::Survivor: 41984K->41984K][G1GC::Tenured: 459776K->459776K][G1GC::Humongous: 2048K->2048K][G1GC::Free: 609536K->607232K][Metaspace: 3634K(4492K, 4492K)->3634K(4492K, 4492K)][class space: 356K(388K, 388K)->356K(388K, 388K)][cause:G1EvacuationPause][RegionSize: 1024K][Target: 0.2000000 secs][Predicted: 0.2495800 secs][TargetTenured: 0K][Reclaimable: 0K(0.00%)][User: 0.0156250 secs][Sys: 0.0312500 secs][IM: 729K, 928K, 0K][TC: 509][DOE: 16K, 171][CCI: 2301K, 49152K, 2304K]

    このログの場合GC前のNew領域のサイズは389120K+41984K=431104Kであり,GC後のNew領域のサイズは397312K+41984K=439296Kであるため,New領域が拡張されたことが分かります。ログの記述内容や詳細に関しては,「-XX:[+|-]HitachiVerboseGC(拡張verbosegc情報出力オプション)」を参照してください。

(9) Concurrent Marking(CM)

Concurrent Markingの流れを次の図に示します。

図2‒25 Concurrent Markingの流れ

[図データ]

(a) 実行契機

CMは大きく次の5つの処理から構成されます。それぞれの実行契機について示します。なお,1.〜5.の表記はこの図の1.〜5.に対応しています。

  1. Concurrent Root Region Scan:

    YoungGC(initial-mark)終了後,実行されます。

  2. Concurrent Mark:

    1.の終了後,1.に続けて実行されます。

  3. Remark:

    2.の終了後,アプリケーションを停止できるタイミングで実行されます。

  4. Cleanup:

    3.の終了後,アプリケーションを停止できるタイミングで実行されます。

  5. Concurrent Cleanup:

    4.の終了後,4.に続けて実行されます。

(b) 対象範囲

New領域,Tenured領域およびHumongous領域

(c) 処理内容

CMは大きく次の5つの処理から構成されます。それぞれの処理の詳細を示します。

  1. Concurrent Root Region Scan:

    ローカル変数や使用中のオブジェクトから直接参照されているSurvivor領域内のオブジェクトにマークを付ける処理です。マルチスレッドで実行されます。

  2. Concurrent Mark:

    YoungGC(initial-mark)のマーキングと1.のマーキングでマークを付けたオブジェクトが参照しているオブジェクトにマークを付ける処理です。マルチスレッドで実行されます。

  3. Remark:

    2.のマーキング中に参照関係が変化したオブジェクトのマークを付け直す処理です。マルチスレッドで実行されます。

  4. Cleanup:

    リージョンごとに使用中オブジェクトの合計サイズを求める処理です。また,次のCMに備え,マークの初期化もします。マルチスレッドで実行されます。

  5. Concurrent Cleanup:

    使用中のオブジェクトが1つも存在しないリージョンを回収する処理です。シングルスレッドで実行されます。

(d) 処理結果

Eden領域:

使用中のオブジェクトに対応した領域にマークが付きます。

5.の処理でEdenリージョンが回収された場合,領域サイズが減少します。

Survivor領域:

使用中のオブジェクトに対応した領域にマークが付きます。

5.の処理でSurvivorリージョンが回収された場合,領域サイズが減少します。

Tenured領域:

使用中のオブジェクトに対応した領域にマークが付きます。

5.の処理でTenuredリージョンが回収された場合,領域サイズが減少します。

Humongous領域:

使用中のオブジェクトに対応した領域にマークが付きます。

5.の処理でHumongousリージョンが回収された場合,領域サイズが減少します。

Metaspace領域:

変化はありません。

Free領域:

使用中のオブジェクトが1つも存在しないリージョンを回収した場合,領域サイズが増加します。

(e) アプリケーションの停止の有無

  1. Concurrent Root Region Scan:

    CMスレッドで,アプリケーションを停止しないで実行されます。

  2. Concurrent Mark:

    CMスレッドで,アプリケーションを停止しないで実行されます。

  3. Remark:

    VMスレッドで,アプリケーションを停止して実行されます。

  4. Cleanup:

    VMスレッドで,アプリケーションを停止して実行されます。

  5. Concurrent Cleanup:

    CMスレッドで,アプリケーションを停止しないで実行されます。

アプリケーションは停止しませんが,4.の処理の終了から5.の処理が終了するまでの間にFullGCや新しいリージョンの確保がされた場合,5.の処理が終了するまで,YoungGC(normal)やFullGCや新しいリージョンの確保の処理を待たせます。

(f) ほかのGCとの関係

注 CMの処理中はYoungGC(initial-mark)は発生しません。

  1. Concurrent Root Region Scan:

    • YoungGC(normal):実行されません。

    • MixedGC:実行されません。

    • FullGC:実行されません。

  2. Concurrent Mark:

    • YoungGC(normal):2.の処理中に実行された場合,2.の処理を中断します。YoungGC(normal)が終了すると,再開されます。

    • MixedGC:実行されません。

    • FullGC:2.の処理中に実行された場合,2.の処理を中止します。途中結果は破棄されます。

  3. Remark:

    • YoungGC(normal):実行されません。

    • MixedGC:実行されません。

    • FullGC:実行されません。

  4. Cleanup:

    • YoungGC(normal):実行されません。

    • MixedGC:実行されません。

    • FullGC:実行されません。

  5. Concurrent Cleanup:

    • YoungGC(normal):5.の処理中に実行された場合,5.の処理が終了するまでYoungGC(normal)を待機させます。

    • MixedGC:実行されません。

    • FullGC:5.の処理中に実行された場合,5.の処理が終了するまでFullGCを待機させます。

(g) 補足

  • 関連オプション

    CMをするスレッド数は-XX:ConcGCThreadsオプションで指定できます。CMをするスレッド数を増やすとスループットが低下します。-XX:ConcGCThreadsオプションを指定しなかった場合,スレッド数は-XX:ConcGCThreadsオプションのデフォルト値となります。詳細については,「5.4 日立JavaVMで指定できるJava HotSpot VMのオプション」の「表5-9 指定できるJava HotSpot VMのオプション」にある「-XX:ConcGCThreads」を参照してください。

  • 確認方法

    Concurrent Root Region Scan,Concurrent Mark,Concurrent Cleanupの確認はログの先頭に[VCM]の識別子が付いていることから確認できます。Concurrent Markのログのイメージを次に示します。

[VCM]<Wed Jul 31 11:45:23 2013>[Concurrent Mark Start][User: 0.0000000 secs][Sys: 0.0000000 secs]
[VCM]<Wed Jul 31 11:45:31 2013>[Concurrent Mark End][User: 0.0321549 secs][Sys: 0.0129454 secs]

VCMのログが複数行にわたるため,CMログは開始時にStart,終了時にEndが出力されます。複数行に渡る場合,CPU使用時間はEndのログにStartからEndまでの処理時間が出力され,Startのログは0が出力されます。

ログの記述内容や詳細に関しては,「-XX:[+|-]HitachiVerboseGC(拡張verbosegc情報出力オプション)」を参照してください。

またRemark,Cleanupの処理は処理中にアプリケーションを停止するため,VG1ログに出力されます。Remark,Cleanupの処理はGCログのGC種別が“CM Remark”,“CM Cleanup”という出力から判断できます。

(10) MixedGC

MixedGCの処理の流れを次の図に示します。

図2‒26 MixedGCの処理の流れ

[図データ]

(a) 実行契機

予測回収サイズがJavaヒープ領域の10%を超えている場合,次のGCにMixedGCが予約されます。その判定はCM終了直後のYoungGC(normal)終了時,またはMixedGCの終了時にされます。

(b) 対象範囲

New領域とTenured領域の一部

(c) 処理内容

  • MixedGCが発生すると,シングルスレッドでリージョンの選択処理を,マルチスレッドでEvacuationを実行します。

  • MixedGCではNew領域をGC対象とし,予測停止時間が目標停止時間に収まる範囲でTenured領域を部分的にGC対象に追加します。

  • MixedGCのEvacuationでは,New領域に対してはYoungGCのEvacuationと同じ処理をします。詳細については,「(8) YoungGC」を参照してください。

  • GC対象に追加したTenured領域に対しては,Tenuredリージョン内の使用中のオブジェクトを別のTenuredリージョンに詰め直します。

  • MixedGC後も予測回収サイズがJavaヒープ領域の10%を超えている場合,継続してMixedGCが選択され,要件を満たしていない場合,通常のYoungGCが実行されます。

(d) 処理結果

Eden領域:

オブジェクトが回収され,空になります。GC後リサイズされます。

Survivor領域:

From空間のオブジェクトが回収され,空になります。GC後リサイズされます。

Tenured領域:

長期間必要と判断されたオブジェクトがTenured領域に移動します。GC対象に追加された領域のオブジェクトが回収されます。

Humongous領域:

変化はありません。

Metaspace領域:

変化はありません。

Free領域:

GC後のリサイズによって,増減します。

(e) アプリケーションの停止の有無

停止します。

(f) ほかのGCとの関係

CM:MixedGC中に実行されません。

YoungGC:MixedGC中に実行されません。

FullGC:MixedGC中に実行要件を満たすと,MixedGCを中止して実行されます。

(g) 補足

  • 関連オプション

    Evacuationをするスレッド数は-XX:ParallelGCThreadsオプションで変更できます。スレッド数を増やすとMixedGCに掛かる時間が小さくなります。また,オプションを指定しない場合,スレッド数はOSが認識しているCPU数が用いられます。-XX:ParallelGCThreadsオプションについては,「5.4 日立JavaVMで指定できるJava HotSpot VMのオプション」の「表5-9 指定できるJava HotSpot VMのオプション」にある「-XX:ParallelGCThreads」を参照してください。

  • 確認方法

    MixedGCの確認はログのGCの種別の“Mixed GC”から確認できます。また,TargetTenuredの項目からMixedGCで選択されたTenured領域のサイズを確認できます。オブジェクトの予測回収サイズに関してはReclaimableの項目から確認できます。ログの記述内容や詳細に関しては,「-XX:[+|-]HitachiVerboseGC(拡張verbosegc情報出力オプション)」を参照してください。

    [VG1]<Wed Jun 12 11:21:10 2013>[Mixed GC 899070K/899072K(1048576K)->501742K/501760K(1048576K), 0.0931560 secs][Status:-][G1GC::Eden: 389120K(389120K)->0K(397312K)][G1GC::Survivor: 41984K->41984K][G1GC::Tenured: 459776K->459776K][G1GC::Humongous: 2048K->2048K][G1GC::Free: 609536K->607232K][Metaspace: 3634K(4492K, 4492K)->3634K(4492K, 4492K)][class space: 356K(388K, 388K)->356K(388K, 388K)][cause:G1EvacuationPause][RegionSize: 1024K][Target: 0.2000000 secs][Predicted: 0.2495800 secs][TargetTenured: 2048K][Reclaimable: 17703K(1.69%)][User: 0.0156250 secs][Sys: 0.0312500 secs][IM: 729K, 928K, 0K][TC: 509][DOE: 16K, 171][CCI: 2301K, 49152K, 2304K]

(11) FullGC

FullGCの流れを次の図に示します。

図2‒27 FullGCの流れ

[図データ]

(a) 実行契機

Free領域がなくなり,Evacuationのコピー先が確保できなかった場合やHumongous領域が確保できなかった場合に実行されます。また,Metaspace領域の空き領域がなくなった場合やSystem.gc()が呼ばれた場合も実行されます。

(b) 対象範囲

New領域,Tenured領域,Humongous領域およびMetaspace領域

(c) 処理内容

  • FullGCはシングルスレッドでアプリケーションスレッドを停止して実行されます。

  • FullGCが発生すると目標停止時間に関係なく,GCが終了するまでアプリケーションを停止します。

  • FullGCの処理はSerialGCのFullGCと同じ処理です。FullGCを実行しても領域が確保できなかった場合は,OutOfMemoryが発生します。詳細については,「2.2.1 SerialGCの仕組み」を参照してください。

  • 一般的に,YoungGCやMixedGCの方がFullGCに比べて短い時間で処理できます。

(d) 処理結果

Eden領域:オブジェクトが回収され,空になります。

Survivor領域:使用中のオブジェクトがTenured領域に移動し,空になります。

Tenured領域:使用中のオブジェクトが詰め直されます。

Humongous領域:使用中のオブジェクトが詰め直されます。

Metaspace領域:使用中のオブジェクトが詰め直されます。

Free領域:回収されたリージョンによって増加します。

(e) アプリケーションの停止の有無

停止します。

(f) ほかのGCとの関係

CM:FullGC中は実行されません。

YoungGC:FullGC中は実行されません。

MixedGC:FullGC中は実行されません。

(g) 補足

  • 確認方法

    FullGCの確認はログ上のGCの種別が“FullGC”であることから確認できます。また,FullGCではこれから実行するGCに対して予測をしないため,予測停止時間や予測回収サイズは0で表示されます。

    [VG1]<Wed Jan 15 12:51:32 2014>[Full GC 130443K/131072K(131072K)->55462K/56320K(131072K), 2.3265610 secs][Status:-][G1GC::Eden: 0K(43008K)->0K(43008K)][G1GC::Survivor: 0K->0K][G1GC::Tenured: 131072K->56320K][G1GC::Humongous: 0K->0K][G1GC::Free: 0K->74752K][Metaspace: 3634K(4492K, 4492K)->3634K(4492K, 4492K)][class space: 356K(388K, 388K)->356K(388K, 388K)][cause:ObjAllocFail][RegionSize: 1024K][Target: 0.2000000 secs][Predicted: 0.0000000 secs][TargetTenured: 0K][Reclaimable: 0K(0.00%)][User: 2.1700000 secs][Sys: 0.0000000 secs][IM: 277185K, 261856K, 44544K][TC: 1168][DOE: 0K, 0][CCI: 5808K, 49152K, 5952K]