Javaはどのように動くのか~図解でわかるJVMの仕組み

第5回 チューニングのために理解しておきたいGCの4つのアルゴリズム

この記事を読むのに必要な時間:およそ 2 分

GCと同時にコンパクションを実行する ~コピーGC

断片化の対策としてコンパクションを解説しましたが,そもそもヒープが断片化しないGCアルゴリズムはあるのでしょうか?

その答えが「コピーGC」です。コピーGCでは,GCと同時にコンパクションと同じ処理を行っているため,ヒープが断片化することはありません。

マーク&スイープGCでは,ヒープを1部屋として使用していました。一方,コピーGCでは,ヒープをFrom領域とTo領域の2つに分けて使用します。

図6 ヒープを分割

図6 ヒープを分割

アプリケーションが新たなオブジェクトを生成すると,⁠必ず⁠From領域に新たなオブジェクトを割り当てます。アプリケーションは⁠絶対に⁠To領域を使えません。

図7 オブジェクトの生成

図7 オブジェクトの生成

それでは,To領域はどのような場合に使われるのでしょうか?

答えは「コピーGCの実行中」です。

アプリケーションが実行されると,From領域の残り空き容量が少なくなっていきます。そうすると,JVMはコピーGCを行います。

図8 コピーGCの開始

図8 コピーGCの開始

コピーGCは,From領域にあるオブジェクトのうち,生きているオブジェクトを探します。生きてるオブジェクトが見つかると,そのオブジェクトをTo領域の端から順にコピーしていきます。

図9 オブジェクトのコピー

図9 オブジェクトのコピー

From領域をすべて探し終わると,すべての生きているオブジェクトはTo領域にコピーされ,From領域は空になります。しかし,アプリケーションはTo領域を使うことができないため,To領域にコピーされた生きているオブジェクトにアクセスすることができません。そのため,このままではアプリケーションが正常に動作することができなくなってしまいます。

図10 オブジェクトのコピー後

図10 オブジェクトのコピー後

この問題を解消するために,コピーGCでは,領域の名前を変更する動作が行われます。具体的には,これまでTo領域であった領域がFrom領域になり,これまでFrom領域だった領域がTo領域となります。アプリケーションは,これまでTo領域だった新しいFrom領域にアクセスすることで,コピーされた生きてるオブジェクトにアクセスすることも,オブジェクトを生成することもできるようになります。

図11 領域の切り替え

図11 領域の切り替え

コピーGCでは,GC時にTo領域の前から順に使用されていきます。これにより,前述したように,GCと同時にコンパクションと同じ処理を行われ,ヒープが断片化することはありません。そのようなメリットがある一方,コピーGCには弱点もあります。アプリケーションはFrom領域しか使用できないため,使用できる容量が半分となってしまうのです。

図12 コピーGCで使用できる容量

図12 コピーGCで使用できる容量

著者プロフィール

伊藤智博(いとうちひろ)

日本オラクル(株)コンサルティングサービス統括所属。アプリケーションアーキテクトやM/Wコンサルとして,Javaに限らずさまざまな言語での開発/支援を経験。アプリ ケーションだけでなくミドルウェア,データベース,OS,ハードウェアにも興味アリ。現在,以下のコミュニティの活動に協力している。

Japan Oracle User Group(JPOUG)
Oracle LOVERS

ブログ:http://chiroito.blogspot.jp/
Twitter:@chiroito