技術共有

[JVM の基礎] Java ガベージ コレクターの概要

2024-07-11

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

ガベージ コレクター (ガベージ コレクション アルゴリズムの実装)

ガベージ コレクターは、ガベージ コレクション アルゴリズムの特定の実装です。 。ガベージコレクタはG1(新世代と旧世代の両方を制御できる)に加えて、若い世代と古い世代に分かれているため、新世代と旧世代のガベージ コレクターは、ホットスポットの要件に従ってペアで使用する必要があります。(JDKのバージョンに応じて対応する組み合わせを選択する必要があります)

具体的な組み合わせ関係は以下の通りです。

ここに画像の説明を挿入します

JVM の基礎となるソース コードでは、特殊な場合に、CMS リサイクラが Serial Old リサイクラを呼び出します。

Arthas が使用するガベージ コレクターを表示します

どのようなガベージ コレクターが使用されているかを直接確認することはできません。アルゴリズムに基づいて推測することしかできません。

ここに画像の説明を挿入します

若い世代 - シリアル ガベージ コレクター

シリアルは、若い世代のシングルスレッド シリアル コレクションガベージコレクター。

ここに画像の説明を挿入します

リサイクルの年齢とアルゴリズム

  • 若い世代
  • レプリケーションアルゴリズム

アドバンテージ

単一の CPU プロセッサでの優れたスループット

欠点がある

マルチ CPU でのスループットは、他のガベージ コレクター (シングル スレッド、1 つの CPU のみを使用) ほど良くありません。ヒープが大きすぎると、ユーザー スレッドは長時間待機することになります。

該当シーン

Java で書かれたクライアント プログラム、または限られたハードウェア構成 (CPU コアがあまり多くない) のシナリオ

使い方

-XX: UseSerialGC: 新世代も旧世代もシリアルコレクタを使用しています。

旧世代 - シリアル古いガベージ コレクター

SerialOld はシリアル ガベージ コレクターの旧世代バージョンであり、シングルスレッドのシリアルコレクション

ここに画像の説明を挿入します

リサイクルの年齢とアルゴリズム

  • 老齢
  • マーク照合アルゴリズム

アドバンテージ

単一の CPU プロセッサでの優れたスループット

欠点がある

マルチ CPU でのスループットは他のガベージ コレクターほど良くありません。ヒープが大きすぎると、ユーザー スレッドは長時間待機することになります。

該当シーン

シリアル ガベージ コレクターまたは CMS の特殊なケースで使用されます。

使い方

-XX: UseSerialGC: 新世代も旧世代もシリアルコレクタを使用しています。

若い世代-パー新しいガベージコレクター

ParNew ガベージ コレクターは本質的には複数の CPU でのシリアルの最適化、ガベージ コレクションにマルチスレッドを使用する

ここに画像の説明を挿入します

リサイクル年齢とアルゴリズム:

  • 若い世代
  • レプリケーションアルゴリズム

アドバンテージ

  • マルチ CPU プロセッサ下での休止時間の短縮

欠点がある

  • スループットと一時停止時間は G1 ほど良くないため、JDK9 以降は推奨されません

該当シーン

  • JDK8 以前のバージョンでは、CMS の旧世代のガベージ コレクターと組み合わせて使用​​されます。

使い方

  • -XX: UseParNewGC: 新世代は ParNew コレクターを使用し、旧世代はシリアル コレクターを使用します。

ここに画像の説明を挿入します

旧世代 - CMS (同時マーク スイープ) ガベージ コレクター

CMS ガベージ コレクターは、(STW を最小限に抑え、ユーザー エクスペリエンスを最適化するために) システムの一時停止時間を重視します。特定のステップでユーザー スレッドとガベージ コレクション スレッドを同時に実行できるようにする、ユーザースレッドの待機時間を短縮します。

リサイクルの年齢とアルゴリズム

  • 老齢
  • マークアンドスイープアルゴリズム

アドバンテージ

  • ガベージ コレクションによるシステムの停止時間が短くなり、ユーザー エクスペリエンスが向上します。

欠点がある

1. メモリの断片化の問題

2. 劣化の問題 (特定のケースでは、SerialOld などのシングルスレッド コレクターに劣化します)

3. 浮遊ゴミ問題(リサイクル工程でリサイクルできないゴミもある)

該当シーン

注文インターフェイス、製品インターフェイスなど、ユーザーが大量のデータを高頻度で要求する大規模なインターネット システムのシナリオ。

使用

XX: UseConcMarkSweepGCでは、若い世代と古い世代のコレクターをそれぞれ設定できます。

ここに画像の説明を挿入します

ここに画像の説明を挿入します

CMSの実行手順

  1. 初期マーキング、非常に短時間でのマーキングGC ルートが直接関連付けることができるオブジェクト
  2. 同時マーキング、 すべてのオブジェクトにマークを付けるの場合、ユーザー スレッドを一時停止する必要はありません。 (同時マーキングはユーザースレッドと並行して実行されますが、同時マーキングにより占有されるリソースが多い場合、ユーザースレッドにも影響します)
  3. リマーキング (同時実行)。一部のオブジェクトは同時マーキング フェーズ中に変更されるため、ラベルの誤り (使用されたオブジェクトは元々生きていましたが、マーキング後にユーザー スレッドによってオブジェクトが実行不可能になり、ラベルの誤りが発生しました)、ラベルの欠落が発生します (これは同時実行であり、一部のオブジェクトはユーザー スレッドによって作成されたばかりである可能性があり、タグの欠落につながります) などの状況があり、再マークする必要があります。
  4. 同時クリーンアップ、死んだオブジェクトのクリーンアップ、ユーザー スレッドを一時停止する必要はありません。

注: STW は、初期マーキング段階と再マーキング段階中にのみ表示されます。

ここに画像の説明を挿入します

欠点:

1. CMS は、オブジェクトの割り当てに影響を与えないように、マークアンドクリア アルゴリズムを使用します。CMS はフル GC 中にデフラグを実行します。 。これにより、ユーザー スレッドが一時停止します。-XX:CMSFullGCsBeforeCompaction=N パラメーター (デフォルトは 0) を使用すると、フル GC を並べ替える前に N 回調整できます。

2. 同時クリーンアップ プロセス中に生成された「フローティング ガベージ」を処理できず、完全なガベージ コレクションを達成できません (このクリーンアップ プロセス中、ユーザー スレッドはいくつかのオブジェクトを並行して作成しましたが、それらはすぐには再使用されませんでした。これらのオブジェクトは存在しません)このクリーンアップでリサイクルされ、次のクリーンアップまで待つ必要があるため、浮遊ゴミと呼ばれます)。

3. 古い世代にオブジェクトを割り当てるためのメモリが不足している場合、CMS は古い世代をリサイクルする Serial Old シングルスレッドに縮退します。

同時スレッドの数:

CMS で同時フェーズを実行するときのスレッド数を渡すことができます。-XX:ConcGCThreadsパラメータ設定はシステムによって計算され、計算式は次のとおりです。(-XX:ParallelGCThreads定义的线程数 3) / 4、ParallelGCThreads は、STW 一時停止後の並列スレッドの数です。

ParallelGCThreads はプロセッサ コアの数によって決まります。

1. CPU コア数が 8 未満の場合、ParallelGCThreads = CPU コア数

2. それ以外の場合、ParallelGCThreads = 8 (CPU コアの数 – 8)*5/8

私のコンピュータには 12 個の論理プロセッサがあるため、ParallelGCThreads = 8 (12 - 8) * 5/8 = 10、ConcGCThreads = (-XX: ParallelGCThreads 3 で定義されたスレッドの数) / 4 = (10 3) / 4 = 3

ここに画像の説明を挿入します

最後に、次の画像を取得できます。

ここに画像の説明を挿入します

同時マーキングフェーズと同時クリーニングフェーズは、3 つのスレッドを使用して並行して処理されます。再マーキングフェーズは 10 個のスレッドを使用して処理されます。 CPU コアの数は限られているため、同時フェーズはユーザー スレッド実行のパフォーマンスに影響します。

ここに画像の説明を挿入します

若い世代 - パラレル スカベンジ ガベージ コレクター

パラレルスカベンジはJDK8のデフォルトの若い世代のガベージコレクタ、マルチスレッド並行収集システムのスループットに重点を置く 。スループットを向上させるために、PS はヒープメモリサイズを自動調整(新世代、旧世代のメモリサイズ、プロモーションしきい値を調整)

ここに画像の説明を挿入します

リサイクルの年齢とアルゴリズム

  • 若い世代
  • レプリケーションアルゴリズム

アドバンテージ

  • スループットが高く、スループットを制御するためのパラメータの手動設定をサポートしています。スループットを向上させるために、仮想マシンはヒープのパラメータを動的に調整します (ユーザーはスループットを設定するだけでよく、メモリ サイズなどの他のパラメータを設定する必要はありません)。

欠点がある

  • 単一の一時停止時間の保証はありませんが、STW 時間の設定はサポートされています。

該当シーン

  • バックグラウンド タスクはユーザーの操作を必要とせず、多数のオブジェクトを生成する傾向があります。例: ビッグデータ処理、大きなファイルのエクスポート

共通パラメータ

Parallel Scavenge では、最大一時停止時間とスループットを手動で設定できます。 Oracle 担当者は、この組み合わせを使用する場合は最大ヒープ メモリを設定しないことを推奨しています。ガベージ コレクタは、最大一時停止時間とスループットに基づいてメモリ サイズを自動的に調整します。

  • 最大一時停止時間、-XX:MaxGCPauseMillis=n 各ガベージ コレクションで一時停止する最大ミリ秒数を設定します。
  • スループット、-XX:GCTimeRatio=n スループットを n に設定します (ユーザー スレッドの実行時間 = n/(n 1))
  • メモリサイズを自動的に調整し、 -XX: UseAdaptiveSizePolicyこの設定により、ガベージ コレクタはスループットと最大一時停止ミリ秒に基づいてメモリ サイズを自動的に調整できます。このパラメータはデフォルトで有効になります (PS の組み合わせを使用する場合は、最大ヒープ メモリを設定せず、ガベージ コレクタが自動的に調整することをお勧めします)。

注: 最大一時停止時間とスループットの 2 つの指標は矛盾しています。ガベージ コレクターは、最大一時停止時間を満たそうと最善を尽くします (設定が小さすぎて満たすことができず、設定された最大一時停止時間を超過する場合があります)。 、スループットが犠牲になります。最大一時停止時間とスループットを同時に設定したい場合は、テストをさらに実行して、それらをより調整する必要があります。

旧世代 - パラレル古いガベージ コレクター

Parallel Old は、マルチスレッド同時収集を利用する Parallel Scavenge コレクター用に設計された旧世代バージョンです。

ここに画像の説明を挿入します

リサイクルの年齢とアルゴリズム

  • 老齢
  • マークアンドソートアルゴリズム (実際にはマークアンドスイープソート)

アドバンテージ

  • マルチコア CPU では同時収集がより効率的になります

欠点がある

  • 一時停止時間が長くなります

該当シーン

  • パラレルスカベンジと併用

使い方

JDK8 は、デフォルトでこのリサイクラーを使用するようにパラメーターを設定します。

パラメータ:-XX: UseParallelGC または-XX: UseParallelOldGCパラレル スカベンジ パラレル オールドの組み合わせで使用できます。
ここに画像の説明を挿入します

ここに画像の説明を挿入します

テスト

-XX: PrintFlagsFinal:プログラム起動時にすべての設定項目の最終値を印刷でき、自動調整機能がオンになっているかどうかを確認できます。

ここに画像の説明を挿入します

ここに画像の説明を挿入します

ここに画像の説明を挿入します

ここに画像の説明を挿入します

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 垃圾回收器案例3
 */
//-XX: UseSerialGC -Xmn1g -Xmx16g -XX:SurvivorRatio=8  -XX: PrintGCDetails -verbose:gc -XX: PrintFlagsFinal
//-XX: UseParNewGC  -Xmn1g -Xmx16g -XX:SurvivorRatio=8  -XX: PrintGCDetails -verbose:gc
//-XX: UseConcMarkSweepGC
//-XX: UseG1GC   -Xmn8g -Xmx16g -XX:SurvivorRatio=8  -XX: PrintGCDetails -verbose:gc MaxGCPauseMillis
//-XX: PrintFlagsFinal  -XX:GCTimeRatio = 19  -XX:MaxGCPauseMillis=10 -XX: UseAdaptiveSizePolicy
public class GcDemo2 {

    public static void main(String[] args) throws IOException {
        int count = 0;
        List