【入門】ガベージコレクションの仕組みとは (Java HotSpot VM)

ガベージコレクション (GC、Garbage Collection)とは)ガベージコレクションとは、不要になったヒープメモリ領域を自動的に解放して、再利用可能にすることです。
スポンサーリンク

世代別コレクション

ガベージコレクションは、次の2つの世代に分けてヒープメモリを管理します。

https://docs.oracle.com/javase/jp/11/gctuning/garbage-collector-implementation.html
permanent 領域は割愛

これは、短命なオブジェクトを New 世代に、長寿なオブジェクトを Old 世代に分けることで、特徴に合わせて適切なガベージコレクションアルゴリズムを使おう、という考え方です。

New (young) 世代

New 世代は以下の3つの領域に分かれています。

領域説明
Eden 領域新規オブジェクトを割り当てる領域
Survivor 0 領域Eden と survivor 1 領域にある使用中オブジェクトの待避先
Survivor 1 領域Eden と survivor 0 領域にある使用中オブジェクトの待避先

Minor GC (Scavenge GC)

Minor GC (Scavenge GC) とは、Eden 領域が埋まった時に実行する、New 世代を対象としたガベージコレクションです。

Scavenge GC は、Eden 領域にある使用中のオブジェクトを Survivor にコピーします。

未使用中のオブジェクトはコピーしない (削除)

Eden 領域がいっぱいになった時に、Survivor 領域にオブジェクトが存在する場合、空の Survivor にコピーします。(以下のコピーを交互に繰り返す)

  • Survivor 0 --> Survivor 1
  • Survivor 1 --> Survivor 0

このままでは、Survivor 領域が埋まってしまいます。

そこで、以下の条件で Old 世代にオブジェクトを昇格 (移動) します。

  • N 回以上 Survivor 間を移動した時 (長寿なオブジェクトとみなす)
  • Eden から Survivor に移動できない (ヒープメモリ領域不足で)

Old (Tenured) 世代

Major GC (Full GC)

Major GC (Full GC) とは、Old 領域が埋まった時に実行する、全世代を対象としたガベージコレクションです。

Major GC (Full GC) は全領域を対象とするため、Minor GC (Scavenge GC) と比較して非常に長い時間、アプリケーションが止まります。(STW [=Stop The World] と呼ぶ)

CMS(Concurrent Mark Sweep) GC

CMS GC とは、Old世代を対象としたガベージコレクションです。

CMS CG の発生条件は、「ヒープメモリの使用率が閾値を超えた時」と設定することが多いです。

コンパクションしないので、フラグメンテーションは発生

CMS CG は、以下の流れでマーク (未使用のオブジェクトを確認) し、スイープ (削除) します。

  1. Initial mark (STW 発生)
  2. Concurrent mark
  3. Concurrent preclean
  4. Concurrent abortable preclean
  5. Remark (Final mark) (STW 発生)
  6. Concurrent sweep
  7. Concurrent reset

これにより、Full GC と比較して、STW を発生するタイミングを大幅に削減できます。

ただし、コンパクションを行わないのでフラグメンテーションが発生します。

フラグメンテーションにより Old 領域に割り当てられなかったり、ヒープメモリ回収が間に合わない場合は Full GC が発生します。

リージョン単位で管理 (G1GC)

G1GC とは、リージョンと呼ばれる単位にメモリを分割して世代を管理する方法です。

四角い箱が1リージョン、humongous は複数のリージョンにまたがる大きなサイズのオブジェクト

通常の Young-Only フェーズ

通常の Young-Only フェーズ とは、以下のガベージコレクションのサイクルにおける緑で囲まれた部分に相当するフェーズです。
https://docs.oracle.com/javase/jp/11/gctuning/garbage-first-g1-garbage-collector1.html#GUID-F1BE86FA-3EDC-4D4F-BDB4-4B044AD83180

コンカレントスタートの Young-Only フェーズ

コンカレントスタートの Young-Only フェーズ とは、ヒープメモリの使用率が特定の閾値を超えた時に発生するフェーズです。

コンカレントスタートの Young-Only フェーズは、以下の緑で囲まれた部分に相当するフェーズです。

大きな丸の処理は STW が発生します

コンカレントスタートの Young-Only フェーズは、以下の処理を実施します。(詳細はこちら)

  1. コンカレントスタート (Concurrent-Start)/初期マーク付け(initial-mark) (STW 発生)
  2. ルートリージョンスキャン(root-region-scan)
  3. 並列マーク付け(concurrent-mark)
  4. 再マーク(remark) (STW 発生)
  5. クリーンアップ(cleanup) (STW 発生)
  6. 並列クリーンアップ(concurrent-cleanup)
通常の Young-Only フェーズ も実行し、New 世代の領域も回収

Space Reclamation フェーズ

Space Reclamation フェーズ とは、Mark されたオブジェクトを回収するフェーズです。

Space Reclamation フェーズは、以下の緑で囲まれた部分に相当するフェーズです。

全ての赤丸で STW が発生します (Young-only フェーズよりも短い)
1度に Mark を全て回収せず、複数回の GC に分けて回収

New 世代は、「コンカレントスタートの Young-Only フェーズ」、「Space Reclamation フェーズ」でも回収されます。

コンカレント開始: このタイプのコレクションはマーキング・プロセスを開始し、通常の若い世代のコレクションも実行します。

領域回収フェーズ: このフェーズは複数の混合コレクションから構成され、若い世代のリージョンに加えて、古い世代のリージョン・セットのライブ・オブジェクトも退避します。

https://docs.oracle.com/javase/jp/11/gctuning/garbage-first-g1-garbage-collector1.html#GUID-F1BE86FA-3EDC-4D4F-BDB4-4B044AD83180

世代別コレクションのまとめ

ガベージコレクションアルゴリズム対象STWフラグメンテーション
Minor GC (Scavenge GC)New 世代発生 (短い)しない
Major GC (Full GC)全部発生 (長い)しない
CMS GCOld 世代一部発生する
G1GC
(通常の Young-Only フェーズ)
New 世代発生しないしてる (リージョン分けされてる)
G1GC
(コンカレントスタート・フェーズ)
New 世代一部発生してる (リージョン分けされてる)
G1GC
(Space Reclamation フェーズ)
全部発生 (短い)してる (リージョン分けされてる)
スポンサーリンク

ガベージコレクションの種類

ガベージコレクションには、次の種類のガベージコレクションが存在します。

  • シリアル GC
  • パラレル GC
  • モーストリコンカレント GC
    • CMS GC (Concurrent Mark Sweep Garbage Collection)
    • G1 GC (Garbage-First Garbage Collection)

シリアル GC

シリアル GC とは、シングルプロセッサ用のガベージコレクションです。

現在はほとんどのコンピュータがマルチプロセッサなので、ほぼ使われてません。

世代利用するアルゴリズム
New 世代Minor GC (Scavenge GC)
Old 世代Major GC (Full GC)

パラレル GC

パラレル GC とは、マルチプロセッサ用のガベージコレクションです。

複数のスレッドを使用してガベージコレクションをするため、シングル GC より高速です。

世代利用するアルゴリズム
New 世代Minor GC (Scavenge GC)
Old 世代Major GC (Full GC)

CMS (Concurrent Mark Sweep) GC

CMS GC とは、Old 世代で Full GC の代わりに CMS GC を使うガベージコレクションです。

CMS GC は、STW の発生時間を短縮し、アプリケーションのレスポンスを早くします。

その代わり、GC の処理が多いのでパラレル GC よりスループットは落ちます。

世代利用するアルゴリズム
New 世代Minor GC (Scavenge GC)
Old 世代CMS GC
コンパクションが必要、回収が間に合わない場合は Major GC (Full GC)

G1GC (Garbage-First Garbage Collection)

G1GC とは、リージョンと呼ばれる単位実施するガベージコレクションです。

リージョンと呼ばれる小さな単位にヒープメモリを分割することで、一回あたりのヒープメモリ回収時間を削減します。(1回あたりの STW を短くします。)

世代利用するアルゴリズム
New 世代G1GC (通常/コンカレントスタート Young-Only フェーズ)
Old 世代G1GC (Space Reclamation フェーズ)
メモリを使い果たした場合はフル GC が発生

ガベージコレクションのまとめ

ガベージコレクション目的備考
シリアル GCスループット重視現在はほぼ使わない
パラレル GCスループット重視マルチコア環境のデフォルト
CMS GCレスポンス重視JDK 9以降非推奨
G1GCレスポンス重視CMS の代わり
スポンサーリンク

関連記事

Java 入門用の記事は以下のとおりです。

参考資料

HotSpot仮想マシン・ガベージ・コレクション・チューニング・ガイド
このガイドでは、Java HotSpot仮想マシン(Java HotSpot VM)に含まれる各種ガベージ・コレクション方式について説明しているので、ユーザーのニーズに応じた最適な方式の選定に役立ちます。
JVMオプション | Java | 技術メモ | TOYATAKU WEB
技術メモ Java JVMオプション
3分で理解するG1ガベージコレクション - Qiita
Java Advent Calendar 2017 21日目の記事です。Java9が今年リリースされてHotSpot JVMのデフォルトGCがG1になったので、おさらいのために投稿します。GCの…