目次
1 ガベージコレクションアルゴリズム
ガベージ コレクション アルゴリズムには次の 4 つがあります。
- マークアンドスイープアルゴリズム
- レプリケーションアルゴリズム
- タグソートアルゴリズム
- 世代別リサイクルアルゴリズム
1.1 マークとクリアのアルゴリズム
- マーキング: メモリ領域を走査し、リサイクルする必要があるオブジェクトにマークを付けます。
- クリア: メモリを再度たどり、マークされたメモリをリサイクルします。
注:蓝色的为存活对象
欠点:
- 効率の問題: メモリ空間が 2 回横断されます (1 回目はマークされ、2 回目はクリアされます)。
- スペースの問題: 大量のメモリ フラグメントが生成されやすく、より大きなメモリが必要な場合、要件を満たすメモリが見つからないため、GC を再度開始する必要があります。
1.2 レプリケーションアルゴリズム
メモリを 2 つの同じサイズのチャンクに分割し、一度に 1 つのチャンクのみを使用します。ブロックが使い果たされたり、一定時間が経過したりしてGCが発動すると、ブロック内に残ったオブジェクトが別の領域にコピーされ、無駄なメモリが一気にクリアされます。次回 GC がトリガーされると、そのブロックの残っている部分がこのブロックにコピーされ、その後そのブロックが消去され、このサイクルが繰り返されます。
アドバンテージ:
- マークスイープ アルゴリズムと比較して、メモリの断片化の問題が解決されます。
- より効率的です (メモリをクリーンアップするときに、最初と最後のアドレスを覚えて、それらを一度に消去します)。
欠点:
メモリ使用率は高くなく、一度に半分のメモリしか使用できないため、スペースの無駄になります。
1.3 マーキングソートアルゴリズム
なぜなら、以前のコピーアルゴリズムにおけるオブジェクトの生存率が比較的高い場合、何度もコピーし続けることは無意味であり、時間の無駄だからである。そこで、高齢者向けに「マーキングソート」アルゴリズムが提案された。
- マーク: リサイクルする必要があるものにマークを付けます
- 整理: 残っているオブジェクトをメモリの片端に移動し、不要なメモリを直接クリーンアップします。
下の図に示すように、並べ替えた後、オブジェクトが集められて連続したスペースが解放されていることがわかります。
利点: 断片化がない
短所: 毎回マークを進めるのは効率が悪い。
1.4 世代別リサイクルアルゴリズム
世代別リサイクル アルゴリズムの本質は、上記のアルゴリズムを組み合わせた最適化であり、現在、ほとんどの商用仮想マシンがこの世代別リサイクル アルゴリズムを使用しています。実際、ほとんどのオブジェクトのライフ サイクルは非常に短いため、GC が発生すると、リサイクルする必要があるオブジェクトが多数あり、生き残るオブジェクトはほとんどありません。したがって、別のメモリに移動する必要があるオブジェクトはほとんどありません。メモリ空間を 1:1 に分割する必要はありません。代わりに、スペース全体を新生代
(1/3) と老年代
(2/3) に分割します。新世代は 8:1:1 の比率で 3 つのブロックに分割されており、最大のブロックをSurvivor Area 、小さい 2 つのブロックをSurvivor Area または Survival AreaEden(伊甸园)区
と呼びます。To Survivor
From Survivor
最初の GC では、Eden の生き残ったオブジェクトのみを にコピーする必要がありますTo Survivor
。その後、エデン地域全体がリサイクルされます。再度 GC を実行すると、残っている Eden と To が にコピーされForm Survivor
、処理が繰り返されます。このようにして、各新しい世代で使用可能なメモリは新しい世代全体の 90% を占め、メモリ使用率が大幅に向上します。
ただし、毎回生き残るオブジェクトが常に新しい世代全体の 10% 未満であるという保証はありません。コピーされたオブジェクトが保存できない可能性があるため、古い世代が最終的な保証を提供します。十分に、OOM がスローされます。
ヒープ領域の構造と詳細なリサイクルプロセスは次のとおりです。
-
ヒープ領域は新世代 (1/3) と旧世代 (2/3) に分割され、新世代は eden (8/10)、survivor1 (1/10)、survivor2 (1/10) に分割されます。 )。
-
オブジェクトはedenに作成されますが、配置できない場合はマイナーgcが発生します。(マイナー gc の間、stop the world がトリガーされ、他のユーザー スレッドが一時停止され、ガベージ コレクション スレッドのみが動作します)。
-
オブジェクトがminorGCを通過した後に生き残ったオブジェクトは生存領域に配置され、その年齢は+1されます。再度minorGCを実行すると、別のsurvivor領域に移動されます。コピー時に保存できなかった場合は古い世代になります。
-
生存エリア内のオブジェクトの年齢が 15 に達すると、老年期に入ります。
-
古いメモリがいっぱいの場合。最初にマイナー GC をトリガーしてから、フル GC をトリガーしようとします。フル GC の実行中は、STW に時間がかかります (古い世代の方が多く残っているため)。
-
古い世代がいっぱいで、リサイクル可能なゴミがない場合は、OutOfmemory が報告されます。
スレッドのメモリがオーバーフローして例外がスローされる(メモリ不足)場合、他のスレッドは実行を終了できなくなります。
これは、スレッドが OOM 例外をスローすると、そのスレッドが占有しているすべてのメモリ リソースが解放され、他のスレッドの動作には影響せず、プロセスは引き続き正常に行われるためです。
jdk に付属のモニターを開いてメモリ割り当てを表示できます。cmd ウィンドウで jvisualvm を実行します。
フローチャートは次のとおりです。
注: 生存エリア内の 15 年以上経過したオブジェクトだけが老年期に入るわけではなく、他にも多くの複雑な状況が存在します。
1.4.1 オブジェクトが旧世代に移行する条件
-
より大きなオブジェクトに遭遇すると、新しい世代のエデンが空でオブジェクトを収容できない場合でも、古い世代に直接入ります。大きなオブジェクトのサイズはパラメータを通じて設定でき、オブジェクトのサイズが考慮されます。大きな物体になること。
-XX:PretenureSizeThreshold
-
オブジェクトの年齢が 15 歳に達すると、老年期に入ります。この年齢は次のパラメータで設定できます。
-XX:MaxTenuringThreshold
-
オブジェクトの動的な経過時間に基づいて判断し、s 領域内のオブジェクトの総数が s 領域の 50% を超える場合、次回コピーするときに、その経過時間が最大経過時間以上であるすべてのオブジェクトがコピーされます。すぐに入れてください。老後まで。
-
古い世代のスペース割り当て保証メカニズム: マイナー gc 中に、古い世代の残りの利用可能なスペースが新しい世代のすべての既存のオブジェクト (ガベージを含む) よりも大きいかどうかを確認します。以上の場合は、マイナー gc を実行します。それより小さい場合は、保証パラメータ設定が設定されているかどうかを確認します。
-XX: -HandlePromotionFailure
保証が設定されている場合は、古い時代の残りのスペースが、履歴内の各マイナー gc 後に古い時代に入るオブジェクトの平均サイズより小さいかどうかを判断します。その場合は、フル gc を直接実行し、マイナー gc を 1 つ減らします。そうでない場合は、minor gc を実行します。保証メカニズムがない場合は、フル gc だけを使用します。説明: 端的に言えば、旧世代の残りの領域に次の新世代のオブジェクトをまだ収容できるかどうかを判断し、旧世代に格納する必要があります。