1.JVM の構成#
- クラスローダー:.class ファイルを JVM のメモリにロードする
- 実行時データ領域:主にプログラムカウンタ、仮想マシンスタック、ネイティブメソッドスタック、メソッド領域、ヒープで構成される
- 実行エンジン:JVM 命令を解析し、マシンコードに変換し、解析が完了したらオペレーティングシステムに送信する
- ネイティブライブラリインターフェース:異なる開発言語のネイティブライブラリを統合したもので、Java から呼び出すためのもの
- ネイティブメソッドライブラリ:Java ネイティブメソッドの具体的な実装
2. クラスローダー#
2.1 分類
- ブートストラップクラスローダー:ネイティブメソッドクラスをロードする
- 拡張クラスローダー:JDK 内部の拡張クラスをロードする
- システムクラスローダー:プログラムのクラスファイルをロードする
2.2 親子委譲メカニズム
クラスファイルを JVM のメモリにロードする際、子クラスローダーはロード要求を親クラスローダーに送り、親クラスローダーが最初にロードを試みます。親クラスローダーがクラスファイルをロードできない場合、子クラスローダーがロードを試みます。
システムクラスローダー拡張クラスローダーブートストラップクラスローダー
3. 実行エンジン#
3.1 変換#
- ジャストインタイムコンパイラ:プログラムのホットスポットコードに対して、対応するマシンコードを保存し、同じコードが再度出現した場合には保存されたマシンコードを使用して置き換えます。
- バイトコードインタプリタ:バイトコードをマシンコードに解釈します。
4. 実行時データ領域#
4.1 ヒープ#
4.1.1 構成要素
- 新生代:eden、survivor(to、from)の 2 つの領域が含まれています。
- 老年代
4.1.2 ガベージコレクションメカニズム
ガベージの判定方法
- 参照カウント法:各オブジェクトに参照数を割り当て、オブジェクトが参照される回数を表しますが、循環参照の問題が発生する可能性があります。
- 辿り可能性分析:gc ルートからのトラバースを開始し、トラバースされなかったオブジェクトはガベージと見なされます。
gc ルートには、仮想マシンスタックのスタックフレームが参照するローカル変数、ネイティブメソッドスタックの参照するローカル変数、メソッド領域のクラスの静的変数、メソッド領域の定数プール内の変数、および synchronized ロックオブジェクトが含まれます。
ガベージの回収方法
マーク・スイープアルゴリズム、マーク・コピー・アルゴリズム、マーク・コンパクションアルゴリズム、世代別収集アルゴリズム
分類
新生代ガベージコレクタ:serial、parallel new、parallel scavenge
老年代ガベージコレクタ:serial old、parallel old、cms
ミックス:G1
ガベージコレクションのタイミング
- young GC
young gen の eden 領域がいっぱいになったときにトリガーされます。注意点として、young GC では一部の生存オブジェクトが old gen に昇格するため、young GC 後に old gen の使用量が通常増加します。 - major GC
old gen 領域が一定の閾値に達したときに実行されます。(通常、cms のみが major GC を実行する?) - full GC
- 大きなオブジェクトを作成し、eden 領域に収まらない場合、そのオブジェクトは直接 old gen に保存されます。ただし、old gen のスペースも不足している場合、full GC がトリガーされます。
- メタスペースがいっぱいになった場合、full GC がトリガーされます。
- young gen のメモリを回収する際、eden 領域と Survivor From 領域から Survivor To 領域に生存オブジェクトをコピーする際、オブジェクトのサイズが Survivor To 領域の使用可能なメモリを超える場合、余分なオブジェクトは old gen に保存されます(このプロセスはアロケーション保証と呼ばれます)。この時点で、old gen の使用可能なメモリがオブジェクトのサイズよりも小さい場合、young GC を試みるかどうかを判断します。試みる場合、old gen の最大連続使用可能なメモリが以前に old gen に昇格したオブジェクトのサイズよりも大きいかどうかを判断します。大きい場合、young GC が試みられます。そうでない場合、full GC がトリガーされます。
- System.gc () を呼び出す場合
CMS
- 三色マーキング
- 主なフロー
- 初期マーキング:stw、gc ルートと young gen から直接参照されるオブジェクト(つまり、gc ルート自体)をマークします。
- 並行マーク:stw ではなく、グレーにマークされたオブジェクトをトラバースし、トラバースされたオブジェクトをグレーにマークし、エントリポイントオブジェクトをブラックにマークします。
- 並行プリパレーション:stw ではなく、並行マーク中に生成された dirty card を処理します。
- 再マーク:stw、SATB write barrier のオブジェクト参照を処理します。
- 並行クリア:stw ではなく、すべてのホワイトオブジェクトをクリアします。
- 欠点
- CPU リソースの使用
- フローティングガベージ:並行クリアフェーズ中にユーザーがガベージを生成し続けるため、次の gc でクリアする必要があります。
- メモリフラグメンテーション:CMS はマーククリアアルゴリズムを使用しているため、大量のメモリフラグメンテーションが発生します。
- 並行失敗:フローティングガベージの存在のため、CMS は新しいガベージが生成されるために一部のスペースを予約する必要があります。CMS は、Old 領域の 68%を使用するときにアクティブ化され、フローティングガベージを収容するために 32%のスペースを予約します。これは比較的保守的な設定です。実際の参照では、Old 領域の成長が速くない場合は、
-XX:CMSInitiatingOccupancyFraction
パラメータを適切な値に調整することができます。JDK6 では、トリガーのしきい値が 92%に引き上げられ、フローティングガベージを収容するために 8%のスペースが予約されました。CMS が予約したメモリにフローティングガベージを格納できない場合、フローティングガベージの存在のために「並行失敗」が発生します。この場合、JVM はバックアッププランをトリガーし、Serial Old ガベージコレクタを使用して Old 領域を回収します。この場合、停止時間はより長くなります。
G1
- リージョン
G1 は、ヒープスペース全体を同じサイズのメモリ領域であるリージョンに分割します。オブジェクトの割り当てには連続した物理的な領域が必要ではなく、論理的に連続した領域である必要があります。各リージョンは特定の世代にサービスを提供する必要はなく、必要に応じて新生代と老年代の間を切り替えることができます。起動時には、パラメータ - XX=n を使用してリージョンのサイズ(1MB〜32MB、2 のべき乗である必要があります)を指定できます。デフォルトでは、ヒープ全体が 2048 のリージョンに分割されます。
G1 では、特別な領域であるヒューモンガス領域もあります。オブジェクトのサイズがリージョンの容量の 50%以上の場合、G1 ガベージコレクタはそれをヒューモンガスオブジェクトと見なします。これらのヒューモンガスオブジェクトはデフォルトで老年代に直接割り当てられますが、それが一時的なヒューモンガスオブジェクトである場合、ガベージコレクタに負の影響を与える可能性があります。この問題を解決するために、G1 は専用のヒューモンガス領域を割り当てることがあります。ヒューモンガス領域が 1 つのリージョンに収まらない場合、G1 は連続したヒューモンガス領域を検索して割り当てます。連続したヒューモンガス領域を見つけるために、場合によってはフル GC を実行する必要があります。 - オブジェクトの割り当てポリシー
- TLAB(スレッドローカル割り当てバッファ):オブジェクトの割り当てには、スレッドごとに固定の領域である TLAB が使用されます。オブジェクトの割り当て時、スレッド間で同期する必要はありません。
- Eden 領域での割り当て:TLAB 領域で割り当てできないオブジェクトは、Eden 領域で割り当てられます。Eden 領域にオブジェクトを割り当てることができない場合、老年代に割り当てられます。
- ヒューモンガス領域の割り当て
-
young gc のプロセス
- 初期マーキング:stw、すべての gc ルートが直接参照するオブジェクト(つまり、gc ルート自体)をマークします。
- RSet の処理と更新:RSet の情報を処理し、old gen のオブジェクトが young gen のオブジェクトを保持している関連参照を追加します。
- クリーニングフェーズ:stw、すべての young region を cset にパックし、予測される回収時間が指定された許容時間よりも短い場合、eden 領域の region 数を増やさずにクリーニングを行います。それ以外の場合、予測される回収時間が指定された許容時間よりも長い場合、マークコピー操作を実行し、すべての生存オブジェクトを空の survivor にコピーします。
-
mixed gc のプロセス
-
初期マーキング:このプロセスは young GC の一時停止プロセスと一緒です。
-
ルート領域のスキャン
-
並行マーキングフェーズ:参照の変更が発生した場合(新しいメモリをオブジェクトに割り当てることは含まれません)、書き込みバリアはこれらの参照の元の値をキャプチャし、ログバッファに記録します。その後、処理されます。新しく作成されたオブジェクトの処理では、G1 は異なる方法を使用します。G1 は 2 つの TAMS 変数を使用して新しく作成されたオブジェクトを判断します。1 つは previous TAMS、もう 1 つは next TAMS です。2 つの TAMS の間にあるオブジェクトは新しく割り当てられたオブジェクトです。
-
再マーキング:stw、SATB write barrier のオブジェクト参照を処理します。
-
クリーニングフェーズ