JVM は、JAVA プラットフォームの重要なコンポーネントの 1 つです。非常に多くの知識ポイントを必要とするため、以下の側面を使用して、JVM を浅いレベルで紹介します。より深い理解が必要な場合は、Machinery Industry Press が発行する「In-depth Understanding of JAVA Virtual Machine」を学習することをお勧めします。
1. JAVAメモリ構造 Java 仮想マシン仕様で規定されている JVM ランタイム データ領域を次の図に示します。 一般的には、スレッド共有部分(メソッド領域、ヒープ)とスレッド分離領域(仮想マシンスタック、ローカルメソッドスタック、プログラムカウンター)に分かれています。 1. 方法領域 クラス情報、定数、静的変数、仮想マシンによってロードされたジャストインタイムコンパイラによってコンパイルされたコードなどのデータを格納するために使用されます。定数は、コンパイル中に生成されたリテラルとシンボリック参照を格納するために使用される領域の一部であるランタイム定数領域に格納されます。ただし、ランタイム定数領域の内容はコンパイル時にのみ生成されるわけではありません。 String.intern() を介して実行時に定数領域にコンテンツを追加することもできます。 2.ヒープ これは JVM 内の特別なメモリ領域であり、オブジェクト インスタンスと配列を格納するためにのみ使用されます。このエリアはGCのメインエリアでもあります。 3. 仮想マシンスタック 各スレッド メソッドは実行時にスタック フレームを作成します。スタック フレームには、ローカル変数テーブル、戻りアドレス、オペランド スタックなどの情報が含まれます。各メソッドの実行と完了は、スタック フレームのプッシュおよびポップ プロセスに対応します。ローカル変数テーブルが占めるスペースのサイズは、コンパイル時に決定されます。 4. ネイティブメソッドスタック 仮想マシン スタックに似ていますが、ネイティブ メソッドが実行されます。 HotSpot 仮想マシンでは、ローカル メソッド スタックと仮想マシン スタックが統合されています。 5. プログラムカウンタ 小さなメモリスペースです。スレッドが Java メソッドを実行している場合、このメモリ領域には実行中の仮想マシン バイトコード命令が記録されます。スレッドがネイティブ メソッドを実行している場合、計算機の値は空になります。 2. JAVAガベージコレクションメカニズム JAVA のガベージ コレクションには、主に、オブジェクトが生きているかどうかの判断やガベージ コレクションなどのアルゴリズムが含まれます。オブジェクトコレクションアルゴリズムは到達可能性分析アルゴリズムを使用し、現在 JVM メーカーで広く使用されているガベージコレクションアルゴリズムは世代別コレクションアルゴリズムです。ここでは主に、世代別コレクション アルゴリズムのプロセスについて説明します。 世代別コレクション アルゴリズムの中心的な考え方は、オブジェクトのライフ サイクル ステージに応じてメモリ領域を分割することであり、ヒープ領域は若い世代と古い世代に分割されます。非ヒープ領域 (通常はメソッド領域) を永続世代に分割します。 1. 新世代 新しい世代は、さらにエデン領域と 2 つのサバイバー領域に分割できます (2 つのサバイバー領域は交換しやすいように同じサイズです)。新しく生成されたオブジェクトは、まず新世代の Eden 領域に保存されます。新世代の特徴は、ガベージコレクションが実行されるたびに大量のメモリがリサイクルされ、コレクションが比較的頻繁に行われるため、新世代は次のコレクションアルゴリズムに適していることです。 まず、新しく生成されたオブジェクトが Eden 領域に割り当てられます。 Eden 領域がいっぱいの場合、到達可能なオブジェクトは survivor1 領域にコピーされ、その後 Eden 領域がクリアされます。 次に、survivor1 領域がいっぱいの場合は、eden 領域と survivor1 領域内の到達可能なオブジェクトを survivor2 領域にコピーし、eden 領域と survivor1 領域をクリアします。クリア後、survivor2 エリアを survivor1 エリアと交換します。つまり、survivor2 を空のままにします。 また、survivor2 領域もいっぱいになった場合は、eden 領域、survivor1 領域、survivor2 領域内の到達可能なオブジェクトが古い世代にコピーされ、新しい世代がクリアされます。 ***、古い世代もいっぱいになると、フル GC がトリガーされます。 2. 古い世代 旧世代のメモリは新世代のメモリよりもはるかに大きく、この領域でのガベージコレクションの頻度は高くありません。古い世代がいっぱいになると、フル GC がトリガーされます。 3. 永続的な生成 永続的な世代とは、一般的に、リサイクルする必要がある破棄された定数とクラスが含まれるメソッド領域を指します。定数の場合、到達可能性分析を使用してリサイクルを決定できます。クラスの場合、リサイクルするには以下の条件を同時に満たす必要があります。 まず、このクラスのすべてのインスタンス オブジェクトがリサイクルされています。 第二に、このクラスのクラスローダーもリサイクルされています。 繰り返しますが、このクラスの Class メソッドはどこからも参照されていません。つまり、このクラスのメソッドはどこからもリフレクションを通じてアクセスできません。 4. ガベージコレクションはいつ解決されますか? 要約すると、eden がいっぱいになると、scavenge GC がトリガーされ、次の状況が発生すると full GC がトリガーされます。 古い世代は満員です。 永久世代は満杯です。 System.gc() メソッドを呼び出します。 3. JAVAクラスのロードプロセス JVM クラスのロード プロセスは、ロード、検証、準備、解析、初期化の 5 つの部分で構成されます。 1. 読み込み 読み込みプロセス中は、次のことを行う必要があります。 1) クラスの完全修飾名を使用してクラスのバイナリ バイト ストリームを取得します。 2) クラスのバイナリ バイト ストリームをメソッド領域のランタイム データ構造に変換します。 3) メソッド領域内のこのクラスのさまざまなデータへのアクセス ポイントとして、このクラスを表す java.lang.Class オブジェクトを生成します。 2. 検証 検証、解析、初期化は接続フェーズとも呼ばれます。検証の主な目的は、バイナリ バイト ストリームが JVM 仕様に準拠しており、コンピューターのセキュリティを危険にさらさないことを確認することです。検証フェーズ中に実行する必要がある具体的な事項は次のとおりです。 1) ファイル形式の検証。バイト ストリームがクラス ファイル形式仕様に準拠しているかどうかを検証します。 2) メタデータ検証: バイトコードの意味検証を行い、その記述情報が JAVA 言語仕様に準拠していることを確認します。 3) バイトコード検証: データフローと制御フローの分析を通じて、プログラムのセマンティクスが合法かつ論理的かどうかを判断します。 4) シンボル参照検証: 定数プール内のさまざまなシンボル参照の情報の一致を検証します。 3. 準備 準備プロセスは、実際にはメモリを割り当てるプロセスです。この段階では混同しやすい概念が 2 つあります。まず、この段階で割り当てられるメモリはインスタンス変数ではなく、クラス変数 (静的変数) のみに使用されます。インスタンス変数のメモリ割り当ては、オブジェクトがインスタンス化されるときにオブジェクトとともにヒープ内に割り当てられます。 2 番目に、この段階で割り当てられたメモリに格納される値はデータ型のゼロ値のみであり、初期化フェーズ中に特定の値を割り当てる必要があります。特殊なケースもあり、静的定数(最終変更)の場合は、準備段階で実際の値に割り当てられます。 4. 分析 解析フェーズは、定数プール内の壊れたシンボルへの参照を直接参照に変換するプロセスであり、具体的には、クラスとインターフェースの解析、フィールドの解析、メソッドの解析、およびインターフェース メソッドの解析が含まれます。 5. 初期化 初期化フェーズは、実際にはクラス コンストラクター (clinit) を実行するフェーズです。 clinit() については以下の点を説明する必要があります。 1) clinit() 内のプログラムは、クラス内の静的変数と静的ブロックを収集して自動的に生成され、実行順序はコード内の順序と一致します。静的ステートメント ブロックでは、その前に宣言された静的変数にのみアクセスできます。それ以降に宣言された静的変数には値を割り当てることしかできず、アクセスすることはできません。 2) clinit() メソッドを実行する前に、JVM は親クラスの clinit() メソッドを自動的に呼び出します。 3) 仮想マシンは、クラスの clinit() がマルチスレッド環境で自動的にロックされ、同期されることを保証します。 4. JVMクラスローダー JVM クラスのロードはクラスローダーを通じて実装されます。よく使用されるクラス ローダーには次の 3 つがあります。 1. ブートストラップクラスローダー: {JDK_HOME}/lib 下のクラスをロードします。 2. 拡張クラスローダー: {JDK_HOME}/lib/ext の下のクラスをロードします。 3. アプリケーションクラスローダー: クラスパスで指定されたクラスをロードします さまざまなクラス ローダーとそれらの連携については、以下の親委任モデルを参照してください。 親委任モデルの動作プロセスは次のとおりです。クラス ローダーがクラス ロード要求を受信すると、まずその要求を親クラスに委任します。これは各レベルのクラス ローダーに当てはまります。すべての読み込み要求は最終的にブートローダーに送信されるからです。親ローダーが単独でロード要求を完了できない場合にのみ、子ローダーが単独でロードを試行します。 親委任モデルにより、混乱を招くことなく JAVA クラスを階層的にロードできるようになります。 5. JVM関連ツール JDK には、コマンド ラインから直接実行できる強力な監視ツールが多数あります。これは、実稼働環境での監視に非常に役立ちます。たとえば、SUN JDK には次の監視およびトラブルシューティング ツールが含まれています。 jps: jvm プロセス ステータス ツール。指定されたシステム内のすべてのホットスポット仮想マシン プロセスを表示します。 jstat: ホットスポット仮想マシンのさまざまな動作データを収集するために使用される、JVM 統計監視ツール jinfo: Java の構成情報、仮想マシンの構成情報を表示します jmap: Java のメモリ マップ。仮想マシンのメモリ ダンプ スナップショット (ヒープダンプ ファイル) を生成します。 jhat: jvm ヒープダンプ ブラウザ。ヒープマップ ファイルを分析するために使用され、ユーザーがブラウザで分析結果を表示できるように http/html サーバーをセットアップします。 jstack: Java のスタック トレース。仮想マシンのスレッドのスナップショットを表示します。 |
<<: 面接でJava仮想マシン(JVM)について質問されたら、この記事を読んでください。
>>: Uber の大規模決済システムの構築中に学んだ分散アーキテクチャの概念
Big Network Dataは、双十一イベントに関する多くの新情報を追加しました:(1)湖北省十...
従来の人材紹介サイトには広告が溢れています。経営者は、自社の成長に貢献できる人材を採用するために多額...
今年初めの SEO で最もホットな話題は、Baidu が Baidu Sharing Tool を正...
namesilo は、目標達成 (年間管理するドメイン名の数が前年の「何とも言えない」数倍) を記念...
ハード広告マーケティングに少しでも偏りがあれば、製品の販売に影響するだけでなく、ブランドイメージにも...
今朝は、部署の作業報告書を定期的に整理してアーカイブしました。あるインターネットマーケターが、広州の...
新型コロナウイルス感染症のパンデミックにより、多くの企業は予想よりも早く従来のテクノロジーの負担に対...
一般的に、SEO 最適化は次の 4 つの主要な部分で構成されます。最初のウェブサイト内部構造の最適化...
ご存知のとおり、SEO 最適化は非常に大変な仕事です。毎日同じことを何度も繰り返すことを意味します。...
近年、OpenStackを中核としたオープンソースソフトウェアの開発がクラウドコンピューティングに大...
今日、Namecheap がサーバー サービスを全面的に更新したというニュースを受け取りました。最低...
ヴィルマックはどうですか? Virmach Dallas のコンピューター ルームはどうですか? V...
学生は学習状況を反映する評価が必要であり、教師は教育状況を反映する評価が必要であり、ビジネスパーソン...
[51CTO.comからのオリジナル記事] 2016年の「不動産エコシステムの革新を推進する新技術」...
myserverplanet は、オプションのコンピュータ ルーム 4 台を備えた特別価格のサーバー...