JVMヒープメモリとメソッド領域の詳細な説明とガベージコレクション

1。概要

JVMは、ヒープおよびメソッド領域(非ヒープ)にデータを格納することに重点を置いているため、メモリ設計は
これら2つの領域にも重点を置いています(これら2つの領域はスレッドによって共有されていることに注意してください)。
仮想マシンスタックの場合、ローカルメソッドスタック、およびプログラムカウンターはすべてスレッドプライベートです。
JVMランタイムデータ領域は仕様であり、JVMメモリモデルは仕様の実装であることが理解できます。
ここに写真の説明を挿入

2.ヒープとメソッド領域(非ヒープ)

ここに写真の説明を挿入
1つは非ヒープエリア(メソッドエリア)、もう1つはヒープエリアです。ヒープは2つのブロックに分割され、1つはオールドエリア、もう1つはヤングエリア、ヤングは2つのブロックに分割され、1つはサバイバーエリア(S0 + S1)、もう1つはエデンエリアです。 S0はS1と同じサイズで、FromおよびToと呼ぶこともできます。

2.1オブジェクト作成プロセス

通常、新しく作成されたオブジェクトはエデンエリアに割り当てられ、一部の特別な大きなオブジェクトはオールドエリアに直接割り当てられます(保証メカニズム)。

私は普通のJavaオブジェクトです。私はエデンエリアで生まれました。エデンエリアでは、私のように見える弟も見ました。私たちはエデンエリアで長い間遊んでいました。ある日、エデンエリアに人が多すぎて、サバイバーエリアの「フロム」エリアに行かざるを得なかったのですが、サバイバーエリアに行ってから漂流し始めました。サバイバーの「フロム」エリアにいることもあります。サバイバーの「To」エリアにいたとき、私には恒久的な家がありませんでした。私が18歳になるまで、父は私が大人であり、世界に侵入するために社会に行くべきだと言いました。それで私は古い世代に行きました。古い世代には多くの人がいて、彼らはかなり古いです。

ここに写真の説明を挿入

2.2ヒープメモリの各領域の詳細な説明
名前 前書き
旧市街 オールドエリアはオールドエイジとも呼ばれ、長寿命のオブジェクトや、保証メカニズムによってヤングエリアのサイズを超える大きなオブジェクトを多数格納します。
若い地区 ヤングエリアは新世代とも呼ばれ、新しく作成されたオブジェクトと長い間作成されていないオブジェクトを格納します。ヤングエリアはエデンエリアとサバイバーエリア(S0 + S1)に分けられます。エデンエリアは新しく作成されたオブジェクトを格納し、サバイバーエリアは格納します。少なくとも1回GCされたオブジェクト

3.よくある質問

マイナー/メジャー/フルGCを理解する方法

マイナーGC:新世代
メジャーGC:旧世代
フルGC:新世代+旧世代+非ヒープ(旧世代のGCは非ヒープGCにバインドされているため)

なぜサバイバーエリアが必要なのですか?それはエデンだけではありませんか?

サバイバーがないと、エデンエリアでマイナーGCが実行されるたびに、サバイバーオブジェクトが古い世代に送信されます。このようにして、古い世代はすぐにいっぱいになり、メジャーGCがトリガーされます(メジャーGCには通常マイナーGCが伴い、フルGCのトリガーと見なすこともできるため)。
旧世代のメモリスペースは新世代のメモリスペースよりもはるかに大きく、フルGCの実行にはマイナーGCよりもはるかに長い時間がかかります。


実行時間が長いことのデメリットは何ですか?
頻繁なフルGCは長い時間を消費し、大きなプログラムの実行と応答速度に影響を与えます。あなたは言うかもしれません、そしてそれから老後のスペースを増減します。老後のスペースが増えると、より多くの生き残ったオブジェクトが老後を埋めることができます。フルGCの頻度は減りますが、旧世代のスペースが増えると、フルGCが発生すると実行に時間がかかります。旧世代のスペースを減らすと、フルGCに必要な時間は短縮されますが、旧世代はすぐにライブオブジェクトでいっぱいになり、フルGCの頻度が高くなります。したがって、サバイバーの存在の重要性は、古い世代に送信されるオブジェクトを減らし、それによってフルGCの発生を減らすことです。サバイバーの事前スクリーニングにより、16のマイナーGCの後に若い世代で生き残ることができるオブジェクトのみが送信されることが保証されます。老齢。

なぜ2つのサバイバーゾーンが必要なのですか?

最大の利点は、断片化を解決することです。つまり、サバイバーエリアが機能しないのはなぜですか?
最初の部分では、サバイバーエリアを設定する必要があることがわかります。サバイバーエリアが1つしかない場合、プロセスをシミュレートしましょう
。新しく作成されたオブジェクトはエデンにあります。エデンがいっぱいになると、マイナーGCがトリガーされ、エデンにあるサバイバーオブジェクトがサバイバーエリアに移動します。これはループし続けます。次にエデンがいっぱいになると、問題が発生します。このとき、マイナーGCが実行されます。エデンとサバイバーにはそれぞれいくつかの生き残ったオブジェクトがあります。この時点でエデンエリアの生き残ったオブジェクトがサバイバーエリアに配置されている場合、これは明らかです。オブジェクトの2つの部分が占めるメモリは連続していないため、メモリの断片化が発生します。
一方のサバイバースペースは常に空であり、もう一方の空でないサバイバースペースにはフラグメントがありません。

新世代のEden:S1:S2 8:1:1はなぜですか?

新世代で使用可能なメモリ:コピーアルゴリズムが保証に使用するメモリは9:1
です。Eden:S1領域は8:1です
。つまり、新世代ではEden:S1:S2 = 8:1:1です。
最新の商用仮想マシンはこの収集アルゴリズムを使用して新世代を回復するIBMの特別な調査によると、新世代のオブジェクトの約98%が「死にかけている」ことがわかっています。

すべての領域がヒープメモリ内のスレッドによって共有されていますか?

デフォルトでは、JVMはスレッドごとにEdenにバッファ領域を開き、TLABと呼ばれるオブジェクトの割り当てを高速化します。フルネームはThread Local AllocationBufferです。
オブジェクトは最初にTLABに割り当てられますが、TLABスペースは通常比較的小さいです。オブジェクトが比較的大きい場合でも、共有領域に割り当てられます。

4.ガベージコレクト(ガベージコレクション)

ヒープメモリには、ヤングエリアのマイナーGC、オールドエリアのメジャーGC、ヤングエリアとオールドエリアのフルGCなどのガベージコレクションがあります。
しかし、オブジェクトの場合、それがゴミであると判断する方法は?リサイクルする必要がありますか?それをリサイクルする方法は?これらの
問題を詳細に調査する必要があります。
Javaは自動メモリ管理とガベージコレクションであり、ガベージコレクションのすべての側面の知識を理解していない場合
、トラブルシューティングと解決が難しい問題がある場合、自動ガベージコレクションはJavaヒープ内のオブジェクトとオブジェクトを見つけることです。分類と識別
を行い、使用中のオブジェクトと使用されなくなったオブジェクトを見つけて、使用されないオブジェクトをヒープから削除します。

4.1オブジェクトがゴミであると判断する方法は?

ガベージコレクションを実行するには、最初にどのようなオブジェクトがガベージであるかを知る必要があります。

4.1.1参照カウント方法

オブジェクトの場合、アプリケーションがオブジェクトへの参照を保持している限り、そのオブジェクトはガベージではないことを意味します。オブジェクトにオブジェクトへのポインタがない場合、それはガベージです。
短所:ABが相互に参照を保持している場合、それをリサイクルすることはできません。

4.1.2アクセシビリティ分析

GCルートのオブジェクトを介して、オブジェクトがGCルートに到達可能かどうかを確認します(オブジェクトでは
ここに写真の説明を挿入
なく、オブジェクトへの参照)
。1。仮想マシンスタックで参照されるオブジェクト(スタックフレーム内のローカル変数テーブル)。
2.メソッド領域のクラスstaticプロパティによって参照されるオブジェクト。
3.メソッド領域の定数によって参照されるオブジェクト。
4.ネイティブメソッドスタック内のJNI(一般にネイティブメソッド)によって参照されるオブジェクト。

4.2ゴミはいつ収集されますか

GCは、JVMシステム環境によっては、JVMによって自動的に完了するため、タイミングは不確実です。
もちろん、System.gc()メソッドを呼び出してJVMにガベージコレクションを実行するように通知するなど、ガベージコレクションを手動で実行することはできます
が、操作の特定のタイミングを制御することはできません。つまり、System.gc()はリサイクルするように通知するだけであり、JVMはいつリサイクルするかを決定し
ます。ただし、GCはより多くのリソースを消費するため、このメソッドを手動で呼び出すことはお勧めしません。

シナリオ
1.エデンエリアまたはSエリアが足りない場合
2.旧世代
のスペースが足りない3.メソッドエリアのスペースが足りない
4.System.gc()

4.3ゴミ収集アルゴリズム
4.3.1マークスイープ

マーク:
メモリ内でリサイクルが必要なオブジェクトを見つけてマークします

このとき、ヒープ内のすべてのオブジェクトが1回スキャンされるため、リサイクルが必要なオブジェクトを特定できますが、これには時間がかかります。

ここに写真の説明を挿入
クリア:
リサイクル用にマークされたオブジェクトをクリアし、対応するメモリスペースを解放します。
ここに写真の説明を挿入
デメリット:
1。マーキングとクリアの両方のプロセスに時間がかかり、非効率的
です。2。多数の不連続なメモリフラグメントが生成され、スペースフラグメントが多すぎます。プログラムの実行中に大きなオブジェクトを割り当てる必要がある場合、十分な連続メモリが見つからず、別のガベージコレクションアクションを事前にトリガーする必要がある場合があります。

4.3.2マークコピー

次の図に示すように、一度に1つだけを使用して、メモリを2つの等しい領域に分割します。メモリの一方が使い果たされ
ここに写真の説明を挿入
たら、残っているオブジェクトをもう一方にコピーしてから、使用済みのメモリスペースを1回使用します。一掃します。

ここに写真の説明を挿入
短所:
スペース使用率の低下。

4.3.3マーク-コンパクト

オブジェクトの生存率が高い場合、レプリケーション収集アルゴリズムはより多くのレプリケーション操作を実行し、効率が低下します。さらに重要なこと
に、スペースの50%を無駄にしたくない場合は、使用済みメモリ内のすべてのオブジェクトが
100%存続するという極端な状況に対処するために、割り当てを保証するための追加のスペースが必要です。そのため、古い世代は通常、これを直接選択できません。アルゴリズム。

マーキングプロセスは「マークスイープ」アルゴリズムと同じですが、後続の手順では、リサイクル可能なオブジェクトを直接クリーンアップするのではなく、残っているすべてのオブジェクトを一方の端に移動してから、端の境界の外側のメモリを直接クリーンアップします。

実際、上記のプロセスでは、「コピーアルゴリズム」と比較して「予約領域」が1つ少なくなっています。

ここに写真の説明を挿入
生き残ったすべてのオブジェクトを一方の端に移動させ、境界で予期しないメモリをクリーンアップします。
ここに写真の説明を挿入

4.3.4世代別収集アルゴリズム

1.若い領域:複製アルゴリズム(オブジェクトが割り当てられた後、ライフサイクルが比較的短く、若い領域のコピー効率が比較的高い)
2。古い領域:マークの削除またはマークの並べ替え(古い領域のオブジェクトは、コピーとコピーの生存時間が長くなります)必要ありません。マークを付けてクリーンアップすることをお勧めします)

4.4ガベージコレクター

収集アルゴリズムがメモリ回復の方法論である場合、ガベージコレクタはメモリ回復の特定の実装です。

ここに写真の説明を挿入

4.4.1シリアル

ここに写真の説明を挿入

シリアルコレクターは、開発履歴が最も長い最も基本的なコレクターであり、(JDK1.3.1より前は)新世代の仮想マシンコレクションの唯一の
選択肢でした。
これはシングルスレッドコレクターです。つまり、ガベージコレクションを完了するために1つのCPUまたは1つのコレクションスレッドのみを使用するだけでなく、さらに重要なことに、ガベージコレクション中に他のスレッドを一時停止する必要があります。

利点:シンプルで効率的で、シングルスレッドの収集効率が高い。
欠点:収集プロセス中にすべてのスレッドを一時停止する必要がある。
アルゴリズム:コピーアルゴリズム。適用範囲:新世代。
アプリケーション:クライアントモードのデフォルトの新世代コレクター

4.4.2シリアルオールド

ここに写真の説明を挿入
Serial Oldコレクターは、Serialコレクターの古いバージョンであり、シングルスレッドコレクターでもあります。違いは、「マークアンドソートアルゴリズム
」を使用し、操作プロセスがSerialコレクターと同じである点です。

4.4.3 ParNew

ここに写真の説明を挿入

このコレクターは、シリアルコレクターのマルチスレッドバージョンとして理解できます。

利点:複数のCPUがある場合、シリアルよりも効率的です。
短所:収集プロセスはすべてのアプリケーションスレッドを一時停止します。これは、単一のCPUを使用する場合のシリアルよりも効率が低くなります。
アルゴリズム:コピーアルゴリズム
適用範囲:新世代
アプリケーション:サーバーモードで実行されている仮想マシンで推奨される新世代コレクター

4.4.4パラレルスカベンジ

Parallel Scavengeコレクターは新世代のコレクターであり、レプリケーションアルゴリズムを使用するコレクターでもあります。また、並列マルチスレッドコレクターでもあります。ParNewと同じように見えますが、ParallelScanvengeはシステムのスループットにさらに注意を払っています。

スループット=ユーザーコードの実行時間/(ユーザーコードの実行時間+ガベージ収集時間)たとえば
、仮想マシンは合計100分間実行され、ガベージ収集時間は1分かかります、スループット=(100-1)/ 100 = 99% 。
スループットが大きい場合は、ガベージコレクション時間が短くなり、ユーザーコードがCPUリソースを最大限に活用して、プログラム
の計算タスクをできるだけ早く完了することができることを意味します
-XX:MaxGCPauseMillisは、ガベージコレクションの最大一時停止時間を制御し
ます。-XX:GCRatioは、スループットのサイズを直接設定します。

4.4.5パラレルオールド

Parallel Oldコレクターは、Parallel Scavengeコレクターの古いバージョンであり、ガベージ
コレクションにマルチスレッドおよびマークアンドソートアルゴリズムを使用し、システムのスループットにさらに注意を払います。

4.4.6 CMS

ここに写真の説明を挿入

CMS(Concurrent Mark Sweep)コレクターは、最短のリカバリー休止時間を取得することを目的としたコレクターですCMSはマークスイープアルゴリズムを使用します。プロセス全体での同時マーキングと同時クリアにより、コレクタスレッドはユーザースレッドと連携できます。したがって、通常、CMSコレクタのメモリ回復プロセスはユーザースレッドと同時に実行されます。の。

  1. 初期マークCMS初期マークGCルートをマークして、トレースなしでオブジェクトを直接関連付けます。これは非常に高速です。
  2. GCルートトレースのCMSコンカレントマークを同時にマークします。
  3. 備考CMS備考ユーザープログラムの変更により、同時マーキングの内容を変更します。
  4. CMS同時スイープは、到達不能なオブジェクトをクリーンアップし、スペースを再利用します。同時に、新しいガベージが生成されます。次のクリーンアップ用に予約されている場合、フローティングガベージと呼ばれます。

長所:同時収集、低休止
短所:大量のスペースの断片化、同時フェーズによりスループットが低下します

4.4.7 G1(ガベージファースト)

ここに写真の説明を挿入

G1コレクターを使用する場合、Javaヒープのメモリレイアウトは他のコレクターとは大きく異なります。
新しい世代と古い世代は引き続き保持されますが、Javaヒープ全体が同じサイズの複数の独立した領域(領域)に分割されます。コンセプトですが、若い世代と古い世代は
物理的に分離されていません。これらはすべて、リージョンの一部のコレクションです(必ずしも連続している必要はありません)。

各リージョンのサイズは同じで、1Mから32Mの間の値にすることができますが、2のn乗であることが保証されている必要があります。
オブジェクトが大きすぎてリージョンが収まらない場合[リージョンサイズの50%以上]、直接になります。
それをHに入れますリージョンサイズを設定します:-XX:G1HeapRegionSize = M。
いわゆるガベージフリストは、実際にはガベージが最初に最も多いリージョンです。

(1)世代別コレクション(世代別の概念を保持)
(2)空間統合(全体として、スペースの断片化を引き起こさない「マーク整理」アルゴリズムに属します)
(3)予測可能な一時停止(CMSよりも高度)場所は、ユーザーが長さMミリ秒の時間セグメントを明確に指定できるようにすることであり、ガベージコレクションに費やされる時間はNミリ秒を超えてはなりません)

ここに写真の説明を挿入

作業過程:

  1. 初期マーキングGCルートに関連付けることができる次のオブジェクトにマークを付け、TAMSの値を変更するには、ユーザースレッドを一時停止する必要があります。
  2. 同時マーキングGCルートから到達可能性分析を実行し、残っているオブジェクトを見つけて、ユーザースレッドと同時に実行します。
  3. 最終マーキング(最終マーキング)同時マーキングフェーズでのユーザープログラムの同時実行により変更されたデータを修正し、ユーザースレッドを一時停止する必要があります。
  4. スクリーニングとリサイクル(ライブデータのカウントと避難)各地域のリサイクル値とコストを並べ替え、ユーザーが期待するGC休止時間に基づいてリサイクル計画を立てます。
4.4.8 ZGC

ここに写真の説明を挿入
JDK11によって導入された新しいZGCコレクターは、物理的または論理的に、ZGCに新旧世代の概念がなくなり、
ページに分割されます。GC操作を実行すると、ページが圧縮されるため、断片化の問題は発生しません。 64ビットLinuxでのみ使用でき、現在はあまり使用されていません。
(1)10ms以内の休止時間要件を達成できます
(2)TBレベルのメモリがサポートされます
(3)ヒープメモリが大きくなった後でも、休止時間は10ms以内です

4.4.9ガベージコレクターの分類
  • シリアルコレクター- >シリアルおよびシリアルオールド
    は、1つのガベージコレクションスレッドでのみ実行でき、ユーザースレッドは一時停止されます。
  • 並列コレクター[スループット優先度]-> Parallel Scanvenge、ParallelOld。
    複数のガベージコレクションスレッドが並行して機能しますが、ユーザースレッドはまだ待機しています。
    科学的コンピューティングやバックグラウンド処理などのインタラクティブなシナリオに適しています。
  • コンカレントコレクター[一時停止時間の優先順位]-> CMS、G1
    ユーザースレッド、およびガベージコレクションスレッドは同時に実行されます(ただし、必ずしも並行して実行されるとは限りません。交互に実行される場合があります)。ガベージコレクションスレッドは、実行中にユーザースレッドを一時停止しません。 Webなど、相対的な時間を必要とするシナリオに適した実行。
4.4.10よくある質問

スループットと一時停止時間

一時停止時間->ガベージコレクターのガベージコレクション端末アプリケーション実行応答時間
スループット->実行中のユーザーコード時間/(実行中のユーザーコード時間+ガベージコレクション時間)

一時停止時間が短いほど、ユーザーと対話する必要のあるプログラムに適しています。応答速度が良いと、ユーザーエクスペリエンスが向上します。スループットが高いと、CPU時間を効率的に使用して、プログラムのコンピューティングタスクをできるだけ早く完了できます。主に、あまり必要としないバックグラウンドコンピューティングに適しています。マルチインタラクティブタスク

適切なガベージコレクターの選び方

ヒープサイズの調整を優先し、サーバーが独自に選択できるようにします。
メモリが100M未満の場合は、シリアルコレクターを使用します。
シングルコアで、一時停止時間の要件がない
場合は、シリアルまたはJVMを使用します。一時停止時間が1秒を超えることが許可されている場合は、並列またはJVMを選択します。自分で選択する
応答時間が最も重要で1秒を超えることができない場合は、コンカレントコレクターを使用します

G1コレクションの場合

JDK 7が使用を開始し、JDK 8は非常に成熟しており、JDK 9のデフォルトのガベージコレクターであり、新旧の世代に適しています。
G1コレクターを使用していますか?

(1)ヒープの50%以上が生き残ったオブジェクトで占められている
(2)オブジェクトの割り当てと昇格の速度が大きく異なる
(3)ゴミの収集時間が比較的長い

おすすめ

転載: blog.csdn.net/qq_38306425/article/details/107811833