世代別コレクション
ガベージコレクションは、次の2つの世代に分けてヒープメモリを管理します。
これは、短命なオブジェクトを New 世代に、長寿なオブジェクトを Old 世代に分けることで、特徴に合わせて適切なガベージコレクションアルゴリズムを使おう、という考え方です。
New (young) 世代
New 世代は以下の3つの領域に分かれています。
領域 | 説明 |
---|---|
Eden 領域 | 新規オブジェクトを割り当てる領域 |
Survivor 0 領域 | Eden と survivor 1 領域にある使用中オブジェクトの待避先 |
Survivor 1 領域 | Eden と survivor 0 領域にある使用中オブジェクトの待避先 |
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) は全領域を対象とするため、Minor GC (Scavenge GC) と比較して非常に長い時間、アプリケーションが止まります。(STW [=Stop The World] と呼ぶ)
CMS CG の発生条件は、「ヒープメモリの使用率が閾値を超えた時」と設定することが多いです。
CMS CG は、以下の流れでマーク (未使用のオブジェクトを確認) し、スイープ (削除) します。
- Initial mark (STW 発生)
- Concurrent mark
- Concurrent preclean
- Concurrent abortable preclean
- Remark (Final mark) (STW 発生)
- Concurrent sweep
- Concurrent reset
これにより、Full GC と比較して、STW を発生するタイミングを大幅に削減できます。
ただし、コンパクションを行わないのでフラグメンテーションが発生します。
フラグメンテーションにより Old 領域に割り当てられなかったり、ヒープメモリ回収が間に合わない場合は Full GC が発生します。
リージョン単位で管理 (G1GC)
G1GC とは、リージョンと呼ばれる単位にメモリを分割して世代を管理する方法です。
コンカレントスタートの Young-Only フェーズは、以下の緑で囲まれた部分に相当するフェーズです。
コンカレントスタートの Young-Only フェーズは、以下の処理を実施します。(詳細はこちら)
- コンカレントスタート (Concurrent-Start)/初期マーク付け(initial-mark) (STW 発生)
- ルートリージョンスキャン(root-region-scan)
- 並列マーク付け(concurrent-mark)
- 再マーク(remark) (STW 発生)
- クリーンアップ(cleanup) (STW 発生)
- 並列クリーンアップ(concurrent-cleanup)
Space Reclamation フェーズは、以下の緑で囲まれた部分に相当するフェーズです。
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 GC | Old 世代 | 一部発生 | する |
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)
現在はほとんどのコンピュータがマルチプロセッサなので、ほぼ使われてません。
世代 | 利用するアルゴリズム |
---|---|
New 世代 | Minor GC (Scavenge GC) |
Old 世代 | Major GC (Full GC) |
複数のスレッドを使用してガベージコレクションをするため、シングル GC より高速です。
世代 | 利用するアルゴリズム |
---|---|
New 世代 | Minor GC (Scavenge GC) |
Old 世代 | Major GC (Full GC) |
CMS GC は、STW の発生時間を短縮し、アプリケーションのレスポンスを早くします。
その代わり、GC の処理が多いのでパラレル GC よりスループットは落ちます。
世代 | 利用するアルゴリズム |
---|---|
New 世代 | Minor GC (Scavenge GC) |
Old 世代 | CMS GC コンパクションが必要、回収が間に合わない場合は Major GC (Full GC) |
リージョンと呼ばれる小さな単位にヒープメモリを分割することで、一回あたりのヒープメモリ回収時間を削減します。(1回あたりの STW を短くします。)
世代 | 利用するアルゴリズム |
---|---|
New 世代 | G1GC (通常/コンカレントスタート Young-Only フェーズ) |
Old 世代 | G1GC (Space Reclamation フェーズ) |
ガベージコレクションのまとめ
ガベージコレクション | 目的 | 備考 |
---|---|---|
シリアル GC | スループット重視 | 現在はほぼ使わない |
パラレル GC | スループット重視 | マルチコア環境のデフォルト |
CMS GC | レスポンス重視 | JDK 9以降非推奨 |
G1GC | レスポンス重視 | CMS の代わり |
関連記事
Java 入門用の記事は以下のとおりです。
- 【Java 入門】オブジェクト指向プログラミングの基本用語
- 【Java 入門】ガベージコレクションの仕組みとは
- 【Java 入門】JDBC (Java DataBase Connectivity)
- 【Java 入門】Gradle (ビルド自動化システム)