この記事では主に次の問題に焦点を当てます:: Java プログラムの実行後、ヒープ内のオブジェクトはいつリサイクルされるか?リサイクルするにはどうすればいいですか?
ヒープは「GC ヒープ」とも呼ばれます。現在、コレクターは基本的に世代別コレクション アルゴリズムを使用しているため、Java ヒープは新世代と旧世代に細分することもできます。その割合は1:2、詳しく言うと新世代はエデンエリアとサバイバーエリアに分かれており、その割合は8:1となっています。次の図は、ヒープの構造を示しています。
##ヒープ内のオブジェクトに対するメモリの割り当ては厳密に行われます。
新世代の GC はマイナー GC を指し、新世代のガベージ コレクションは頻繁かつ高速です。古い世代の GC (メジャー GC/フル GC) は古い世代でガベージ コレクションを実行し、通常は少なくとも 1 つのマイナー GC を伴います。遅い。フル GC は次の状況でトリガーされます:
古い世代のスペースが不十分; メソッド領域のスペースが不十分;
- #System.gc() を呼び出し、JVM が完全な gc を実行することをお勧めします;
- Long-存続期間中のオブジェクトは古い世代に転送されます。スペースが不足しています;
#大きなオブジェクトに割り当てられる連続したスペースが十分にありません;-
# 新しい世代のガベージ コレクションで生き残るオブジェクトが多すぎるため、S1 がそれらを収容できません。古い世代の保証された領域が不足しています。保証された領域とは、利用可能な最大のスペースがあるかどうかを指します。古い世代の連続スペースは、新しい世代のすべてのオブジェクトの合計スペースよりも大きくなります。
-
ほとんどすべてのオブジェクトはヒープに配置されます。では、これらのオブジェクトがまだ使用できるかどうかをどのように確認すればよいでしょうか? JVM は、次の 2 つの決定方法を提供します。
- ##参照カウント方法
: オブジェクトは、参照カウンタ。参照されるたびにカウンタ値が 1 増加し、参照が無効になるとカウンタ値が 1 減少します。参照回数が 0 の場合、オブジェクトは生きていないことを意味します。参照カウント法では循環参照問題は解決できませんが、周志鵬先生の本に詳細な例が載っており、比較的理解しやすいです。
#到達性分析手法 :ツリーのルートノードと同様に、「GC Roots」オブジェクトを起点として下方向に探索します。その探索でたどる経路を参照チェーンと呼びます。オブジェクトから開始点までの参照チェーンが存在しない場合は、 GC ルート、次にこれ オブジェクトは到達できないため、リサイクルする必要があります。 GC ルートは、仮想マシン スタックによって参照されるオブジェクト、ローカル メソッド スタックによって参照されるオブジェクト、メソッド領域の静的プロパティによって参照されるオブジェクト、およびメソッド領域の定数によって参照されるオブジェクトを指します。
参照については上で説明しました。オブジェクトの存続は参照に関係します。参照の種類は、強参照、ソフト参照、弱参照、仮想参照に分類されます。
強力な参照、新しいオブジェクト、ガベージ コレクターはそれをリサイクルしません;
-
ソフト参照。システム内で OMM が発生する前に、これらのオブジェクトのメモリがリサイクルされます。
弱い参照。ガベージ コレクターがそれを見つけるとすぐに再利用されます。動作している場合、すぐにリサイクルされます ;
仮想参照は役に立たず、いつでもリサイクルされる可能性があります。
実際には、到達可能性分析メソッドによって決定された到達不可能なオブジェクトはすぐにはリサイクルされません。オブジェクトはその前に 2 回マークされる必要があります。実際にはリサイクルされます。最初のマーキングでは、オブジェクトが到達不能であると判断され、次にフィルターが実行されます。フィルター条件は、このオブジェクト # の Finalize() メソッド # を実行する必要があるかどうかです。 ####。 Finalize() メソッドがオーバーライドされていない場合、または Finalize() メソッドが仮想マシンによって呼び出された場合、finalize() メソッドはシステムによって 1 回だけ呼び出されます。どちらの場合も「実行する必要はありません」。必要に応じて、このオブジェクトは、仮想マシンによって自動的に作成される低優先度 キューである F-Quene キューに配置されます。 Finalizerスレッドは、finalize() メソッドを実行します。この期間中、GC は 2 番目の小規模なスケールで F-Quene 内のオブジェクトをマークします。オブジェクトがまだ参照されていない場合は、リサイクルされます。フィルタリングされないオブジェクトは必ずしもリサイクルされるわけではありません。 #オブジェクトが何であるかはすでにわかっています時間はリサイクルされていますが、どのようにリサイクルすればよいでしょうか?最も一般的に使用される 4 つのガベージ コレクション アルゴリズムを紹介します。
マーククリア: 最初にクリアする必要があるオブジェクトにマークを付け、次にそれらを均一に収集します --- - 効率的ではありません、大量の不連続フラグメントが生成されます;
コピー アルゴリズム: メモリをブロックに分割し、一度に 1 つのブロックのみを使用してコピーします使用後に残ったオブジェクトを別のオブジェクトに移動します。1 つのピースで;
マーク付けと並べ替え: 最初に残ったオブジェクトにマークを付け、次に残ったすべてのオブジェクトを一方の端に移動します。終了境界の外側のメモリを直接クリーンアップします;
世代アルゴリズムでは、ヒープは新しい世代と古い世代に分割されます。新しい世代が収集されるたびに消滅するため、コピー アルゴリズムを選択します。旧世代の生存率は比較的高く、割り当て保証のための余分なスペースがないため、マーク クリアまたはマーク ソート アルゴリズムを選択します。
ガベージ コレクション アルゴリズムはメモリのリサイクルのアイデアであり、具体的な実装はガベージ コレクターです。一般的に使用されるガベージ コレクターの簡単な紹介:
シリアル シリアル コレクター。単一スレッドの場合、ガベージ コレクション中は他の作業を一時停止する必要があります。新入生にはコピー、老人にはラベリング。シンプルで効率的;
ParNew コレクター。シリアルのマルチスレッド バージョン、
Parallel Scavenge コレクター、レプリケーション アルゴリズムのマルチスレッド コレクター。スループット、CPU 実行コード時間 / 合計 CPU 消費時間に注意してください。新世代のコピー、旧マークのソート;
シリアル古いコレクター、旧世代のバージョン;
Parallel Old コレクター、Parallel Scavenge 旧世代バージョン;
CMS コレクター、最短の一時停止に焦点を当てています。並行コレクタを使用すると、ガベージ コレクション スレッドは (基本的に) ユーザー スレッドと同時に動作します。マーク アンド スイープ アルゴリズム
ガベージ コレクターの詳細については、Zhou Zhipeng 氏の本をご覧ください。
推奨チュートリアル: 「
JS チュートリアル
」
以上がヒープとガベージ コレクション メカニズムの簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。