JVM の深い理解 (焦点: 親委任モデル + ガベージ コレクション アルゴリズム)

1.JVMとは何ですか?

JVMとはJava Virtual Machineの略で、Java仮想マシンのことです。仮想マシンとは、ソフトウェアによってシミュレートされ、完全に分離された環境で実行される完全なハードウェア機能を備えた完全なコンピューター システムを指します。 JVM は現実には存在しないカスタマイズされたコンピュータと考えることができ、Java プログラムは最終的には JVM (Java Virtual Machine) 上で実行されます。

2. JVM実行処理

3. JVMランタイムデータ領域

  1. ヒープ: Java プログラムの最大のメモリ領域であり、new キーワード オブジェクトを使用して作成されたオブジェクト インスタンスと配列を格納するために使用されます。

  2. スタック: スレッドごとに個別のスタック領域を割り当てます。主にメソッド呼び出し時にスタック フレーム、ローカル変数などを格納するために使用されます。

  3. メソッド領域: 主にクラスの構造情報 (クラス オブジェクト)、メソッドのメタ情報、定数プール、静的変数などを格納するために使用されます。

  4. プログラム カウンター レジスタ: 各スレッドには独立したプログラム カウンターがあり、現在のスレッドによって実行されている命令、または次に実行される命令のアドレスを保存するために使用されます。住所。

4. JVMクラスロード機構

1. クラスロード処理

プログラムを実行するには、依存する「命令とデータ」をメモリにロードする必要があります。これは主に、 .class ファイルをメモリにロードするプロセスに反映されます。 5 つの言葉で要約すると:

  1. ロード: クラス ローダー (ClassLoader) を通じてクラスのバイトコード ファイルを検索して読み取り、メモリにロードします。読み込みプロセス中に、クラスを表す Class オブジェクトが後続の操作のために生成されます。
  2. 確認:.classファイルのデータ形式は明確です
  3. 準備: クラスで定義された変数 (静的変数、静的変数によって変更された変数) にメモリを正式に割り当て、クラス変数の初期値を設定する段階。
  4. 解析: Java 仮想マシンが定数プール内のシンボル参照を直接参照に置き換えるプロセスであり、定数を初期化するプロセスです。
  5. 初期化: 主に静的メンバーの初期化、静的コード ブロックの実行、親クラスの読み込み (親クラスが存在する場合) およびその他の処理を行います。

2. 保護者による委任モデル

ロード」のプロセスには、クラス ローダーの概念が関係します。JVM には 3 つのクラス ローダーが組み込まれています。 「 親の委任モデル: 」を構成します。

  1. BootStrap ClassLoader: Java 標準ライブラリのクラスのロードを担当します。
  2. Extension ClassLoader: Sun および Oracle 拡張ライブラリのクラスのロードを担当します。
  3. Application ClassLoader: プロジェクト内のカスタム クラスとサードパーティ ライブラリ内のクラスのロードを担当します。

クラス ローダーがクラス ロード リクエストを受信した場合、最初にクラス自体をロードしようとするのではなく、リクエストを親クラス ローダーに委任して完了します。これはクラス ローダーのすべてのレベルに当てはまります。そのため、すべてのロード リクエストは最終的に親ローダーがロード要求を完了できない(必要なクラスが検索範囲に見つからない)ことを報告した場合にのみ、子ローダーはロードを完了しようとします。特定のレイヤーの読み込みが完了して次のステップに入るまで、それでも見つからない場合は、例外がスローされます: ClassNotFoundException

5. JVM ガベージ コレクション戦略

JVM ガベージ コレクション (ガベージ コレクション) は主に、プログラムによって参照されなくなったメモリ オブジェクトを回復するために使用されます。オブジェクトはヒープメモリ上に格納されるため、CG の主なターゲットは であり、CG は 对象 単位で解放されます。他のメモリ領域については:

スタック: メソッド呼び出しが完了すると、メソッドのスタック フレームとローカル変数はポップ操作で破棄されます。スタック全体もスレッドとともに破棄されます。

メソッド領域: 主にクラス オブジェクトを格納し、「アンロード」操作を伴うことはほとんどありません。

プログラム カウンター: これは単純なアドレス整数であり、スレッドとともに破棄されます。

1. 死骸判定アルゴリズム

すべてのオブジェクト インスタンスは Java ヒープに格納されます。ヒープ上でガベージ コレクションを実行する前に、ガベージ コレクタはまず、これらのオブジェクトのうちどのオブジェクトがまだ生きていて、どのオブジェクトが「死んでいるか」を判断する必要があります。オブジェクトが「死んでいる」かどうかを判断するための主なアルゴリズムは 2 つあります。

(1) 参照カウントアルゴリズム

オブジェクトに参照カウンタを追加します。オブジェクトへの参照がある場合、カウンタは +1 になります。参照が期限切れになると、カウンタは -1 になります。カウンタが常に 0 のオブジェクトは使用できなくなります。 、つまり、オブジェクトは " "die" になりました。

オブジェクトの生存を判定するために参照カウント法を使用するという考え方は非常にシンプルであり、一般に判定効率は比較的高いですが、参照カウントでは、オブジェクトへの循環参照の問題を解決できません。

(2) 到達可能性の解析手法(Javaで採用されているソリューション)

オブジェクト内の参照関係をツリー構造として理解し、「GCルート」と呼ばれる一連のオブジェクトを起点として、これらのノードから下に向かって探索することで、たどることができるオブジェクトに到達できる限り、それ以外の場合は、次のことが証明されるオブジェクトは使用できません。

ここでの GC ルートには次のものが含まれます。

  1. スタック上で参照されるオブジェクト
  2. メソッド領域の定数プールで参照されるオブジェクト
  3. メソッド領域の静的メンバーによって参照されるオブジェクト

到達可能性分析は参照カウント方法の問題を解決しますが、循環参照問題は発生しますが、検索処理に時間がかかる場合があり、検索処理中に参照関係が変更されるのを防ぐために、一部のビジネス スレッドが作業を一時停止するため、STW (Stop-The-World) 問題が発生します。

2. ガベージコレクションアルゴリズム

(1) マーククリア

「マークスイープ」アルゴリズムは、最も基本的なガベージ コレクション アルゴリズムです。アルゴリズムは「マーキング」と「クリア」の 2 つの段階に分かれています。まず、リサイクルする必要があるすべてのオブジェクトにマークを付けます。マーキングが完了すると、マークされたすべてのオブジェクトが均一にリサイクルされます。

マーク アンド スイープ アルゴリズムの最大の問題は、記憶の断片化。一般に、メモリを申請する場合、連続した領域全体が申請されることが多く、メモリの断片化により領域使用率が大幅に削減されます。

(2) コピーアルゴリズム

容量に応じて整个可用内存同じサイズの 2 つの部分に分割され、一度に 1 つのみが使用されます。このメモリの部分をガベージ コレクションする必要がある場合、この領域に残っているオブジェクトが別の部分にコピーされ、その後、使用されているメモリ領域が一度にクリアされます。この利点は、毎回半分の領域全体がリサイクルされるため、メモリを割り当てるときにメモリの断片化などの複雑な状況を考慮する必要がないことです。

このアルゴリズムの欠点は、メモリ領域の使用率が比較的低く、利用可能な最大領域が元の平均値まで減少することです。また、使用可能なメモリにゴミがほとんどなく、保持する必要があるオブジェクトが多数ある場合は、コピーのコストが比較的高くなり、効率が低くなります。

(3) マーキングと分別

マークのデフラグでは、メモリの断片化の問題も解決できます。一般的な考え方は、シーケンシャル テーブルの中間要素を削除するのと似ています。毎回、残っているオブジェクトが一方の端に移動され、端の境界の外側にあるメモリが直接クリアされます。

マーキングや仕分けのアルゴリズムは、毎回移動する必要があるため効率の低下につながります。

(4) 世代別リサイクル(JVM採用)

世代別アルゴリズムは、領域分割を通じてさまざまな領域 (ステージ) でさまざまなガベージ コレクション戦略を実装します。多くの経験から、ほとんどの Java オブジェクトには一時的な寿命の特性があることが示されています。一般に、多数の新世代のオブジェクトは一連のスキャン後に消滅します。オブジェクトが長期間存続する場合、経験からは存続することが示されています。より長い時間。

  1. 新しく作成されたオブジェクトはエデンエリアに配置されます。ガベージ コレクションが Eden 領域をスキャンすると、ほとんどのオブジェクトは GC の最初のラウンドで強制終了されます。
  2. Eden エリア内のオブジェクトが GC の最初のラウンドで生き残った場合、生き残ったオブジェクトはコピー アルゴリズムを通じてサバイバル エリアにコピーされます。
  3. 生存領域は同じサイズの 2 つの部分に分割され、一度に半分が使用されます。ガベージ コレクションが生存領域をスキャンし、ガベージが見つかった場合は、コピー アルゴリズムを使用して生存オブジェクトを残りの半分にコピーします。サバイバルエリアの。
  4. 生存領域内のオブジェクトが数ラウンドの GC を生き延び、特定の年齢に達したとみなされると、そのオブジェクトは古い領域に入り、コピー アルゴリズムを通じて古い世代にコピーされます。
  5. 旧世代に入るオブジェクトは一般に生存時間が長く、死亡する確率が新世代よりもはるかに小さいため、旧世代の GC 頻度は大幅に低くなります。スキャンで古い世代のオブジェクトがガベージであることが判明した場合、そのオブジェクトはマーク付けされて直接削除されます。
  6. 特殊なケース: オブジェクトが非常に大きい場合、古い世代に直接入ります。大きなオブジェクトをコピーするコストは比較的高く、大きなオブジェクトはそれほど多くないためです。

6. Java 仮想マシンのガベージ コレクター (理解)

Java 仮想マシンの 3 つのガベージ コレクターは、上記のアルゴリズムの特定の実装に基づいており、通常は上記に基づいていくつかの改善と最適化が行われます。主なものは次の 2 つです。

  1. CMS (同時マークスイープ) ガベージ コレクター: CMS は、アプリケーションの一時停止時間を短縮するために設計されたガベージ コレクターです。同時マークアンドスイープ アルゴリズムを使用しているため、クリーンアップ プロセスのほとんどの間、アプリケーションは実行を継続できます。
  1. G1 (ガベージ ファースト) ガベージ コレクター: G1 はサーバー側アプリケーション用のガベージ コレクターであり、制御可能な一時停止時間と高いスループットを提供するように設計されています。世代別および地域別のガベージ コレクション戦略を使用して、一時停止時間をより正確に制御します。

おすすめ

転載: blog.csdn.net/LEE180501/article/details/132414662