Jump to content 日本-日本語

製品  >  ソフトウェア  >  HP- UX Developer Edge

Javaのかなめ、
「ガベージ・コレクション」をやさしく学ぶ・前編

HP-UX/Integrityサーバー お問い合せ
コンテンツに進む
Javaのかなめ、「ガベージ・コレクション」をやさしく学ぶ・前編

マイナーGCで「ふるい」にかける

マイナーGCでは、JVM内部で次々に生成されるオブジェクトをYoung領域の中で「ふるい」にかけて、Old領域に配置するのにふさわしい“長生きするオブジェクト”を探し出す。この「ふるい」の役目を担うのが、Young領域の中にある以下の3種類の領域である。
Javaのかなめ、「ガベージ・コレクション」をやさしく学ぶ・前編
HotSpot VMのガベージ・コレクションをおさらいする
マイナーGCで「ふるい」にかける
 

Young領域の3つの領域
図4:Young領域の3つの領域
  • Eden領域:“新しい”オブジェクトを格納する領域
  • From領域:“ちょっと古い”オブジェクトを格納する領域
  • To領域:Eden領域またはFrom領域からオブジェクトをコピーする領域
では、これら3つの領域を用いて、マイナーGCがどのようなメカニズムで実施されるのか説明しよう。

JVM内部で新たに生成されるオブジェクトは、最初はEden領域に配置される。当然ながらEden領域はすぐに満杯となるため、満杯となったタイミングでマイナーGCが起動される。このマイナーGCでは、まずEden領域中のオブジェクトの参照関係をたどり、使用中のオブジェクトをTo領域へと移動する。

Eden領域からTo領域へのオブジェクトの移動
図5:Eden領域からTo領域へのオブジェクトの移動

この移動が完了したら、To領域とFrom領域を入れ替える。これでマイナーGCは完了だ。Eden領域とTo領域は空になるため、新しいオブジェクトを受け入れ可能になる。

さて、Eden領域が再び満杯になると、いま説明したマイナーGCを同じ手順で繰り返す。ただその際には、From領域(=ひとつ前のTo領域)に存在するオブジェクトも合わせてTo領域に移動する。

Eden領域およびFrom領域からTo領域へのオブジェクトの移動
図6:Eden領域およびFrom領域からTo領域へのオブジェクトの移動

つまりYoung領域内のオブジェクトは、それが使用中である限りは、マイナーGCの度にFrom領域とTo領域の間を行ったり来たりするわけである。ただし移動の度に、上図に示すように「何回移動したか」をカウントしておく。そして、この移動回数が一定のしきい値に達したオブジェクトは、「長生きするオブジェクト」と判断されてOld領域へ移動する。ちなみに、このしきい値は、Young領域がすぐに満杯にならないような値に動的に調整される。

長生きするオブジェクトのOld領域への移動
図7:長生きするオブジェクトのOld領域への移動

このような「ふるい」のメカニズムによって、Old領域へ配置すべきオブジェクトの量を減らし、マーク&スイープGCの頻度を少なくできるのが、世代別GCのメリットである。

世代別GCの実際のふるまい

  こうしたHotSpot VMによる世代別GCのふるまいを観察するには、JVM起動時のオプションとして「-XX:+PrintGCDetails」を指定する。これにより、以下のようなログがコンソールに出力される。

[GC [DefNew: 512K->0K(576K), 0.0002047  secs] 1233K->722K(1984K), 0.0002661 secs]
[GC [DefNew: 512K->0K(576K), 0.0001534 secs] 1654K->1142K(1984K), 0.0002156 secs]
[Full GC [Tenured: 21637K->21635K(60544K), 0.0645247 secs] 21637K->21635K(63872K),
[Perm : 262K->262K(8192K)], 0.0647529 secs]

<以下略>

このログにおいて、「GC」で始まる行はマイナーGCを表し、「Full GC」で始まる行はメジャーGCを表す。上記例では2回のマイナーGCと1回のメジャーGCが発生しているのが分かる。ここで1行目の、

[DefNew: 512K->0K(576K), 0.0002047 secs]

という部分は、
  • Young領域の512KB分のオブジェクトがGC対象となった
  • Young領域の0KB分のオブジェクトが残存した(つまりすべて削除された)
  • Young領域のサイズが576KBとなった
という意味を表している。また、それにつづく、

1233K->722K(1984K), 0.0002661 secs

という部分は、
  • JVMヒープ中の1233KB分のオブジェクトがGC対象となった
  • JVMヒープ中の722KB分のオブジェクトが残存した
  • JVMヒープ中のサイズが1984KBとなった
  • GCが0.0002661 secs(0.2ms)で完了した
という意味である。さらに、最後の行である、

[Full GC [Tenured: 21637K->21635K(60544K),  0.0645247 secs]21637K->21635K(63872K),
[Perm : 262K->262K(8192K)], 0.0647529 secs]

という部分にはメジャーGCの実行結果が記されており、「Tenured:」および「Perm:」で始まる部分において、それぞれOld領域とPerm領域におけるメモリ使用量の変化や領域サイズが記録されているのが分かる。またメジャーGCには64msの時間を要しており、マイナーGCに比べると3桁ほど長い時間を費やしていることを示している。

ちなみに、こうした数字の羅列からなるログ出力だけでは、JVM内部のメモリ消費動向を直感的に把握することは難しい。そこで実際のパフォーマンス・チューニングでは、前述のVisual GCをはじめ、HPが提供するプロファイリング・ツールであるHP jmeter、HP jtuneなどの解析ツールを併用するのが常套手段である。

後編では、HotSpot VMに備わる4種類のGCポリシーについて説明する。

トップへ 戻る    

その他のコラム(特集)もお読み下さい

 
 

本ページの内容は執筆時の情報に基づいており、異なる場合があります。

お問い合わせ

ご購入前のお問い合わせ


ご購入後のお問い合わせ

オンラインサポート
製品の標準保証でご利用いただける無償のサービスです。

ショールーム

ショールーム 導入をご検討のお客様へ
業務アプリケーションの継続・標準化・開発性とシステム担当者様、システム開発者様が抱える悩み・疑問に対する解決策実体験して頂けます。
印刷用画面へ
プライバシー ご利用条件・免責事項