ガベージコレクション
世代別リサイクル理論
現在商用の仮想マシン ガベージ コレクターのほとんどは、「世代別コレクション」の理論に従って設計されており、この理論は一般に次のように説明されます。
1. ほとんどのオブジェクトは生と死です。
2. 複数のガベージ コレクションを経て生き残ったオブジェクトは、リサイクルがより困難になります。
上記の 2 つの理論によれば、すぐに死んでしまう物体はある領域に配置され、リサイクルが難しい物体は別の領域に配置され、これが新世代と旧世代を構成します。
GC分類
1. ヤング GC (マイナー GC/ヤング GC): 新しい世代のみのリカバリを指します。
2. 古い世代のコレクション (Major GC/Old GC): 古い世代のみのコレクションを指します。現在、CMS ガベージ コレクターのみがこの個別の古い世代の動作を備えています。
(メジャー GC の定義は非常に混乱しています。古い世代を指すという人もいますし、ヒープ全体のコレクションであるという人もいます。これは他の人のシナリオに従って決定する必要があり、明確な定義はありません。)
3. フルヒープのリサイクル (フル GC): Java ヒープ全体とメソッド領域を収集します (メソッド領域が含まれることに注意してください)
ガベージコレクションアルゴリズム
コピーアルゴリズム(コピー)
使用可能なメモリを容量に応じて同じサイズの 2 つの部分に分割し、一度に 1 つだけを使用します。このブロックのメモリがなくなったら、残ったオブジェクトを別のブロックにコピーし、使用済みのメモリ空間を一度にクリーンアップします。このようにして、メモリは毎回半分の領域全体で再利用され、メモリが順番に割り当てられる限り、メモリを割り当てるときにメモリの断片化などの複雑な状況を考慮する必要がなく、実装が簡単で効率的です。動作します。ただ、このアルゴリズムのコストはメモリを元のサイズの半分に減らすことです。
ただし注意してください。メモリの移動は実際の移動 (コピー) であるため、対応する参照 (ダイレクト ポインタ) を調整する必要があります。
コピー回復アルゴリズムは新世代に適しています。ほとんどのオブジェクトは生まれて消滅するため、過去にコピーされたオブジェクトは比較的小さく、効率は自然に高く、1 回のクリーニングの残りの半分はとても早い。
リサイクルの魅力
コピーリカバリのためのより最適化された世代戦略: 具体的な方法は、より大きな Eden 領域と 2 つの小さな Survivor スペースを割り当てることです (From または To、または Survivor1 と Survivor2 と呼ぶことができます)。
特別な研究によると、新世代のオブジェクトの 98% は「生きて死ぬ」ため、メモリ空間を 1:1 の比率に従って分割する必要はなく、メモリを 1 つの大きなエデン空間と 2 つの大きなエデン空間に分割する必要があります。 Survivor スペースが小さいため、毎回 Eden と Survivor[1] の 1 つを使用します。リサイクルする場合は、Eden と Survivor に残っているオブジェクトを別の Survivor スペースに一度にコピーし、最後に、使用したばかりの Eden と Survivor スペースをクリーンアップします。
HotSpot 仮想マシンの Eden と Survivor のデフォルトの比率は 8:1 です。つまり、各新しい世代で利用可能なメモリ領域は、新しい世代の容量全体の 90% (80%+10%) であり、メモリは「無駄」になります。」もちろん、一般的なシナリオでは、リサイクル可能なオブジェクトの 98% は単なるデータです。各リサイクルで生き残るオブジェクトが 10% 以下であることを保証する方法はありません。Survivor スペースが十分でない場合は、他のスペースに依存する必要があります。割り当て保証(ハンドルプロモーション)を実行するメモリ(ここでは旧世代を指します)
マーククリアアルゴリズム (マークスイープ)
このアルゴリズムは「マーキング」と「クリア」の 2 段階に分かれています。最初にすべてのオブジェクトをスキャンしてリサイクルする必要があるオブジェクトをマークし、マーキングが完了した後、マークされたすべてのオブジェクトをスキャンしてリサイクルするため、2 回スキャンする必要があります。
回復効率は若干低くなりますが、ほとんどのオブジェクトが生きている場合と死んでいると、マークされたオブジェクトや再利用されたオブジェクトが大量に必要となるため、回復効率が低下し、コピーによる回復効率よりも低くなります。
その主な問題は、マークがクリアされた後に多数の不連続なメモリ フラグメントが生成されることです。スペースのフラグメンテーションが多すぎると、プログラムが将来大きなオブジェクトを割り当てる必要があるときに、十分な連続メモリを見つけることができず、メモリをトリガーしなければならない可能性があります。ガベージ コレクション アクション。
リサイクルする際、より多くのオブジェクトをリサイクルする必要がある場合、より多くのマーキングとクリア作業を実行する必要があるため、マーク クリア アルゴリズムは旧世代に適しています。
マーク照合アルゴリズム (Mark-Compact)
まず、リサイクルする必要があるすべてのオブジェクトにマークを付けます。マーク付けが完了したら、次のステップでは、リサイクル可能なオブジェクトを直接クリーンアップするのではなく、残っているすべてのオブジェクトを一方の端に移動し、端の外側のメモリを直接クリーンアップします。境界。マークソートアルゴリズムにはメモリの断片化はありませんが、効率は低くなります。
マークソートアルゴリズムとマークスイープアルゴリズムの主な違いは、オブジェクトの動きであることがわかります。オブジェクトの移動はシステムの負荷を増大させるだけでなく、プロセス全体にわたってユーザー スレッドを一時停止する必要があり、オブジェクトへのすべての参照を更新する必要があります (ダイレクト ポインターを調整する必要があります)。
したがって、旧世代で使用されていたマークソートアルゴリズムとマーククリアアルゴリズムには、それぞれ長所と短所があることがわかります。
JVM の一般的なガベージ コレクター
新しい世代では、ガベージコレクションが実行されるたびに多数のオブジェクトが消滅し、少数のオブジェクトだけが生き残ることが判明したため、レプリケーションアルゴリズムが使用され、コピーのコストを支払うだけでリサイクルを完了できます生き残った少数のオブジェクト。
旧世代では、オブジェクトの生存率が高く、追加で割り当てるスペースがないため、リサイクルには「mark-clean」または「mark-organize」アルゴリズムを使用する必要があります。
シリアル/古いシリアル
誕生したとき、この種類の JVM しか存在せず、最も古く、シングルスレッドで、排他的で、成熟し、単一 CPU に適しており、通常はクライアント モードで使用されます。
この種のガベージ コレクタは、数十メガバイトから 100 メガバイトまたは 200 メガバイトのヒープ領域のガベージ コレクションにのみ適しています (一時停止時間は 100ms 程度に制御できます) が、このサイズを超えるメモリの回復速度は非常に遅いため、とりあえずこのゴミ リサイクル業者はすでに味気ないものです。
ストップ・ザ・ワールド(STW)
単一のスレッドがガベージ コレクションを実行する場合、リサイクルが完了するまですべてのワーカー スレッドを一時停止する必要があります。この一時停止は「Stop The World」と呼ばれますが、この STW はユーザー エクスペリエンスを低下させます。たとえば、アプリケーションは実行する 1 時間ごとに 5 分間一時停止する必要があります。これは、初期の JVM と Java が C/C++ 言語からパフォーマンスが悪いと批判された重要な理由でもあります。そのため、JVM 開発チームは STW 時間を排除または短縮するために懸命に取り組んできました。
パラレル スカベンジ(ParallerGC)/パラレル オールド
JDK1.3からリサイクル効率を高めるため、JVMではガベージコレクタのスループットを重視したマルチスレッドのガベージコレクション機構が採用されており、高いスループットによりCPU時間を効率的に使用し、プログラムの計算タスクを即座に完了させることができます。主に、あまり対話せずにバックグラウンドで動作するタスクに適しています。
いわゆるスループットは、CPU が消費した合計時間に対するユーザー コードの実行に CPU が費やした時間の比率です。つまり、スループット = ユーザー コードの実行時間/(ユーザー コードの実行時間 + ガベージ コレクション時間) 、仮想マシンは合計 100 分間実行されており、そのうちガベージの収集には 1 分かかるため、スループットは 99% です。
ガベージ コレクターは、数百メガバイトから数ギガバイトのヒープ領域を再利用するのに適しています。
パーニュー
マルチスレッド ガベージ コレクターは CMS と連携します。CMS の場合 (CMS は旧世代のみを収集します)、新世代のガベージ コレクターは Serial と ParNew のみを選択できます。基本的にシリアルとの違いはありませんが、唯一の違いは、マルチスレッド、マルチ CPU、シリアルよりも一時停止時間が短いことです。(JDK9以降、ParNewはCMSに統合されました)
コンカレントマークスイープ(CMS)
リサイクルプロセス
コレクターは、収集の一時停止時間を最短にすることを目標とするコレクターです。現在、Java アプリケーションの大部分はインターネット Web サイトや B/S システムのサーバー側に集中しており、このようなアプリケーションではサービスの応答速度に特に注意が払われており、システムの停止時間を最短にすることが期待されています。ユーザーにより良いエクスペリエンスをもたらします。CMS コレクターは、この種のアプリケーションのニーズに非常に適しています。
名前 (「マーク スイープ」を含む) からわかるように、CMS コレクターは「マーククリア」アルゴリズムに基づいて実装されており、その操作は以前のコレクターよりも複雑です。
プロセス全体は次の 4 つのステップに分かれています。
初始标记
短時間であれば、GC ルートが直接関係できるオブジェクトをマークするだけで、速度は非常に速くなります。
并发标记
ユーザーのアプリケーション プログラムと同時に、GC ルート追跡のプロセスが実行され、GC ルートに関連付けられたすべてのオブジェクトが、到達可能な分析パス全体を横断するようにマークされます。この時間は比較的長いため、同時処理が使用されます (ガベージ コレクター スレッドとユーザー スレッドが同時に動作します)。
重新标记
つまり、同時マーク中にユーザープログラムの継続的な動作によってマークが変化したオブジェクトの部分のマークレコードを修正するために、この段階の一時停止時間は通常、最初のマーク段階よりわずかに長くなりますが、同時マークより短い。
并发清除
プロセス全体で最も長い同時マーキングおよび同時クリア処理のコレクター スレッドはユーザー スレッドと連携できるため、一般に、CMS コレクターのメモリ回復プロセスはユーザー スレッドと同時に実行されます。
CMリサイクラーの問題
CPU敏感:
CMS はプロセッサ リソースの影響を受けやすいため、同時収集が使用されます。処理コアの数が 4 未満の場合、CMS はユーザーに大きな影響を与えます。
浮动垃圾:
CMS の同時クリーニング フェーズ中もユーザー スレッドが実行されているため、プログラムの実行中に新しいガベージが自然に生成され続けます。この部分のガベージはマーキング プロセスの後に表示され、CMS は現在のコレクションでそれを破棄できません。次回のために保存する必要があるため、GC 中にクリーンアップしてください。このゴミの部分を「浮遊ゴミ」といいます。
フローティング ガベージが存在するため、メモリの一部を予約する必要があります。これは、CMS コレクションが他のコレクタのようにリサイクルする前に、古い世代がいっぱいになるのを待つことができないことを意味します。
会产生空间碎片:
マークアンドスイープ アルゴリズムでは、不連続なスペース フラグメントが発生します。
断片化は 2 つの問題を引き起こします。
効率の問題
1、空间分配效率较低:
連続した空間であれば、ポインタ衝突を利用してJVMを割り当てることができますが、このような多数のフラグメントを含むフリーリストの場合、フリーリスト内の項目に1つずつアクセスして、割り当て可能なアドレスを見つける必要があります。新しいオブジェクトを保存します。
2、空间利用效率变低:
新世代で昇格するオブジェクトのサイズは連続領域のサイズより大きく、Old領域全体の容量が十分であっても、不連続であるため新しいオブジェクトを格納することができません。メモリの断片化が原因でプロモーションに失敗しました。Young GC は Old に十分な領域があると考えます。その結果、プロモートされたラージ オブジェクトが割り当てられるときに、それを格納するための連続した領域を見つけることができません。
ガベージ コレクターの劣化
これが発生すると、プロモーションが失敗し、CMS が縮退します。また、シングルスレッドのシリアル GC モードでは通常、シリアル オールドが使用されます。シリアル オールドはシングルスレッドであるため、メモリ空間が大きく、オブジェクトが多い場合、この状況は発生します。 CMS の遅延で発生します。
Serial はマークソートアルゴリズムとシングルスレッドの完全一時停止方式を使用してヒープ全体のガベージを収集し、一時停止時間は CMS よりも長くなります。