この記事では主にJVMがクラスをロードするプロセスを紹介します。非常に優れた参考値です。以下のエディターで見てみましょう
クラスのロードプロセス
Javaのソースコードはクラスのバイトコードにコンパイルされ、JVMはクラスを記述するバイトコードの.Classファイルをロードします。データをメモリにロードし、データの検証、変換、分析、初期化を実行し、最終的に仮想マシンで直接使用できる Java 型を形成します。これが仮想マシンのクラス ロード メカニズムです。
クラスが仮想マシンのメモリにロードされてからメモリからアンロードされるまでのライフサイクルには、ロード、検証、準備、解決、初期化、使用 (使用)、およびアンロード (アンロード) が含まれます。 7 つの段階に分かれており、そのうち検証、準備、解析の 3 つの部分をまとめてリンクと呼びます。
ロード (ロード)、検証、準備、初期化、アンロードの 5 つの段階の順序は固定されていますが、解析段階は必ずしもこの順序で開始できるわけではありません。場合によっては初期化後に開始します。これはランタイム動的バインディング機能 (動的バインディングまたはオーバーライドなどの遅延バインディングとも呼ばれます) 用です。
1. ロード:
ロードフェーズ中に、仮想マシンは主に 3 つのことを実行します:
1. クラスの完全修飾名を使用して、このクラスを定義するバイナリ バイト ストリームを取得します。
2. このバイトストリームで表される静的ストレージ構造をメソッド領域の実行時データ構造に変換します。
3. メソッド領域データへのアクセス入口として、Java ヒープ内にこのクラスを表す java.lang.Class オブジェクトを生成します
クラス読み込みプロセスの他の段階と比較して、読み込み段階 ( (準備段階) ロードフェーズでクラスのバイナリバイトストリームを取得する動作と言われています) ロードフェーズはシステムが提供するクラスローダ(ClassLoader)を使用して完了できるため、開発期間中最も制御しやすいフェーズですまたは、ユーザーがカスタマイズできるクラス ローダーが完成し、開発者は独自のクラス ローダーを定義してバイト ストリームの取得方法を制御できます。
ロードフェーズが完了すると、仮想マシンの外部にあるバイナリバイトストリームは、仮想マシンが要求する形式に従ってメソッド領域に格納されます。メソッド領域のデータ格納形式は、仮想マシンの実装によって定義されます。仮想マシンは領域の特定のデータ構造を規定しません。次に、java.lang.Class クラスのオブジェクトが Java ヒープ内にインスタンス化されます。このオブジェクトは、プログラムがメソッド領域内のこれらのタイプのデータにアクセスするための外部インターフェイスとして機能します。
2. 検証:
検証フェーズの目的は、クラス ファイルのバイト ストリームに含まれる情報が JVM 仕様に準拠しており、JVM に害を及ぼさないことを確認することです。検証が失敗した場合は、java.lang.VerifyError 例外またはそのサブクラス例外がスローされます。検証プロセスは 4 つの段階に分かれています
1. ファイル形式の検証: バイト ストリーム ファイルがクラス ファイル形式の仕様に準拠しており、現在の仮想マシンで正しく処理できるかどうかを検証します。
2. メタデータ検証: 記述された情報が Java 言語の仕様に準拠していることを確認するために、バイトコードによって記述された情報の意味解析です。
3. バイトコード検証: 主にデータ フローと制御フローを分析し、検証されたクラスのメソッドが実行時に仮想マシンに害を及ぼさないことを確認します。
4. シンボル参照の検証: 仮想マシンがシンボル参照を直接参照に変換するときに、この変換アクションが解析フェーズ中に発生します。
3. 準備:
準備フェーズでは、変数にメモリを割り当て、クラス変数の初期化を設定します。この段階では、クラスのインスタンス変数ではなく、クラスの変数 (静的に変更された変数) のみが割り当てられます。最終的ではなくなった変数の場合、JVM は代入ステートメントの値の代わりに変数を「ゼロ値」に設定します:
pirvate static int size = 12; この段階では、size の値は 0 です。 12ではありません。 Final によって変更されたクラス変数には実数値が割り当てられます。
4. 解析:解析フェーズは、仮想マシン定数プール内のシンボル参照を直接参照に置き換えるプロセスです。
シンボリック参照: シンボリック参照は、参照されるターゲット オブジェクトを説明するためのシンボルのセットであり、使用時にターゲットを明確に特定できる限り、シンボルは任意の形式のリテラルにすることができます。シンボリック参照は、仮想マシンによって実装されるメモリ レイアウトとは何の関係もなく、参照されるターゲット オブジェクトは必ずしもメモリにロードされる必要はありません。
直接参照: 直接参照は、ターゲット オブジェクトを直接指すポインター、相対オフセット、またはターゲットを間接的に特定できるハンドルです。直接参照は、仮想マシンのメモリ レイアウトの実装に関連しています。異なる仮想マシン インスタンス上の同じシンボル参照から変換された直接参照は、通常、同じではありません。直接参照がある場合、参照ターゲットはメモリ内にすでに存在している必要があります。
仮想マシンの仕様では、解析フェーズが発生する特定の時間を規定していません。anewarry、checkcast、getfield、instanceof、invokeinterface、invokespecial、invokestatic、invokevirtual、multianewarray、new、putfield の実行中に必要なだけです。 putstatic バイトコード命令の前に、使用するシンボル参照が最初に解析されるため、仮想マシン実装は、クラスがローダーによってロードされるときに定数プール内のシンボル参照を解析するか、シンボリック命令が実行されるまで待機するかを必要に応じて判断します。参照は使用される直前に解決されます。 解析アクションは主に、クラスまたはインターフェイス、フィールド、クラス メソッド、およびインターフェイス メソッドの 4 種類のシンボル参照に対して実行されます。コンパイル済み定数プール内の 4 つの定数タイプ CONSTANT_Class_Info、CONSTANT_Fieldref_Info、CONSTANT_Methodef_Info、および CONSTANT_InterfaceMethoder_Info にそれぞれ対応します。1. クラスとインターフェースの分析
2. フィールドの分析
4. インターフェースメソッドの分析5. 初期化:
クラスの初期化フェーズは、クラスのロードプロセスの最後のステップです。準備フェーズでは、クラス変数にはシステムが必要とする初期値が割り当てられています。初期化フェーズでは、主観的な値に基づいています。プログラムを通じてプログラマーによって作成された計画。クラス変数やその他のリソースを初期化します。または、別の観点から表現することもできます。初期化フェーズは、クラス コンストラクター 6 を実行します。使用:
新しいスレッド --- プログラムカウンタ ---- jvm スタック実行 (オブジェクト参照) ----- ヒープメモリ (直接参照) ----メソッド領域
7. アンインストール:
GC ガベージコレクション
以上がJVM がクラスをロードするプロセスの詳細な図による説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。