導入プログラムを実行するには、必然的にメモリ リソースの適用が必要になります。メモリ リソースが使用後に時間内に解放されない場合、メモリ内のゴミがどんどん増え、最終的にはメモリ オーバーフローが発生します。ガベージコレクションは、プログラムがメモリを繰り返し使用できるように、不要なメモリのガベージをクリーンアップすることです。 ガベージ コレクション (GC) は、Java システムの最も重要なコンポーネントの 1 つです。 C/C++ の手動メモリ管理方法とは異なり、JVM 仮想マシンは完全に自動化されたメモリ管理ソリューションを提供して、メモリ管理に関連する開発者の作業を軽減します。 (I)一般的なガベージコレクションアルゴリズムとガベージコレクタ1. 一般的なガベージコレクションアルゴリズム a) マークスイープ 最も初期かつ最も基本的なガベージ コレクション アルゴリズムであり、アルゴリズムは「マーキング」と「クリア」の 2 つの段階に分かれています。まず、リサイクルが必要なすべてのオブジェクトにマークを付けます。マーキングが完了したら、マーキングされたすべてのオブジェクトが均一にリサイクルされます。このアルゴリズムはシンプルで高速ですが、明らかな欠点があります。まず、マーキングとクリアの両方のプロセスの効率が高くありません。第二に、クリア後に不連続なメモリフラグメントが大量に生成されます。メモリの断片化が多すぎると、プログラム実行中により大きなオブジェクトを割り当てる必要があるときに十分な連続メモリが見つからず、事前に別のガベージ コレクション アクションがトリガーされる可能性があります。図 1 はマーククリアアルゴリズムのプロセスを示しています。 図1 b) コピー マークスイープアルゴリズムの大きなオブジェクトの回復効率とメモリの断片化の問題を解決するため。別の「ハーフブロックコピー」アルゴリズムが提案されています。基本的な考え方は、元のメモリ空間を 2 つの部分に分割し、そのたびに半分の領域のみを使用することです。ガベージ コレクション中、使用済みのオブジェクトは未使用の半分の領域にコピーされ、現在使用中の半分の領域にあるすべてのオブジェクトがクリアされ、最後に 2 つのメモリ ロールが交換されてリサイクル作業が完了します。メモリの断片化の問題は解決されますが、アクティブなオブジェクトが多数ある場合、コピーされるオブジェクトが多すぎて、コピーのコストが非常に高くなり、メモリの半分しか使用できなくなります。したがって、単純なコピーアルゴリズムにも多くの問題があります。図 2 はレプリケーション アルゴリズムのプロセスを示しています。 図2 c) マークコンパクト マーク圧縮アルゴリズムのマーキング プロセスは、マーク スイープ アルゴリズムと同じですが、後続のステップでは、リサイクル可能なオブジェクトを直接クリーンアップするのではなく、残っているすべてのオブジェクトを空きメモリの一方の端に移動し、境界外のすべてのメモリを直接クリーンアップします。この方法は、メモリの断片化の発生を回避し、2 つの同一のメモリ空間を必要としません。マーク圧縮アルゴリズムの最終的な効果は、マークスイープの実行後にメモリのデフラグを実行することと同じです。図 3 はタグ圧縮アルゴリズムのプロセスを示しています。 図3 2. 世代を超えた収集 世代別コレクションは、現在仮想マシンで広く使用されているリサイクルのアイデアです。これまでに紹介したアルゴリズムの中には、他のアルゴリズムを完全に置き換えることができるアルゴリズムはありません。世代別コレクションはこのアイデアに基づいています。オブジェクトの特性に応じてメモリを複数のブロックに分割し、メモリの各ブロックの特性に応じて異なるリサイクル アルゴリズムを使用して、メモリのリサイクル効率を向上させます。主流の JVM 仮想マシンでは、JAVA ヒープ メモリは通常、Young Generation と Old Generation の 2 つの領域に分かれています。各ガベージ コレクション中に、多数のオブジェクトがリサイクルされ、生き残った少数のオブジェクトが徐々に古い世代に転送されて保存されます。図 4 は、主流の JVM 仮想マシンのメモリ世代を示しています。 図4 3. 一般的なガベージコレクター ガベージ コレクターについて説明する前に、ガベージ コレクターを継続的に最適化する必要がある理由について説明する必要があります。すべては「Stop The World」、略して STW という言葉から生まれています。 JVM 仮想マシンはガベージ コレクション作業を自動的に開始し、完了します。ユーザーは、介入なしでガベージ コレクションが完了するまで待機するために、すべての通常の作業スレッドを一時停止する必要があります。数時間ごとに数分間休憩しなければならないと想像してみてください。このような手続きは受け入れられません。 ガベージ コレクション アルゴリズムは、ガベージ コレクターの理論的基礎を提供し、ガベージ コレクターはこれらの理論的アルゴリズムの具体的な実装です。図 5 は 7 つの異なるガベージ コレクターを示しています。 2 つのコレクター間に接続がある場合は、それらを一緒に使用できることを意味します。 図5 a) シリアルコレクター(シリアル + シリアルオールド) 最も古いガベージ コレクターであり、最も基本的なものの 1 つは、若い世代で動作しているときはマーク コピー アルゴリズムを使用し、古い世代で動作しているときはマーク圧縮アルゴリズムを使用するシングル スレッド ガベージ コレクターです。 CPU パフォーマンスが制限されているにもかかわらず、そのパフォーマンスは依然として優れています。図 6 は、シリアル ガベージ コレクターの収集プロセスを示しています。 図6 b) 同時コレクター(ParNew および CMS) ParNew コレクターは、若い世代でのみ動作できる並列コレクターです。これは、シリアル コレクターのマルチスレッド バージョンです。ガベージ コレクションにマルチスレッドを使用するため、計算能力が強力な CPU で生成される一時停止時間は、シリアル コレクターよりも短くなります。図 7 は ParNew 並列リサイクル プロセスを示しています。 図7 CMS (Concurrent Mark Sweep) は、古い世代でのみ動作できるコレクターです。これは、比較的複雑な設計を持つ最初のコレクターであり、JVM 仮想マシンが短い一時停止を追求する最初の試みです。しかし、明らかな欠点もあります。図 8 は CMS コレクターの回復プロセスを示しています。一般的に、3 つのポイントがあります。まず、CMS コレクターは CPU パフォーマンスに敏感です。 CPU のパフォーマンスが不十分であったり、負荷自体が非常に高かったりすると、ガベージ コレクション プロセス全体が長くなります。次に、同時マーキングと同時クリアの段階で、ユーザー スレッドによって新しいガベージが生成され、「浮動ガベージ」が生成されます。したがって、他のコレクターとは異なり、古い世代が 100% になるまで待ってからリサイクルすることはできません。メモリの一部は、ユーザー スレッドが使用するために予約する必要があります。最後に、CMS はマークスイープ アルゴリズムに基づくコレクターであり、大量のメモリ断片化を生成します。処理する必要がある大きなオブジェクトがある場合、フラグメントが多すぎると、メモリを整理するために Old 領域に対して再度ガベージ コレクションを実行する必要があります。 ParNew と CMS ガベージ コレクターは通常一緒に使用されますが、これら 2 つのコレクターは JDK9 で非推奨とマークされており、JDK14 では正式に削除されます。 図8 c) 並列コレクション (ParallelGC+ParallelOldGC) ParallelGC と ParallelOldGC は、それぞれ若い世代と古い世代で使用される JDK8 の 2 つのデフォルト コレクターであり、どちらもマルチスレッド コレクターです。 ParallelGC はガベージ コレクションにコピー アルゴリズムを使用します。 ParNew とは異なり、システム スループットと最大一時停止時間を制御でき、セルフ チューニング機能が追加されており、ParNew のアップグレード版に相当します。 ParallelOldGC はマーク圧縮アルゴリズムを使用します。このコレクターは JDK6 以降で利用可能です。図 9 は、ParallelGC と ParallelOldGC のリサイクル プロセスを示しています。 図9 d) パーティションコレクター(ガベージファースト) ビッグデータ時代の到来により、JVM 仮想マシンのメモリはますます大きくなっています。同じ条件下では、メモリ空間が大きいほど、GC が完了するまでの時間が長くなり、一時停止も長くなります。 GC によって生成される STW 時間をより適切に制御するため。ガベージファーストコレクター(略してG1)が登場しました。実験バージョンは JDK6 で開始され、JDK7 Update4 で徐々に成熟しました。最終的に、JDK8 Update40 以降、G1 は並行クラス アンロード機能を提供し、CMS を置き換えることができるコレクターになりました。 JDK9 バージョンでは、G1 がデフォルトのガベージ コレクターとして設定されていました。 G1 コレクターは、パーティション (領域) の概念を導入し、メモリ空間全体をさまざまなサイズの小さなパーティションに分割します。それぞれの小さなパーティションは独立して使用され、リサイクルされます。しかし、G1 は依然として世代循環の理論に従っており、若い世代と古い世代の概念を区別しています。全体的な観点から見ると、G1 はマーク圧縮アルゴリズムに基づいて実装されていますが、ローカルの観点から見ると、各パーティションはマーク コピー アルゴリズムに基づいて実装されています。 図10 (II) ガベージコレクタのメモリ割り当ての詳細な説明1. 世代別ガベージコレクター 世代別ガベージコレクターはどのようにしてメモリを割り当て、管理するのでしょうか?世代の考え方を見直してみましょう。図 11 に示すように、JVM スペース全体は、Young Generation と Old Generation の 2 つの領域に分かれています。ヤングエリアは、エデンエリア(総称してエデン)とサバイバーエリアに分かれています。 Survivor エリアはさらに、From (Survivor0、総称して「S0」) エリアと To (Survivor1、総称して「S1」) エリアに分割されます。若い世代と古い世代の比率は 1:2 (デフォルト パラメータ) で、若い世代のメモリは 3 つの部分に分割されます (デフォルトは 8:1:1)。 G ラインでは、JDK6 を JDK8 に徐々に置き換え始めています。この部分では主に JDK8 バージョンについて説明します。 図11 ほぼすべての新しく生成されたオブジェクトは、まず若い世代に配置されます。ほとんどのオブジェクトはエデンエリアで生成されます。 Eden 領域のメモリ空間が不足すると、GC が開始されます。コレクターは、Eden 領域内の残存オブジェクトを S0 にコピーし、Eden 領域をクリアします。このプロセスを図 12 に示します。 図12 次回、エデン領域が不足したときは、エデン領域と S0 領域に残っているオブジェクトが S1 領域にコピーされ、その後エデン領域と S0 領域がクリアされます。このプロセスを図 13 に示します。 図13 このとき、別の疑問が生じます。オブジェクトはいつ古い世代に移行するのでしょうか? S0 と S1 の間でオブジェクトがコピーされるたびに、オブジェクトの経過年数は 1 年ずつ増加します。 15 年が経過すると (デフォルトは 15 年ですが、パラメータで調整できます)、オブジェクトは古い世代にコピーされます。このプロセスを図 14 に示します。 図14 このサイクルが繰り返され、古い世代のスペースも不足すると、コレクターは古い世代をリサイクルしてメモリ スペースを解放します。これは一般にフル GC と呼ばれます。 2. パーティション化されたガベージコレクター 従来の GC コレクターは、連続したメモリ空間を新しい世代、古い世代、永続的な世代に分割します (JDK 8 では永続的な世代が削除され、メタスペースが導入されました)。これは下の図 15 に示されていますが、今は忘れてください。 図15 G1のメモリ格納アドレスは不連続です。 G1 は、連続した Java ヒープを、等しいサイズの複数の独立した領域に分割します。各リージョンは、必要に応じて、新世代のエデン空間、サバイバー空間、または旧世代のオールド空間の役割を果たすことができます。各領域のサイズは 1MB から 32MB の範囲で、2 の累乗にする必要があります。さらに、巨大オブジェクト (H-obj) と呼ばれる新しい領域が追加されます。サイズがリージョンの容量の半分を超える場合は、大きなオブジェクトと判断され、大きなオブジェクト領域に直接配置できます。リージョン全体の容量を超える超大型オブジェクトは、N 個の連続する Humongous Region に保存されます。 G1 メモリの割り当てを以下の図 16 に示します。 図16 一般オブジェクトを割り当てる際に、すべての Eden 領域の使用量が最大しきい値に達し、メモリ不足が要求されると、若い世代の領域の GC がトリガーされます。各 GC はすべての Eden 領域と Survivor 領域を再利用し、生き残ったオブジェクトを空の Survivor 領域にコピーします。下の図17に示します。 5A974d6e659b30673a30fcdee4aa6e7.jpg" ターゲット="_blank">5A974d6e659b30673a30fcdee4aa6e7.jpg" 幅="自動" ボーダー="0" 高さ="自動" alt="" タイトル=""> 図17 では、メモリはいつ旧世代領域に入るのでしょうか? G1 コレクターでは、メモリが古い世代の領域に入る状況が 2 つあります。 世代リサイクルのルールによれば、若い世代領域でメモリがコピーされるたびに、その年齢は 1 年ずつ増加します。 15 年が経過すると (デフォルトは 15 年ですが、パラメータで調整できます)、オブジェクトは古い世代の領域にコピーされます。 動的年齢判定ルール: 若い世代の GC 後、Survivor 領域内の同じ年齢のオブジェクトが Survivor 領域の 50% に達していることが判明した場合、この年齢以上のオブジェクトは古い世代に直接移動されます。たとえば、Survivor 領域に年齢が 1、2、3、4 のオブジェクトがあり、年齢が 3 のオブジェクトが Survivor 領域の 50% 以上を占める場合、年齢が 3 以上のすべてのオブジェクトは古い世代の領域に移動されます。 最後に、パーティションリサイクルのユニークな混合 GC について説明します。 G1 では、古い世代のリージョンを個別にリサイクルすることはありません。代わりに、古い世代をリサイクルするときに、新しい世代と大きなオブジェクトも同時にリサイクルされます。したがって、この段階は混合リサイクルと呼ばれます。旧世代リージョンの使用率が 45% に達すると、混合リカバリがトリガーされます。 ただし、G1 には Full GC がまだ存在します。空き領域のサイズが残存オブジェクトのメモリ サイズに対応できない場合、システムはアプリケーションを一時停止し、Full GC を実行する必要があります。フル GC を実行すると、メモリのマーク、クリーンアップ、および整理に単一のスレッドが使用されます。このプロセスは非常に長いため、Full GC のトリガーは可能な限り回避する必要があります。 (III) ガベージコレクターの最適化のアイデアガベージコレクターの最適化のアイデア ガベージ コレクターの選択は、JVM の最適化にとって重要な構成です。適切なガベージ コレクターを選択すると、JVM のパフォーマンスが大幅に向上します。実際、JVM チューニングでは主に次の 2 つの指標を調整します。 JVM 仮想マシンの一時停止時間 (Stop The World) スループットとは、CPU がユーザー コードを実行するために使用する時間と CPU の総消費時間の比率を指します。つまり、スループット = ユーザー コード実行時間 / (ユーザー コード実行時間 + ガベージ コレクション時間) リサイクル選びの体験談をご紹介します。 1. メモリが少ない、デフォルトの優先度: ほとんどのアプリケーションの JVM ヒープ メモリは 4G 以内であり、JDK8 のデフォルトのガベージ コレクターが最初に使用されます。現在、ほとんどのシステムは仮想マシン上で実行されます。 G1 は確かにより高度なガベージ コレクターですが、ガベージ コレクション中に G1 によって生成されるメモリ使用量も高くなります。したがって、小さなコンテンツのコレクターとして G1 を使用すると、GC の数が増加し、スループットが低下します。 2. 大容量メモリ、G1 が推奨されます。 メモリが 8G を超える場合は、G1 ガベージ コレクターを優先する必要があります。これは、メモリが増加すると、ガベージ コレクション中にオブジェクトが s0 から s1 にコピーされるためです。メモリが大きいほどコピー時間が長くなり、システムの STW 時間が増加し、システムが長時間停止する原因になります。 要約するJava の継続的な開発により、RedHat と Oracle がそれぞれ開発した新世代の低レイテンシ コレクターである shenandoahGC や ZGC など、多くの新しいコレクターが登場しました。ただし、これらはまだ実験段階であり、実稼働環境ではまだ使用されていません。 Java は、さまざまな種類のアプリケーションに対してさまざまなガベージ コレクション戦略を提供します。 この記事では、Java 仮想マシンのガベージ コレクターとそのコレクション戦略を 1 つずつ紹介し、ガベージ コレクションの最適化の考え方について簡単に説明します。これにより、読者が Java 仮想マシンのガベージ コレクションに関する理解を深め、ガベージ コレクションの最適化について予備的な理解を深め、その後の作業で Java アプリケーションをチューニングするための基礎を築くことを期待しています。 |
<<: プライベート DLT かパブリック ブロックチェーンか?
>>: Sentry Monitoring - フルスタック開発者向けの分散トレース
メタバースは、一般的には現実世界と並行する仮想世界として理解できます。現実世界で人々ができることはす...
私が初めて SEO 業界に入ったとき、多くのことについてまだ無知でした。ウェブサイトの最適化能力を向...
アメリカの老舗ブランドであるSharktechが、特別価格でサーバーを販売しています。シカゴとデンバ...
[[436076]] Kubernetes を通じてアプリケーションをデプロイする前に、Kubern...
いわゆる愛占語数とは、Baiduランキングにおけるキーワードの検索結果を指しますが、愛占語数を増やす...
英国企業である Speedypage (登録番号 13269524) は現在、シンガポール VPS、...
収益性は、ウェブサイトが必ず通らなければならない道のようです。多くのウェブサイトは利益を上げる目的で...
私たちの周りでは日々多くのことが変化していますが、習慣は変わりません。ユーザーはQQスペースを利用し...
ライカクラウド(広東ライカ情報技術有限公司)は、IDC/ISP/CDNライセンスB1-2761を持つ...
序文: 4ヶ月25日前、広州網科は正式にインターネットに定着し、ドメイン名を登録しましたが、今日7月...
サイトトラフィックがサイト運営の基盤であるならば、トラフィックのコンバージョン率は利益の基盤となりま...
ビジネスアプリケーションを作成するプログラマーの多くは、実際の開発で Redis を使用する際に S...
英国企業 hypere.cloud (AS 番号 200636) は、英国ロンドンの元のデータ セン...
この記事では、JVM メモリ モデル、クラス ローダー、GC 回復アルゴリズム、GC コレクターなど...
ウェブサイトのポジショニングは、ウェブサイト構築全体の中核部分であると言えます。なぜそう言うのでしょ...