さまざまなメモリ オーバーフローやメモリ リークのトラブルシューティングが必要な場合、およびシステムがより高い同時実行性を達成するためにガベージ コレクションがボトルネックになる場合、これらを監視して調整する必要があります。
ディレクトリタイトル
1.対象者は死亡している
-
参照カウントアルゴリズム: 参照がある場合、カウンタは 1 つインクリメントされ、参照が無効な場合、カウンタは 1 つ減らされ、相互参照は再利用できません。
-
アクセシビリティ分析
- GC Roots のルート オブジェクトは開始ノード セットとして使用され、検索プロセスによって通過するパスは「参照チェーン」と呼ばれます。
- オブジェクトと GC ルートの間に参照リンクがなく、オブジェクトに到達できない場合、そのオブジェクトはもう使用できないことがわかります。
- GC ルート オブジェクト
- 仮想マシン スタックで参照されるオブジェクト: パラメーター、ローカル変数、一時変数など。
- メソッド領域の静的プロパティによって参照されるオブジェクト、定数によって参照されるオブジェクト: 参照型静的変数、文字列定数プール内の参照
- ネイティブ メソッド スタック内の JNI によって参照されるオブジェクト
- Java 仮想マシン内の参照、同期ロックによって保持されるすべてのオブジェクトなど。
-
引用について話しましょう
- 強参照: プログラム コード内で遍在する参照割り当て。ガベージ コレクターは参照されたオブジェクトを決してリサイクルしません。
- ソフト参照: まだ有用ではあるが必要ではないオブジェクト。これらのオブジェクトは 2 回目のリサイクルのリサイクル範囲に含まれます。
- 弱い参照: 次のガベージ コレクションが発生するまで存続する非必須オブジェクト
- ファントム参照: 最も弱い参照関係。オブジェクト インスタンスは仮想参照を通じて取得できず、リサイクル時にシステム通知を受け取ります。
-
生きるか死ぬか
- 実際の死は 2 回マークする必要があります。最初は参照チェーンがないため、finalize() メソッドは 1 回保存できます。
-
リサイクル方法分野
- メソッド領域のガベージ コレクションは主に、廃止された定数と使用されなくなった型の 2 つの部分をリサイクルします。
- 廃止された定数: 他では参照されていません
- 使用されなくなった型: すべてのインスタンスはリサイクルされ、クラスをロードしたクラス ローダーはリサイクルされ、java.lang.Class オブジェクトはどこからも参照されません。
2. ガベージコレクションアルゴリズム
- 世代別コレクション理論
- 弱い世代の仮説: 生と死
- 強力な世代仮説: より多くのガベージ コレクションで生き残るオブジェクトは、消滅しにくいです。
- 世代間参照仮説: オブジェクト間には世代間参照が存在します。
- 設計原則
- 年齢に応じて異なるエリアを分割し、それらをまとめます(少数の生存者のみに注意を払う)、および腐りにくいオブジェクトをまとめます(このエリアを低頻度でリサイクルします)
- マイナー GC (新世代コレクション)、メジャー GC (旧世代コレクション、CMS)、フル GC、混合 GC (混合コレクション、G1)
- メモリ セット: 古い世代をいくつかの小さなブロックに分割し、古い世代のどのメモリ部分が世代間参照を持つかを特定し、世代間参照を持つ小さなメモリ オブジェクトをマイナー GC 中の GC ルート スキャンに追加します。
- マーククリア アルゴリズム: 最も基本的なガベージ コレクション アルゴリズム、不安定な実行効率、メモリ領域の断片化の問題 (次の割り当てに十分な連続メモリがありません)
- マークコピーアルゴリズム: 2 つの部分に分割し、1 つの部分が使い果たされたら残った部分をもう一方の部分にコピーし、最初の部分をクリーンアップすると、メモリは元の半分に減ります。
- ほとんどの Java 仮想マシンは、このアルゴリズムを使用して新しい世代をリサイクルすることを優先し、通常、このアルゴリズムを古い世代で直接使用することはできません。
- アピール スタイルのリサイクル: 新世代は、より大きな Eden スペースと 2 つの小さな Survivor スペースに分割されます。Eden と Survivor の比率は 8:1 です。過剰容量を避けるために、割り当ての保証が必要です
- マークソートアルゴリズム: 生き残ったオブジェクトはメモリ空間の一端に移動し、境界の外側のメモリを直接クリーンアップします。
- 移動するとメモリの回復がより複雑になり、移動しないとメモリの割り当てがより複雑になります。
- そして、muddy タイプ: 通常はマーククリアアルゴリズムを使用し、断片化が大きい場合にはマークソートアルゴリズムを使用します。
3. HotSpotアルゴリズムの実装詳細
- ルートノードの列挙
- OopMap データ構造にはオブジェクト参照が保存されます。クラス読み込みアクションが完了すると、HotSpot はオブジェクト内のオフセットにあるデータのタイプを計算します。これはスキャン時に直接使用できます。
- セーフティ ポイント: GC ルートが列挙されている場合、スレッドは一時停止する必要があります。セーフティ ポイントが設定されている場合、スレッドはセーフティ ポイントに到達した後にのみ停止できます。
- アクティブな割り込み: フラグ ビットを設定し、各スレッドがポーリングします。割り込みフラグが見つかると、アクティブな割り込みは最も近い安全なポイントで一時停止されます。
- 安全領域: スレッドは安全な場所に行って中断したり中断したりすることができないため、安全領域を導入する必要があります (スレッドは安全領域を出て、仮想マシンがルート ノードの列挙を完了したかどうかを確認する必要があります) メモリ セットとカード
テーブル- メモリ セット: 古い世代全体が GC ルート スキャン範囲に追加されるのを避けるために使用されます。
- カードテーブル: カード精度 (記録はメモリ領域に対して正確です)
- ダーティ: カード ページのオブジェクトのフィールドに世代間ポインタがあり、フラグが 1 になり、ダーティになることを意味します。
- ライトバリア: カードテーブルの状態を維持します。
- 割り当て前の書き込みバリアはプレライト バリアと呼ばれ、割り当て後の書き込みバリアはポストライト バリアと呼ばれます。
- 同時到達可能性分析
- 三色のマーク
- 白: オブジェクトがガベージ コレクターによってアクセスされていないことを示します
- 黒: オブジェクトがガベージ コレクターによってアクセスされ、すべての参照がスキャンされたことを示します。
- 灰色: オブジェクトがガベージ コレクターによってアクセスされており、スキャンされていない参照が少なくとも 1 つあることを示します。
- 同時スキャンで消えたオブジェクトを修正: 増分更新、オリジナルのスナップショット
- 増分更新: 白いオブジェクトへの参照を挿入した後、黒いオブジェクトが灰色のオブジェクトに戻ります (CMS)
- 元のスナップショット:参照関係が削除されているか否かに関わらず、スキャン開始直後のオブジェクトグラフのスナップショットに従って検索が実行されます(G1、シェナンドー)
- 三色のマーク
4 番目、古典的なガベージ コレクター
- シリアルコレクター
- 最も基本的で最も古いシングルスレッドコレクター
- クライアントモードのデフォルトの若い世代コレクター
- パーニューコレクター
- シリアル コレクターのマルチスレッド並列バージョン、サーバー モードで実行される HotSpot 仮想マシン
- ParNew は、CMS をアクティブ化した後のデフォルトの新世代コレクターです (-XX: +UseConcMarkSweatGC) (-XX: +UseParNewGC は必須または無効です)
- 並列: 並列は、複数のガベージ コレクター スレッド間の関係を表します。
- コンカレント: コンカレントは、ガベージ コレクター スレッドとユーザー スレッドの関係を表します。
- パラレルスカベンジコレクター
- 新世代のコレクターは、マークコピー アルゴリズムに基づいており、並列収集されるマルチスレッド コレクターにより、制御可能なスループットを実現します。
- スループット = ユーザー コードの実行時間 / (ユーザー コードの実行時間 + ガベージ コレクションの実行時間)
- -XX: MaxGCPauseMillis は、ガベージ コレクションの最大一時停止時間を制御します
- -XX: GCTimeRatio はスループット サイズを直接設定します
- シリアルオールドコレクター
- 旧世代バージョンのシリアル コレクター、シングル スレッド コレクション、マーククリア アルゴリズム
- パラレルオールドコレクター
- Parallel Scavenge コレクターの古いバージョン、マークソートに基づくマルチスレッド同時コレクション
- スループットが重要である場合、またはプロセッサ リソースが不足している状況では、Parallel Scavenge コレクターと Parallel Old コレクターの組み合わせを検討できます。
- CMSコレクター
- マークスイープアルゴリズム、同時収集、低一時停止に基づいて、最短の回復一時停止時間を取得することを目的としたコレクター
- 4つのステップ
- 初期マーキング: GC ルートが直接関係できるオブジェクトをマークするだけで、高速かつプロセッサ リソースに非常に敏感です。
- 同時マーキング: GC ルートの直接関連付けられたオブジェクトから開始して、オブジェクト グラフ プロセス全体を横断し、ガベージ コレクション スレッドと並行して実行できます。
- リマーキング:同時マーキングの修正中に、ユーザプログラムの継続動作によりマークが変更されたオブジェクトの部分のマーク記録
- 同時クリーンアップ: マークフェーズによって判断された無効なオブジェクトをクリーンアップして削除します。
- 最初のタグ付け、再フラグ付けには引き続き「Stop The World」が必要です
- リサイクルスレッドの数: (プロセッサコアの数 + 3) / 4
- 「フローティング ガベージ」、同時マーキングおよび同時クリーニング フェーズを処理できず、ユーザー スレッドは実行を続けて、現在のコレクションで処理できない新しいガベージ オブジェクトを生成します。
- 同時収集中のプログラム操作のためにスペースの一部を予約する必要があり、スペースの 68% が使用されると古い世代がアクティブ化されます。
- ゴミファーストコレクター
- 主にサーバー側アプリケーション向けのフル機能のガベージ コレクターが、メモリ リサイクルの「動作」と「実装」を分離します。
- ヒープ メモリの任意の部分をリサイクルするためのリサイクル コレクションを形成するための、混合 GC モード
- 測定の基準は、もはやどの世代に属するかではなく、どのメモリに最も多くのゴミが保存され、リサイクルのメリットが最も大きいかということです。
- リージョンのヒープ メモリ レイアウトに基づいて、G1 は Java ヒープを同じサイズの複数の独立したリージョン (リージョン) に分割し、各リージョンは必要に応じて Eden および Survivor スペースとして機能できます。
- 単一リカバリの最小単位としてリージョンを使用する
- 記憶されたセットを使用して、GC ルートとしてのヒープ全体のスキャンを回避します
- 4つのステップ
- 初期マーキング: GC ルートが直接関係できるオブジェクトをマークするだけです
- 同時マーキング: GC ルートから始まるヒープ内のオブジェクトの到達可能性分析
- 最後のマーク: ユーザー スレッドでもう一度短い一時停止
- スクリーニングと回復: 地域の統計データの更新を担当します。
- G1 は大容量メモリのアプリケーションで利点を発揮できます
5. 低遅延ガベージ コレクター
- ガベージ コレクターを測定するための重要な指標: メモリ使用量、スループット、レイテンシ
5.1 シェナンドーコレクター
- 任意のヒープメモリサイズ下でガベージコレクションの一時停止時間を10ミリ秒以内に制御できるメソッドを実装する
- 同時ガベージ マーキングだけでなく、オブジェクト クリーニング後の同時クリーニング アクションも実行可能
- G1との違い
- 同時実行をサポートする照合アルゴリズム
- 世代別コレクションはデフォルトでは使用されません
- メモリ セットの代わりに、接続マトリックスのグローバル データ構造を使用して、リージョン間の参照関係を記録します。
- 作業過程
- 初期マーク: GC ルートに直接関連付けられたオブジェクト
- 同時マーキング: オブジェクト グラフを走査し、到達可能なすべてのオブジェクトをマークします。
- 最終マークアップ: 残りの SATB スキャンの処理
- 同時クリーンアップ: 領域全体で生存オブジェクトが見つからない領域
- 同時リサイクル: まず、残っているオブジェクトを他の未使用のリージョンにコピーします。
- 初期化参照の更新: ヒープ内の古いオブジェクトへの参照は、コピー後に新しいアドレスに固定されます。
- 同時参照更新: 参照更新操作の実際の開始
- リファレンスの最終更新: GC ルートに存在するリファレンスを修正
- 同時クリーンアップ: コレクション セット全体のすべてのリージョンに存続オブジェクトがありません。
- 重要なフェーズ: 同時マーク、同時収集、同時参照更新
- ポインタの転送: オブジェクトに新しいコピーがある場合、1 つのポインタの値 (新しいオブジェクトを指すように古いオブジェクトの前方ポインタの位置) を変更するだけで済みます。
5.2 ZGCコレクター
- リージョン メモリ レイアウトに基づいて、生成なしで、読み取りバリア、カラー ポインタ、およびメモリ複数マッピングを使用して同時マークソート アルゴリズムを実装します。
- ZGC のリージョンは動的です。動的に作成および破棄され、リージョンの容量サイズも動的に変化します。
- 小領域: 容量は 2MB に固定されており、256KB 未満の小さなオブジェクトを配置するために使用されます。
- 中サイズ領域:容量は32MB固定で、256KBを超え4MB未満のオブジェクトが配置されます
- Largeリージョン:容量は固定ではなく動的に変更可能、2MBの整数倍、4MB以上のラージオブジェクトが配置される
- 象徴的なデザインは染色ポインター技術の使用です
- 作業工程
- 同時マーキング: 同時マーキングは、到達可能性分析のためにオブジェクト グラフを走査する段階です。
- 同時準備再配布: 特定のクエリ条件に従って、この収集プロセスでクリーンアップするリージョンが計算され、これらのリージョンが再配布セットを形成します。
- 同時再配布: 再配布セット内の存続するオブジェクトを新しいリージョンにコピーし、各リージョンへの再配布用の転送テーブルを維持します。
- 同時再マッピング: 再割り当てセット内の古いオブジェクトを指すヒープ全体内のすべての参照を変更します。
6. 適切なガベージ コレクターを選択する
- Epsilon: no-op コレクター
- コレクターのトレードオフ: スループット、レイテンシー、メモリー占有量
- 仮想マシンとガベージ コレクターのログ
- HotSpot のすべての機能のログが「-Xlog」パラメータに返されます。
- パラメータの概要
7. メモリの割り当てと回復戦略
- オブジェクトは最初に Eden に割り当てられます
- オブジェクトは新世代の Eden 領域に割り当てられ、Eden 領域に割り当てられる十分なスペースがない場合、仮想マシンはマイナー GC を開始します
- 大きなオブジェクトは古い世代に直接転送されます
- 大きなオブジェクト: 多数の連続したメモリ空間 (非常に長い文字列、多数の要素を含む配列) を持つ Java オブジェクト。大きなオブジェクトはメモリ コピーのオーバーヘッドが高くなります。
- HotSpot には次の機能があります。 -XX: PretenureSizeThreshold パラメータ。この設定値より大きいオブジェクトが古い世代に直接割り当てられるように指定し、Eden エリアと 2 つの Survivor エリアの間でのコピーの往復を回避します。
- 長寿命のオブジェクトは古い世代に入る
- 仮想マシンはオブジェクトごとに経過時間カウンターを定義し、マイナー GC を乗り越えるたびに経過時間は 1 ずつ増加します。
- 旧世代の年齢しきい値まで引き上げます -XX: MaxTenuringThreshold 設定
- 動的なオブジェクトの年齢判定
- Survivor 空間内の同じ年齢のすべてのオブジェクトのサイズの合計が Survivor 空間の半分より大きい場合、年齢がこの年齢以上のオブジェクトは直接古い年齢に入ります。
- スペース割り当ての保証
- マイナー GC の前に、仮想マシンはまず古い世代の最大利用可能な連続スペースが新しい世代のすべてのオブジェクトの合計スペースより大きいかどうかを確認する必要があります。
- 確立されていない場合は、古い世代で使用可能な最大連続領域が古い世代に昇格されたオブジェクトの平均サイズよりも大きいかどうかのチェックが継続され、マイナー GC が開始される危険性があります。
- 失敗がフル GC をトリガーする
- マイナー GC の前に、仮想マシンはまず古い世代の最大利用可能な連続スペースが新しい世代のすべてのオブジェクトの合計スペースより大きいかどうかを確認する必要があります。