JVM ガベージ コレクション アルゴリズムとガベージ コレクタ (Serial、ParNew、CMS) - JVM シリーズ (4)

1. ガベージ コレクション アルゴリズム

ここに画像の説明を挿入

1. 世代別収集アルゴリズム

現在、ほとんどのガベージ コレクターは世代別コレクション アルゴリズムを使用しています. このアルゴリズムは実際にはアイデアです: オブジェクトのさまざまなライフサイクルに応じて、メモリは若い世代と古い世代に分けられます.時代ごとの特徴ガベージコレクションのアルゴリズム。复制算法たとえば、若い世代では、オブジェクトが収集されるたびにほとんどのオブジェクトが破棄されます (GC ルートによって参照されません)。各ガベージ コレクションを、少量のオブジェクト コピー コストのみで完了するように選択できます。古い世代の生存確率は比較的高く、その割り当てを保証するための追加スペースがないため、ガベージ コレクションを選択标记清除算法または実行します; 一般的に言えば、マーク クリア アルゴリズムまたはマーク クリーニング アルゴリズムは多くのコピーアルゴリズムより遅い!标记整理算法

2. 複製アルゴリズム

簡単に言えば、コピーのアルゴリズムは、メモリを同じサイズの 2 つの領域に分割し、いずれかの領域が使用されるたびに、メモリ領域が使い果たされると、生き残ったオブジェクトを別のメモリ領域にコピーし、クリーンアップすることです。以前に使用されたメモリ領域を一度に回復するため、各メモリ回復はメモリ領域の半分になります。一般的に言えば、空間は時間と交換され、複製アルゴリズムは若い世代での適用に適しています (若い世代のサバイバー領域の s1:s2 は正確に 1:1 です)。

  • 利点: ガベージ コレクションの効率が高く、メモリの断片化がない
  • 短所:メモリスペースを占有します
    ここに画像の説明を挿入

3. マーク スイープ アルゴリズム

アルゴリズムは一般に2 つの段階标记清除分けられます: 生き残ったオブジェクトをマークし、マークされていないすべてのオブジェクトを均一にリサイクルします (通常はこれを選択します)。または、回収する必要があるすべてのオブジェクトをマークし、マークの完了後に統合します。マークされたすべてのオブジェクトをリサイクルします.

  • 利点: (コピー アルゴリズムと比較して) メモリ スペースを節約し、効率はマーク ソート アルゴリズムよりも高い
  • 短所: マークされたオブジェクトが多すぎる場合、効率が高くなく、マークがクリアされた後に多数の不連続なメモリ フラグメントが生成されます。
    ここに画像の説明を挿入

4. マークアップアルゴリズム

マーキングおよびソート アルゴリズムは、古い世代の特性に基づくガベージ コレクション アルゴリズムであり、标记2 つの整理段階に分けられます; マーキング プロセスはマーキングおよびクリーニング アルゴリズムと同じですが、その後のステップは直接リサイクルすることではありません。再利用可能なオブジェクトですが、生き残ったすべてのオブジェクトを許可するには、オブジェクトのオブジェクトは一方の端に移動し、端の境界の外側のメモリを直接クリーンアップします。時間と空間を交換するアルゴリズムです

  • 利点: (コピー アルゴリズムと比較して) メモリ スペースを節約し、メモリの断片化を回避します。
  • 短所: ガベージ コレクションは最も効率的ではありません (コピーおよびマーク アンド スイープ アルゴリズムと比較して)。
    ここに画像の説明を挿入

5. 3 つのガベージ コレクション アルゴリズムの特性の比較:

コピーアルゴリズム マークアンドスイープアルゴリズム マークアップアルゴリズム
スピード 最速 中くらい 最も遅い
スペースオーバーヘッド 通常、ライブ オブジェクトの 2 倍のサイズが必要です (フラグメントを積み上げません)。 少ない(ただし、破片が蓄積する) 少ない(ゴミが溜まらない)
オブジェクトを移動するかどうか はい いいえ はい
  • コピー アルゴリズムがマーク スイープおよびマーク コンパクト アルゴリズムよりも高速なのはなぜですか?
    個人的な理解: シングルスレッドの場合, コピーに必要なトラバーサルは 1 回だけです. 参照を更新しながらマーキングしてコピーすること, つまりマークトラバーサルと理解できます.永遠の場合。コピー後、メモリ内のオブジェクトの順序は、マークの順序と一致する参照関係に従って配置されます。マークの並べ替えアルゴリズムの場合、ヒープ領域を最適化する追加のプロセスがあるため、より時間がかかります。


2.ガベージコレクター

ガベージコレクタの組み合わせ関係

ここに画像の説明を挿入
JVM のガベージ コレクションは、これらのガベージ コレクタによって実現されます. ガベージ コレクタにはそれぞれ独自の特性があります. 完璧なガベージ コレクタはありません. さまざまなアプリケーション シナリオに応じて適切なガベージ コレクタを選択する必要があります. .

1.シリアルコレクター

シリアル (シリアル) コレクタは、比較的初期のガベージ コレクタです。シングル スレッドのガベージ コレクタです。ガベージ コレクション プロセス中、コレクション作業を完了するために 1 つのスレッドのみが使用され、このプロセス中は他のすべてのスレッドを中断する必要があります。ワーカー スレッド (つまり、"Stop The World") は、ガベージ コレクションが完了するまで実行を継続しません。其年轻代采用复制算法,老年代采用标记整理算法

コレクターの設定パラメーター:-XX:+UseSerialGC -XX:+UseSerialOldGC

  • 利点: シンプルで効率的 (他のシングルスレッド コレクターと比較して)、シリアル コレクターは、スレッド相互作用のオーバーヘッドがないため、高いシングルスレッド コレクション効率を自然に得ることができます; フローティング ガベージを生成しません。
  • 短所: Stop The World を長時間使用すると、ユーザー エクスペリエンスが低下する可能性があります。

ここに画像の説明を挿入

補足: Serial Old コレクターは、Serial コレクターの古いバージョンであり、シングルスレッド コレクターでもあります。主な用途は 2 つあります。1 つは JDK1.5 以前のバージョンの Parallel Scavenge コレクターと組み合わせて使用​​され、もう 1 つは CMS コレクターの候補として使用されます。

2. パラレル スカベンジ コレクター

パラレル コレクタは、実際にはシリアル コレクタのマルチスレッド バージョンです. 違いは、ガベージ コレクションにマルチスレッドを使用することです. コレクション アルゴリズムやリサイクル戦略などの他の動作は、シリアル コレクタに似ています. コレクション スレッドのデフォルト数は、 CPU コアの数. 収集スレッドの数は、-XX:ParallelGCThreadsパラメーターを介して設定することもできます. スループット (CPU の効率的な使用) は、並列コレクターの焦点です, つまり、CPU でのユーザー コードの実行に費やされた時間とCPU が消費した合計時間。其年轻代采用复制算法,老年代采用标记整理算法。

コレクターの設定パラメーター:-XX:+UseParallelGC -XX:+UseParallelOldGC

  • メリット:浮遊ガベージが発生しない、マルチスレッド化によりガベージコレクションのスループットが向上
  • 欠点: ガベージ コレクション プロセス中にユーザー スレッド Stop The World が中断され、ユーザー エクスペリエンスが低下します。

ここに画像の説明を挿入
Parallel Old コレクターは、Parallel Scavenge コレクターの旧世代バージョンです。多线程と を使用します标记整理算法スループットと CPU リソースを重視する場合は、Parallel Scavenge コレクターと Parallel Old コレクター ( JDK8默认的年轻代和老年代收集器) を優先できます。

3.ParNewコレクター

ParNew コレクターは、実際には Parallel コレクターと非常によく似ています。主な違いは、CMS コレクターと組み合わせて使用​​できることです。新生代采用复制算法,老年代采用标记整理算法。これは、サーバー モードで実行されている多くの仮想マシンの最初の選択肢であり、シリアル コレクターを除いて、CMS コレクターと連携できる唯一のものです。

コレクターの設定パラメーター:-XX:+UseParNewGC
ここに画像の説明を挿入

4.CMSコレクター

CMS (Concurrent Mark Sweep) コレクターは、リカバリー一時停止時間を最短にすることを目的としたコレクターです。これは、ユーザー エクスペリエンスに重点を置いたアプリケーションでの使用に非常に適しており、ガベージ コレクション スレッドとユーザー スレッド (基本的に) を同時に動作させることができる、HotSpot 仮想マシン用の最初の実際の同時コレクターです。

コレクターの設定パラメーター:-XX:+UseConcMarkSweepGC

CMS コレクターが実装ベースのコレクターであることは、その名前から理解するのに難しくありません。标记清除算法また、その操作プロセスは、以前のガベージ コレクターよりも複雑です。全体のプロセスは、次の 4 つのステップに分かれています。

  • 初期マーキング: すべてのアプリケーション スレッドを中断し、GC ルートによって直接参照されるオブジェクトを記録します。この段階は非常に高速です。
  • 同時マーキング: 同時マーキング フェーズは、GC ルートの直接関連付けられたオブジェクトからオブジェクト グラフ全体をトラバースするプロセスです. このプロセスは時間がかかりますが、ユーザー スレッドを一時停止する必要はなく、ガベージ コレクター スレッドと同時に実行できます。このフェーズはユーザー スレッドも実行されているため、マークされたオブジェクトの状態が変化する可能性があることに注意してください。
  • 再マーキング: この段階は、前の並行マーキング フェーズでユーザー スレッドの継続的な実行のためにマーキングが変更されたオブジェクトの一部のマーキング レコード (主に欠落したマーク) を修正することです. このフェーズの一時停止時間は通常、最初のマーキング フェーズよりも長くなります。わずかに長くなりますが、同時マーキング フェーズよりも短くなります。主に、再マーキング用の 3 色マークでインクリメンタル更新アルゴリズムを使用します。
  • 同時クリーンアップ: ユーザー スレッドが実行を継続できるようにします。同時に、GC スレッドもマークされていない領域のクリーンアップを開始します。この段階で、新しいオブジェクトがある場合、それらは処理なしで直接黒としてマークされます (詳細については、次の 3 色マーキング アルゴリズムを参照してください)。
  • 同時リセット: この GC プロセスでマークされたデータをリセットします。

ここに画像の説明を挿入

  • 利点: 同時収集、短い一時停止 (STW 時間は比較的短くなります)
  • 欠点:
    • (1) CPU リソースに敏感です (アプリケーション スレッドと同時に実行されるため、サービスとリソースを競合します)。
    • (2) 浮遊ガベージを処理できない (ガベージは同時マーキングおよび同時クリーニング フェーズ中に生成され、この浮遊ガベージは次の GC 後にのみクリーンアップできます)。
    • (3) 使用するリカバリ アルゴリズムは、标记清除算法コレクションの最後に大量のメモリの断片化を引き起こします. もちろん、これは、パラメータを設定して、-XX:+UseCMSCompactAtFullCollectionマーク クリアの実行後に jvm がクリーンアップできるようにすることで実行できます。
    • (4) 実行プロセスの不確実性、前回実行されなかったガベージ コレクションが発生し、その後 gc が再度トリガーされます。特に、同時マーキングおよび同時クリーニング フェーズでは、参照スレッドをリサイクルしながら実行しやすく、おそらく、まだリサイクルされていない可能性があります。フル gc をトリガーすると、" concurrent mode failure" が発生し、STW に入り、Serial old ガベージ コレクターを使用してリサイクル タスクを処理します。

関連する CMS のコア パラメータ:

-XX:+UseConcMarkSweepGC:cms を有効にする;
-XX:ConcGCThreads:同時 GC スレッドの数;
-XX:+UseCMSCompactAtFullCollection:FullGC 後に圧縮を行う (断片化を減らす);
-XX:CMSFullGCsBeforeCompaction:FullGC 後に圧縮する回数。デフォルトは 0 で、各 FullGC の後に一度圧縮されることを意味します
-XX:CMSInitiatingOccupancyFraction:;古い世代の使用率がこの比率に達する (デフォルトは 92 で、パーセンテージです);
-XX:+UseCMSInitiatingOccupancyOnly:設定された回復しきい値 (-XX:CMSInitiatingOccupancyFraction設定値) のみを使用します。指定されていない場合、JVM は初回のみ設定値を使用し、自動的に後で調整する;
-XX:+CMSScavengeBeforeRemark:CMS GC の前に開始する マイナー gc は CMS GC マーキング フェーズのオーバーヘッドを削減します (若い世代も一緒にマークされます。マイナー gc で多くのガベージ オブジェクトが強制終了された場合、マーキング フェーズによってマーキング時間が短縮されます) )、および一般的な CMS GC の時間のかかる 80% はマーキング段階にあります;
-XX:+CMSParallellnitialMarkEnabled:これは、最初のマーキング中にマルチスレッド実行を意味し、STW を短縮します;
-XX:+CMSParallelRemarkEnabled:再マーキング中にマルチスレッド実行を行い、STW を短縮します;

3. ガベージ コレクションの基本原則

1. 三色マーキング

同時マーキングのプロセスでは、アプリケーションスレッドがマーキング期間中に実行し続けるため、オブジェクト間の参照が変更される可能性があり、マルチマーキングおよびマーキングの欠落の状況が発生する可能性があります.マーキングの欠落の問題は主にそれを解決するために導入されています. 三色标记算法.

3 色マーキング アルゴリズムは、GC ルート到達可能性分析でオブジェクトをトラバースする過程で遭遇したオブジェクトを、「訪問したかどうか」の条件に従って次の 3 つの色にマークすることです。

  • : 黒でマークされたオブジェクトは、ガベージ コレクターによってアクセスされ、オブジェクトへのすべての参照がスキャンされ、存続しても安全であることを意味します。黒のオブジェクトを指している他のオブジェクト参照がある場合は、その必要はありません。再スキャンします。黒いオブジェクトは灰色のオブジェクトのみを指すことができ、白いオブジェクトを直接指すことはできません。
  • グレー: グレーでマークされたオブジェクトはガベージ コレクターによってアクセスされましたが、オブジェクトにはまだスキャンされていない参照があります。
  • : オブジェクトがガベージ コレクターによってアクセスされていないことを示します。到達可能性分析の開始時には、すべてのオブジェクトが白であり、到達可能性分析が終了した後もオブジェクトがまだ白である場合は、到達不能であることを意味します (つまり、ゴミオブジェクト)。

ここに画像の説明を挿入

たとえば、次のコード:

写真の説明を追加してください

マルチラベル - 浮遊ゴミ

並行マーキング プロセス中に、実行中のメソッドの終了により一部のローカル変数 (GC ルート) が破棄され、この GC ルートによって参照されるオブジェクトが以前にスキャンされた (存続オブジェクトとしてマークされた) 場合、このラウンドの GCこの部分のメモリはリサイクルされません。再利用されるべきであるが、再利用されていないメモリのこの部分は、「フローティング ガベージ」と呼ばれます。フローティング ガベージはガベージ コレクションの正確性には影響しません需要等到下一轮垃圾回收中才被清除

さらに、コンカレント マーキング (およびコンカレント クリーニング) の開始後に生成された新しいオブジェクトの場合、通常はそれらをすべて黒として直接扱い、このラウンドではクリアされません。オブジェクトのこの部分も期間中にゴミになる可能性があり、これも浮遊ゴミの一部です。

ラベルがありません - バリアの読み取りと書き込み

ラベルが漏洩すると、参照されたオブジェクトがゴミとして誤って削除される原因となります. これは解決しなければならない深刻な問題です. 2 つの解決策があります:增量更新(Incremental Update)和原始快照(Snapshot At The Beginning,SATB)

増分更新: 黒のオブジェクトが白のオブジェクトを指す新しい参照関係を挿入すると、将这个新插入的引用记录下来同時スキャンが終了した後、記録された参照関係の黒のオブジェクトがルートとして使用され、再度スキャンされます。これを単純化すると、白いオブジェクトを参照して黒いオブジェクトが新たに挿入されると、灰色のオブジェクトになることがわかります。

元のスナップショット: 灰色のオブジェクトが白いオブジェクトを指している参照関係を削除したい場合、将这个要删除的引用记录下来同時スキャンが終了した後、記録された参照関係の灰色のオブジェクトをルートとして使用し、再度スキャンして、白いオブジェクトを削除できるようにします。オブジェクトをスキャンし、白いオブジェクトを直接黒としてマークします (目的は、このオブジェクトを gc クリーンアップの現在のラウンドで存続させ、gc の次のラウンドで再スキャンすることです。このオブジェクトはフローティング ガベージでもある可能性があります)。

参照関係レコードの挿入または削除に関係なく、仮想マシンのレコード操作はすべて書き込みバリアを通じて実装されます。

書き込みバリア

いわゆる書き込みバリアとは、簡単に言えば、割り当て操作の前後に何らかの処理を追加することです (Spring の AOP コンセプトに似ています)。

写真の説明を追加してください

  • 書き込みバリアは SATB (元のスナップショット) を実装します。
    オブジェクト B のメンバー変数の参照が変更された場合、たとえば、参照が消える (abd = null) 場合、書き込みバリアを使用して、元のメンバー変数の参照オブジェクト D を記録できます。 B:
    写真の説明を追加してください

  • 増分更新を実現する書き込みバリア
    オブジェクト A のメンバー変数の参照が新しい参照 (ad = d) などで変更された場合、書き込みバリアを使用して、A の新しいメンバー変数参照オブジェクト D を記録できます。
    写真の説明を追加してください

バリアを読む

写真の説明を追加してください
読み取りバリアは、最初のステップを直接対象としています: D d = abd、メンバー変数を読み取るとき、すべてのレコードが記録されます:
写真の説明を追加してください

最新のトレース (到達可能性分析に基づく) ガベージ コレクターは、実装方法が異なりますが、ほぼすべてのアルゴリズムの 3 色マーキングの考え方を取り入れています。場所を反映する)、グレーコレクションはスタック&キュー&キャッシュログなどによって実現でき、トラバーサル方法は幅&深さトラバーサルなどです。

読み取り/書き込みバリアの場合、Java HotSpot VM を例にとると、同時マーキング中の欠落マークの処理スキームは次のとおりです。

  • CMS: 書き込みバリア + インクリメンタル更新
  • G1、シェナンドー: 書き込みバリア + SATB
  • ZGC: バリアを読む

また、読み書きバリアには他にも機能があり、例えば、世代間・領域参照の変化を記録する書き込みバリアや、移動オブジェクトの同時実行をサポートする読み込みバリアなどがあります。パフォーマンスに関する考慮事項です。

CMS コレクターが増分更新を使用するのに、なぜ G1 コレクターは SATB を使用するのですか?
       個人的な理解: 実際、増分更新と元のスナップショットの最大の違いは、SATB は再マーキング段階で削除された参照オブジェクトを再度深くスキャンする必要がないのに対し、新しい更新では新しく追加されたルートでディープ スキャンを実行することです。オブジェクト. 同時に, G1 多くのオブジェクトが異なる地域にあり、CMS は古い世代の領域であるため. したがって, オブジェクトを詳細に再スキャンすると、G1 コレクターの構造にとって明らかにコストが高くなります. したがって, G1 は選択しますSATB であり、オブジェクトを詳細にスキャンするのではなく、単純なマークであり、次のラウンド GC までディープ スキャンで待機します。

2.メモリーセットとカード一覧

世代を超えて参照されるオブジェクトは、若い世代做GC Root可达性扫描で検出される場合があります又去对老年代再去扫描效率太低このため、新しい世代に導入できる记录集(Remember Set)データ構造 ( ) は记录从非收集区到收集区的指针集合、古い世代全体を GC ルートのスキャン範囲に追加することを回避します。実はこれは新世代と旧世代の世代間参照の問題だけではなく、G1コレクタやZGCコレクタなど、部分領域コレクション(Partial GC)を伴うすべてのガベージコレクタが同じ問題に直面します。ガベージ コレクションのシナリオでは、コレクターはメモリ セットを介して特定の非コレクション領域にコレクション領域へのポインターがあるかどうかを判断するだけでよく、世代間参照ポインターのすべての詳細を知る必要はありません

Hotspot は、卡表(Cardtable)メモリ セットを実装するために呼び出されるメソッドを使用します。これは、現在最も一般的に使用されているメソッドでもあります。

ここに画像の説明を挿入

カード テーブルは、バイト配列を使用して実装されます:CARD_TABLE[]各要素は、「カード ページ」と呼ばれる、特定されたメモリ領域内の特定のサイズのメモリ ブロックに対応します。HotSpot が使用するカード ページのサイズは 2 9 です。つまり、512バイトです。

カード ページには複数のオブジェクトを含めることができます. オブジェクトのフィールドに世代間ポインターがある限り、対応するカード テーブルの要素 ID は 1 になり、要素がダーティであることを示します。コレクション領域のカード テーブル内のダーティな要素が GCRoots に追加されます。


カードテーブルのメンテナンス:
       カードテーブルをダーティにする方法は上記で説明しましたが、カードテーブルをダーティにする方法、つまり、参照フィールドの割り当てが発生したときにカードテーブルの対応する ID を 1 に更新する方法と、Hotspot を知っておく必要があります。書き込みバリアを使用して、カード テーブルのステータスを維持します。


参照:

「Java仮想マシンの深い理解」

おすすめ

転載: blog.csdn.net/qq_40436854/article/details/130038215