ホームページ  >  記事  >  Java  >  Java GC について (2)

Java GC について (2)

黄舟
黄舟オリジナル
2017-02-22 10:09:181500ブラウズ

コレクション アルゴリズム

ガベージ コレクション アルゴリズムには主に、マーククリア、コピー、マーク整理が含まれます。

1. マークアンドクリアアルゴリズム

リサイクルするオブジェクトをマークします。

アルゴリズムの欠点: 効率の問題、マーキングとクリアのプロセスは非常に非効率的です; スペースの問題、収集後に大量のメモリの断片が生成されるため、大きなオブジェクトの割り当てには役立ちません。

2. コピー アルゴリズム

コピー アルゴリズムは、使用可能なメモリを 2 つの同じサイズのブロック A と B に分割します。一度に 1 つだけが使用され、A のメモリがなくなると、残ったオブジェクトが B にコピーされます。 A のメモリをクリアすると、生き残ったオブジェクトのみをマークする必要があるため、マークの効率が向上するだけでなく、使用可能なメモリが元のサイズの半分に減少するという犠牲を払って、メモリの断片化の問題も回避されます。

3. マーク照合アルゴリズム

旧世代ではオブジェクトの生存率が高く、コピーアルゴリズムの効率が非常に低かった。マークコンパクト アルゴリズムでは、すべての生きているオブジェクトがマークされて一方の端に移動され、境界の外側のメモリが直接消去されます。

オブジェクトマーキングプロセス

到達可能性分析プロセス中に、GC ルートに関連付けられたオブジェクトを正確に見つけるには、実行エンジン全体が特定の時点でフリーズしているように見える必要があります。実行中のスレッドでは、オブジェクトの参照関係が変化し続けることはできません。

GC ルートを素早く列挙するにはどうすればよいですか?

GC ルートは主にグローバル参照 (定数またはクラスの静的プロパティ) と実行コンテキスト (ローカル変数テーブルの参照) にあり、走査して検索すると、その効率は非常に高くなります。低い。 。

HotSpot では、OopMap と呼ばれる一連のデータ構造を使用して実装されます。クラスのロードが完了すると、HotSpot はオブジェクト内のどのオフセットにどのようなタイプのデータがあるかを計算し、それを OopMap に格納します。JIT を通じてコン​​パイルされたローカル コードは、スタックとレジスタ内のどの位置が参照であるかも記録します。 GC が発生した場合、OopMap データをスキャンすることで、生き残ったオブジェクトを迅速に特定できます。

安全な GC を行うには?

スレッドの実行中は、安全なポイントに到達した場合にのみ GC のために停止できます。

OopMap データ構造に基づいて、HotSpot は GC ルートの走査を迅速に完了できますが、HotSpot は各命令に対応する OopMap を生成せず、この情報をセーフ ポイントに記録するだけです。

したがって、セーフ ポイントの選択は非常に重要です。少なすぎると、GC の待機時間が長すぎる可能性があります。頻繁すぎると、実行時のパフォーマンスの問題が発生する可能性があります。ほとんどの命令の実行時間は非常に短く、メソッド呼び出し、ループ ジャンプ、例外ジャンプなど、実行時間の長い一部の命令は通常、セーフ ポイントとして選択されます。

セーフ ポイントの詳細については、この記事を参照してください。JVM の Stop The World、Safe Point、Dark Underground World

GC が発生したとき、すべてのスレッドを最も近いセーフ ポイントまで実行してから一時停止する方法は?

GC が発生すると、スレッドは直接中断されませんが、各スレッドがセーフ ポイントまで実行されると、割り込みフラグがアクティブにポーリングされ、割り込みフラグが true の場合は中断されます。 。

ここでは問題は無視されます。GC が発生すると、実行中のスレッドはセーフ ポイントまで実行されてハングする可能性があります。ただし、スリープまたはブロック状態にあるスレッドは、現時点では JVM の割り込み要求に応答できず、セーフ ポイントに進むことができません。ハングはいつでも発生します。この状況では、安全領域を使用して問題を解決できます。

安全な領域とは、コード内でオブジェクトの参照関係がこの領域内のどこででも安全に開始できることを意味します。

1. スレッドが安全領域コードまで実行されると、この期間中に GC が発生すると、JVM は安全領域状態としてマークされたスレッドを無視します。スレッドが安全領域から出ようとしている場合、JVM が GC を完了したかどうかを確認し、完了している場合は実行を継続します。そうでない場合、スレッドは安全に安全領域から出ることができるという信号を受信するまで待機する必要があります。


ガベージ コレクター

Java 仮想マシンの仕様では、ガベージ コレクターの実装方法は規定されていません。ユーザーは、システムの特性に応じて各領域で使用されるコレクターを組み合わせることができます。

Java GC について (2)

上の写真は、異なる世代の 7 つのコレクターを示しています。2 つのコレクターの間につながりがある場合は、組み合わせて使用​​できることを意味します。

1. シリアルコレクター (シリアル GC)

シリアルは、単一のスレッドを使用し、コピーアルゴリズムに基づいて新しい世代で動作するコレクターです。シングル CPU 環境の場合、Serial はスレッド対話オーバーヘッドがないため、ガベージ コレクションを非常に効率的に実行できます。これは、クライアント モードの新世代のデフォルト コレクターです。

2. ParNew コレクター (並列 GC)

ParNew は実際にはシリアルのマルチスレッド バージョンで、ガベージ コレクションに複数のスレッドを使用することを除いて、残りの動作はシリアルと同じです。

3. Parallel Scavenge コレクター (並列リサイクル GC)

Parallel Scavenge は、制御可能なスループットを実現することに焦点を当てた、新世代で動作するコレクターです。 「スループット優先」のコレクターとして。

スループット = ユーザー コードの実行時間 / (ユーザー コードの実行時間 + ガベージ コレクション時間)

Parallel Scavenge は、スループットを正確に制御するための 2 つのパラメーターを提供します:

1、-XX: MaxGCPauseMillis は、ガベージ コレクションの最大一時停止時間を設定します

2、-XX: GCTimeRatio はスループット サイズを設定します

4、Serial Old コレクター (シリアル GC)

Serial Old は、シングルスレッドのマークソート アルゴリズムを使用し、古い世代で動作するコレクターです。これがデフォルトです。クライアントモードの古い世代のコレクター。

5. Parallel Old Collector (Parallel GC)

Parallel Old は、マルチスレッドのマーク照合アルゴリズムを使用し、古い世代で動作するコレクターです。スループットが重要であり、CPU リソースが重要である状況では、Parallel Scavenge と Parallel Old のコレクターの組み合わせを優先できます。

6. CMS コレクター (同時 GC)

CMS (同時マーク スイープ) は、古い世代で動作し、「マーク スイープ」に基づいて実装されています。アルゴリズム全体は次の 4 つのステップに分かれています:

1、初期マーキング: このプロセスは GC ルートが直接関連付けることができる次のオブジェクトのみをマークしますが、依然として Stop The World を実行します。同時マーキング
: GC ルート トレースの実行 このプロセスはユーザー スレッドで動作できます。
3. 再マーキング
: 同時マーキング中にユーザープログラムが実行を継続するために変更されたレコードの部分を修正するために使用されますが、一時停止時間は同時マーキングよりもはるかに短くなります。時間;
4. 同時クリーンアップ
: ユーザー スレッドを操作できます。
CMS コレクターの欠点:
1. 同時フェーズでは、ユーザー スレッドが一時停止することはありませんが、スレッド リソースの一部を占有し、システムの合計スループットが低下します。 。

2. フローティング ガベージは処理できません。同時クリーンアップ フェーズでは、ユーザー スレッドの実行によって新しいガベージ オブジェクトが生成されます。この部分は次の GC でのみ収集されます。

3. CMS はマーク アンド スイープ アルゴリズムに基づいて実装されているため、収集完了後に大量のメモリ フラグメントが発生し、古い世代では大量の領域が残る可能性がありますが、現在のオブジェクトを割り当てるのに十分な大きさの連続スペースが見つからないため、事前にフル GC をトリガーする必要があります。

JDK1.5 の実装では、古い世代のスペース使用量が 68% に達すると、CMS コレクターがトリガーされます。アプリケーション内の古い世代があまり速く増加しない場合は、-XX:CMSInitiatingOccupancyFraction を使用してトリガーの割合を増やすことができます。パラメータを使用してメモリのリサイクル回数を削減すると、システムのパフォーマンスが向上します。

JDK1.6 実装では、CMS コレクターをトリガーするためのしきい値が 92% に増加しました。CMS の動作中に予約されたメモリがユーザー スレッドのニーズを満たせない場合、「同時モード障害」エラーが発生します。仮想マシンがシリアルを開始すると、Old コレクターは古い世代からガベージを収集します。当然、アプリケーションの一時停止時間が長くなるため、「同時モードの失敗」が発生する場合は、このしきい値をあまり高く設定できません。パフォーマンスを低下させるための設定方法については、このしきい値は古い世代の領域の使用量を長期間にわたって監視する必要があります。


7. G1 コレクター

G1 (Garbage First) は、新世代と旧世代で動作する JDK1.7 によって提供されるコレクターであり、「マーク照合」アルゴリズムに基づいて実装されており、後のメモリを回避できます。デブリの問題は完了しました。
G1 の利点:

1. 並列処理と同時実行性: 複数の CPU を最大限に活用して、Stop The World の一時停止時間を短縮します。

2. 世代別コレクション: 他のコレクションの連携なしで Java ヒープ全体を管理できます。さまざまな方法を使用して、新しく作成されたオブジェクト、一定期間存続したオブジェクト、複数の GC を経験したオブジェクトを処理して、より良い収集結果を取得します。

3. 空間統合: CMS の「マーククリア」アルゴリズムとは異なり、G1 は動作中にメモリ空間の断片化を生成しないため、アプリケーションの長期運用に役立ちます。大きなオブジェクトを割り当てるときに、アプリケーションを適用できなくなることはありません。十分な大きさのオブジェクト。連続メモリにより事前にフル GC がトリガーされます。

4. 一時停止時間モデルを G1 で確立できるため、ユーザーは M ミリ秒の時間セグメント内での時間を明確に指定できます。ガベージ コレクションは N ミリ秒を超えてはなりません。

G1 コレクターを使用する場合、Java ヒープのメモリ レイアウトは他のコレクターとは大きく異なり、新しい世代と古い世代は物理的に分離されなくなり、同じサイズの複数の独立した領域に分割されます。これらはすべて、リージョンの一部のコレクションです (連続している必要はありません)。 G1 は、各リージョンのガベージ コレクションのステータス (リサイクル スペースのサイズとリサイクル時間) を追跡し、優先リストを維持し、許可された収集時間に基づいて最大の値を持つリージョンを優先して、全体のリージョン全体のガベージ コレクションを回避します。 Java ヒープ。G1 コレクターが限られた時間内でできるだけ多くのガベージを収集できるようにします。

しかし、ここで疑問が生じます。G1 コレクターを使用すると、オブジェクトはリージョンに割り当てられ、Java ヒープ上の任意のオブジェクトと参照関係を持つことができます。では、オブジェクトが生きているかどうか、またスキャンする必要があるかどうかをどのように判断するかということです。 Java ヒープ全体?実際、この問題は以前のコレクターにも存在していました。新しい世代でオブジェクトをリサイクルするときに同時に古い世代をスキャンする必要がある場合、マイナー GC の効率が大幅に低下します。

この状況に対して、仮想マシンは解決策を提供します。G1 コレクターのリージョン間のオブジェクト参照関係と、他のコレクターの新しい世代と古い世代の間のオブジェクト参照関係は、記憶されたセット データ構造に保存され、フルヒープスキャンを避けてください。 G1 の各領域には、対応する記憶セットがあります。プログラムが参照タイプのデータを書き込んでいることを仮想マシンが検出すると、書き込みバリアを生成して書き込み操作を一時的に中断し、参照によって参照されるオブジェクトが存在するかどうかを確認します。そうでない場合、関連する参照情報は、CardTable を通じて、参照されたオブジェクトが属するリージョンの Remenbered Set に記録されます。

Java GC のあれこれ (1)

Java GC のあれこれ (2)

上記は Java GC のあれこれ (2) の内容です。さらに関連する内容については、PHP 中国語 Web サイトを参照してください。 (www.php.cn)!

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。