第四に、ガベージコレクター
1.ガベージコレクションアルゴリズム
[1] Mark-Sweepアルゴリズム(Mark-Sweep)
ガベージコレクターは、最初にリサイクルが必要なすべてのオブジェクトを判別し、それらにマークを付けてから、クリーンアップ作業を実行して、マークされたばかりのすべてのオブジェクトをリサイクルします。
短所:1つは効率的ではなく、もう1つはメモリの断片化です
[2]コピーアルゴリズム(コピー)
ガベージコレクタが機能した後もまだ生きているオブジェクトを、ガベージコレクションが実行されるメモリ領域から別の空きメモリ領域にコピーします
利点:メモリの断片化がありません
短所:メモリ領域の浪費
[3] Mark-Compactアルゴリズム
ガベージコレクターは、最初にリサイクルが必要なすべてのオブジェクトを判別してマークを付け、次にリサイクルが不要な(マークが付いていない)オブジェクトをメモリの自由端に移動し、最後にガベージコレクション操作を実行します。
利点:メモリの断片化がありません
短所:効率が低い
[4]世代別収集アルゴリズム(世代別収集)
オブジェクトのライフサイクルの違いに応じて、メモリはいくつかのブロックに分割されます。通常、Javaヒープは若い世代と古い世代に分けられます。このように、各時代の特性に応じて最適な収集アルゴリズムを採用することができます。
新世代、オブジェクトのライフサイクルは短く、レプリケーションアルゴリズムを使用するのに適しています
老後は、オブジェクトのライフサイクルが長く、保証を割り当てるための余分なスペースがないため、マークスイープまたはマーク整理アルゴリズムを使用するのに適しています
2.Javaガベージコレクター
【1】シリアル
シリアルコレクター
新世代と旧世代の両方で、ガベージコレクション操作を実行するための収集スレッドは1つだけです。収集スレッドがガベージコレクションを実行する場合、収集が終了するまで他のワーカースレッドを一時停止する必要があります(STW、Stop The World)
新世代はシングルスレッド作業とレプリケーションアルゴリズムを採用し、旧世代はシングルスレッド作業を採用し、マークアンドソートアルゴリズムを使用します
【2】ParNew
新世代の並列コレクター
SerialGCと比較すると、その最適化のポイントは、新世代が並列収集スレッドを使用して機能することです。デフォルトで有効になっている収集スレッドの数はCPUの数と同じであり、-XX:ParallelGCThreads
並列収集スレッドの数はパラメーターによって制限できます。
新世代は並列収集スレッドを使用して動作し、コピーアルゴリズムを使用します。旧世代は単一スレッドを使用して動作し、マークアンドソートアルゴリズムを使用します
【3】パラレルスカベンジ
新世代の並列コレクター
ParNewと比較して、その目標はSTW時間を短縮し、制御可能なスループットを達成することです(スループット)
スループットは、CPUがユーザーコードを実行するために使用する時間と、CPUが消費する合計時間(ユーザーコードを実行するための時間+ GC時間)の比率です。たとえば、仮想マシンが100分間実行され、ガベージコレクションに1分かかる場合、スループットは(100-1)/ 100 * 100%= 99%になります。
-XX:MaxGCPauseMillis=???
最大休止時間は、次の方法で制御できます。
そして-XX:GCTimeRatio=???
スループットを制御するために
さらに、パラメータがあります-XX:+UseAdaptiveSizePolicy
。それを開くと、JVMは現在のシステム操作に従ってパフォーマンス監視情報を収集し、-Xmn(新世代サイズ)、-XX:SurvivorRatio(エデンパークとサバイバーの比率)などの動的に調整できます。 Area)および-XX:PretenureSizeThreshold(古い年齢オブジェクトの年齢を昇格)およびその他のパラメーター
新世代は並列収集スレッドを使用して動作し、コピーアルゴリズムを使用します。旧世代は単一スレッドを使用して動作し、マークアンドソートアルゴリズムを使用します
【4】シリアルオールド(PS MarkSweep)
古いシリアルコレクター
現在は、主にCMSコレクターのバックアップ計画として使用されます。つまり、並行モード障害が発生したときに使用されます。
若い世代と古い世代でガベージコレクション操作を実行するために1つの収集スレッドのみを使用します
ParallelScavengeの旧世代のコレクターはPSMarkSweepを使用しますが、その実装はSerial Oldの実装に非常に近いため、多くの公式資料では、PSMarkSweepの代わりにSerialOldを使用して説明されています。
新世代はシングルスレッド作業とレプリケーションアルゴリズムを採用し、旧世代はシングルスレッド作業を採用し、マークアンドソートアルゴリズムを使用します
【5】パラレルオールド
パラレルコレクター
新世代は並列収集スレッドを使用して動作し、レプリケーションアルゴリズムを使用します。旧世代は並列収集スレッドを使用して動作し、マークソートアルゴリズムを使用します
【6】CMS(コンカレントマークスイープ)
コンカレントマーク-クリーンアップコレクター
最短のSTW時間を目指すコレクターです
老後は、マークスイープアルゴリズムを使用して、並列マーキングスレッドと並列収集スレッドを使用して機能します
作業過程:
-
CMSイニシャルマーク【STW】
GCルートが直接関連付けることができるオブジェクトをマークします
-
並行マーク(CMS並行マーク)[ユーザースレッドの操作]
GCルートトレースを実行する
-
CMS備考【STW】
同時マーキングの修正中、ユーザープログラムの継続的な操作により、オブジェクトのその部分のマーキングレコードが変更されます
実行時間、この段階ではあるより大きい初期マークの実行時間と未満の実行時間並行マーク
-
同時スイープ(CMS同時スイープ)[ユーザースレッドの操作]
短所:
-
CMSはCPUリソースに非常に敏感です。実際、並行性のために設計されたプログラムは、CPUリソースに非常に敏感です。同時マーキングフェーズではありますが、STWは実行されませんが、スレッドの一部(CPUリソース)を使用するため、プログラムの速度が低下し、全体的なスループットが低下します。
デフォルトで開始されるリサイクルスレッドの数は(CPUの数+ 3)/ 4です。CPUの数が4を超える場合、並列ガベージコレクションのガベージコレクションスレッドは25%以上であり、CPUの数がが4未満の場合は、収集スレッドを実行するためにCMSに与えられている計算能力の半分を取り出す必要があります。
-
CMSはフローティングガベージ(フローティングガベージ)をクリーンアップできません。同時モード障害が発生し、フルGCが発生する可能性があります
フローティングガベージとは、同時マーキングフェーズの後に表示される新しいガベージオブジェクトを指します。これらのオブジェクトは、次のGCでのみ収集できます。
-
他のコレクターと同様に、CMSは収集する前に老後がほぼ満杯になるまで待つことができません。プログラム操作を並列実行するために、スペースの一部を予約する必要があります。を使用
-XX:CMSInitiatingOccupancyFraction
して、トリガーのパーセンテージを調整できます。この属性のデフォルト値:JDK5は68、JDK6は92、JDK7は-1(JDK7にはCMSInitiatingPermOccupancyFraction
、永続生成によってトリガーされるメモリーのパーセンテージに対応する別のパラメーターがあります)、およびJDK8は-1です。予約されたメモリスペースがプログラムのニーズを満たすことができない場合、並行モード障害が発生します。このとき、JVMはバックアップ計画を開始し、一時的にシリアルオールドを開始してガベージコレクションを実行します。ただし、これによりSTW時間が長くなります。したがって、予約されたメモリスペースは小さすぎないようにする必要があります
-
CMSは、メモリの断片化を生成するマークスイープアルゴリズムを使用します。過度のメモリの断片化は、大きなオブジェクトの割り当てに多くの問題を引き起こします。古い世代には多くの空き領域がありますが、十分な連続メモリ領域が見つからないため、フルGCがトリガーされます。
-XX:+UseCMSCompactAtFullCollection
フルGC時のメモリのソート操作を制御するために使用されるパラメータがあります。ただし、メモリ統合操作は並列化できません。-XX:CMSFullGCsBeforeCompaction
メモリを配置せずに実行されるフルGCの数を設定するために使用されるパラメータもあり、その後に圧縮されたフルGCが続きます。デフォルトは0です。つまり、すべてのフルGCが圧縮されます。
【7】G1
ガベージ-まず、サーバー側アプリケーション用のガベージコレクターです
G1は、Javaヒープ全体を同じサイズの複数のリージョン(リージョン)に分割します。過去との違いは、新生代と高齢者世代の概念は保持されていますが、新生代と高齢者世代は物理的に連続しておらず、代わりに、各地域に新生代と高齢者世代の一部が含まれていることです。
デフォルトでは、Javaヒープは約2048のリージョンに分割されています(数が少なすぎると、収集効率に影響し、スキャン時間が長くなります)。-XX:G1HeapRegionSize=???
各パーティションのサイズはパラメータで調整できます。デフォルトは1MB(1048576B)、最大は32MB(33554432B)で、2の累乗、1MB未満、1MB以上、1MB以上、 2の累乗値
G1は、Javaヒープ全体でのリージョン全体のガベージコレクションを回避することも計画できます。G1は、各リージョンでのガベージ蓄積の値(GCによって解放できるメモリの量と必要な収集時間)を追跡し、1つを維持します。バックグラウンドの優先度リストでは、許容収集時間に応じて、値が最も高い領域(Garbage-Firstという名前の由来)が優先されます。
特徴:
-
並列および並行性
マルチコアCPUのハードウェアの利点を最大限に活用して、STW時間を短縮し、スループットを向上させます。また、ガベージコレクションスレッドとユーザースレッドを同時に処理できます
-
世代別コレクション
G1は、各地域を論理的にエデン、サバイバー、オールドに分割します。G1コレクターが実行されると、各リージョンは継続的に調整および切り替えられます
-
空間統合
G1は全体としてマークアンドソートアルゴリズムを使用しますが、部分的な観点からは、コピーアルゴリズムに基づいて実装されます。これは、G1コレクターの操作中に、メモリの断片化が発生しないことを意味します。プログラムは大きなオブジェクトを割り当てる必要があり、連続したメモリスペースを見つけることができないため、事前に次のGCをトリガーすることはありません。
-
予測可能な一時停止
-XX:MaxGCPauseMillis
最大STW時間は、パラメーターで指定できます。そして、確立されたリサイクル優先リストに従って、リサイクル価値の高い地域のリサイクルを優先します
作業過程:
-
イニシャルマーキング【STW】
GCルートが直接関連付けることができるオブジェクトをマークします。実行時間の短縮
-
同時マーキング[ユーザースレッドの操作]
GC Rootsから開始して、ヒープメモリ内のオブジェクトの到達可能性分析が実行され、存続しているオブジェクトが検出されます。実行時間は長いですが、ユーザープログラムと同時に実行できます
-
ファイナルマーキング【STW】
プログラムの同時実行によるマーク変更の記録を修正します。ユーザープログラムと並行して実行できます
-
スクリーニングとリサイクル(ライブデータのカウントと避難)
ユーザーが指定した一時停止時間に応じて、収集計画を立て、収集コマンドを実行します。ユーザープログラムと並行して実行できます
注:現時点では、G1コレクターは安定していないため、実動システムで使用することはお勧めしません。
3.ガベージコレクターの選択
[1] JDKソースコード
bool Arguments::check_gc_consistency() {
bool status = true;
uint i = 0;
if (UseSerialGC) i++;
if (UseConcMarkSweepGC || UseParNewGC) i++;
if (UseParallelGC || UseParallelOldGC) i++;
if (UseG1GC) i++;
if (i > 1) {
jio_fprintf(defaultStream::error_stream(),
"Conflicting collector combinations in option list; "
"please refer to the release notes for the combinations "
"allowed\n");
status = false;
}
return status;
}
JDKのC ++ソースコードには、GCポリシー設定の正しさをチェックする方法があります。
【2】シリアル+シリアルオールド
パラメータを使用する-XX:+UseSerialGC
新世代はシリアルコレクターを使用し、旧世代もシリアルコレクターを使用します
【3】ParNew +シリアルオールド
パラメータを使用する-XX:+UseParNewGC
新世代はパラレルコレクターを使用し、旧世代はシリアルコレクターを使用します
この戦略構成を使用すると、仮想マシンは警告メッセージをスローすることに注意してください
Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
このポリシー構成は使用しないことをお勧めします。将来のリリースで削除される可能性があります
【4】ParNew +(CMS +シリアルオールド)
パラメータを使用する-XX:+UseConcMarkSweepGC
新世代は並列コレクターを使用し、旧世代は並列クリアコレクターを使用します(シリアルコレクターはバックアップ計画を実行します)
【5】パラレルスカベンジ+パラレルオールド
パラメータを使用する-XX:+UseParallelGC
か-XX:+UseParallelOldGC
新世代は並列コレクターを使用し、旧世代も並列コレクターを使用します
JDK8のデフォルトのGCポリシー構成
【6】G1
パラメータを使用する-XX+:UseG1GC
[7]まとめ
シングルコア:シリアル
マルチコア、高スループット:ParallelScavengeおよびParallelOld
マルチコア、高速応答:ParNewとCMS
4.Javaオブジェクトのメモリ割り当て
-
配布はエデン(新世代エデンパーク)を優先
-
大きな物体は直接老後に入ります。いわゆるラージオブジェクトとは、非常に長い文字列や大きな配列など、大量の連続メモリスペースを必要とするオブジェクトを指します。
-XX:PretenureSizeThreshold=???
オブジェクトサイズのしきい値はパラメータで調整できます。デフォルトは0、つまり制限なしです。このパラメーターには単位がありません。このパラメーターはSerialコレクターとParNewコレクターにのみ有効であり、ParallelScavengeコレクターはこのパラメーターを認識しないことに注意してください。 -
オブジェクトの生存回数がMaxTenuringThresholdに達すると、オブジェクトは古い年齢になります
-
サバイバルエリア内の同じ年齢のすべてのオブジェクトの合計サイズがサバイバー(サバイバルエリア)の半分より大きい場合、この年齢以上の年齢のオブジェクトは、マイナーGC中に古い世代にコピーされます。 。これは動的オブジェクトの年齢判断です
-
マイナーGCが発生した場合、エデンパーク内のサバイバルオブジェクトと特定のサバイバルエリアを別のサバイバルエリアにコピーできない場合、スペース割り当て保証メカニズムは、古い世代からメモリを借用し、オブジェクトを古い世代に事前にコピーします。
XX:+HandlePromotionFailure
保証の失敗を許可するパラメータを渡すことができます保証の失敗が許可されている場合は、旧世代で使用可能な最大連続メモリが旧世代にプロモートされたオブジェクトの平均サイズよりも大きいかどうかを確認します。大きい場合は、マイナーGCを実行しようとします。それ以外の場合は実行します。フルGCを実行します。マイナーGCは、ここでは危険です。大きな存続オブジェクトが存在する可能性があり、古い世代への昇格につながり、古い世代には十分なメモリスペースがないため、フルGCになります。
保証の失敗が許可されない場合は、フルGCに直接進んでください