JVMはクラスファイルをメモリにロードし、データを検証、変換、解析し、初期化して、最終的にJVMが直接使用できるJava型を形成するプロセスがロードメカニズムです。
クラスが仮想マシンのメモリにロードされてからメモリからアンロードされるまでのライフサイクルには、ロード、検証、準備、解決、初期化、使用 (使用)、およびアンロード (アンロード) が含まれます。 7 つの段階に分かれており、そのうち検証、準備、解析の 3 つの部分をまとめてリンクと呼びます。
ロード (ロード)、検証、準備、初期化、アンロードの 5 つの段階の順序は固定されていますが、解析段階は必ずしもこの順序で開始できるわけではありません。場合によっては初期化後に開始します。これはランタイム動的バインディング機能用です。これらのステージは通常、混合して実行され、通常は 1 つのステージの実行中に別のステージを呼び出すかアクティブ化することに注意してください。
ロードフェーズは、通常「ロード」とも呼ばれます。これは主に次のように完了します。
1.クラスの名前" クラスのバイナリ バイト ストリーム
2. バイト ストリームで表される静的ストレージ構造をメソッド領域の実行時データ構造に変換します
3. このクラスを表す java.lang.Class オブジェクトを生成しますJava ヒープ内で、メソッド領域内のこれらのデータへのアクセス ポイントとして
仮想マシンの仕様では、「このクラスを定義するバイナリ バイト ストリームを、 "クラスのフルネーム""。正確に言うと、どこでどのように取得するのかがまったく示されていません。例:
Zip パッケージからの読み取りは非常に一般的であり、最終的には将来の JAR、EAR、および WAR 形式の基礎になります。
共通アプリケーション アプレットをインターネットから入手します。
このシナリオで最も一般的に使用されるのは、動的プロキシ テクノロジであり、java.lang.reflect.Proxy では、特定の $Prxoy プロキシ クラスのバイナリ バイト ストリームを生成するために使用されます。インターフェース。
他の形式ファイルから生成、典型的なシナリオ: JSP アプリケーション
がデータベースから読み取ります。このシナリオは比較的まれで、一部のミドルウェア サーバー (SAP Netweaver など) は、プログラム コードを完成させるためにデータベースにプログラムをインストールすることを選択できます。間のクラスター分布。
クラスロードプロセスの他のステージと比較して、ロードステージ(準備的に言えば、ロードステージでクラスのバイナリバイトストリームを取得するアクション)は、開発期間中最も制御可能なステージです。提供するシステムを使用します。クラス ローダー (ClassLoader) によって完了することも、ユーザー定義のクラス ローダーによって完了することもできます。開発者は独自のクラス ローダーを定義することで、バイト ストリームの取得方法を制御できます。
ロードフェーズが完了すると、仮想マシンの外部にあるバイナリバイトストリームは、仮想マシンが要求する形式に従ってメソッド領域に格納されます。メソッド領域のデータ格納形式は、仮想マシンの実装によって定義されます。仮想マシンは領域の特定のデータ構造を規定しません。次に、java.lang.Class クラスのオブジェクトが Java ヒープ内にインスタンス化されます。このオブジェクトは、プログラムがメソッド領域内のこれらのタイプのデータにアクセスするための外部インターフェイスとして機能します。ロード フェーズとリンク フェーズの一部 (バイトコード ファイル形式検証アクションの一部など) はインターリーブされています。ロード フェーズはまだ完了しておらず、リンク フェーズが開始されている可能性がありますが、これらのアクションはまだロード フェーズの間に挟まれています。ステージの内容とこれら 2 つのステージの開始時間は依然として固定された順序を維持します。
検証は、リンクフェーズの最初のステップです。このステップの主な目的は、バイトストリームに含まれる情報を確認することです。 class ファイルは現在の仮想化に準拠しており、仮想マシンの要件を満たしており、仮想マシン自体のセキュリティを危険にさらすことはありません。
検証フェーズには主に、ファイル形式検証、メタデータ検証、バイトコード検証、シンボル参照検証の 4 つの検証プロセスが含まれます。
1. ファイル形式の検証
クラス ファイル形式の仕様を検証します。たとえば、クラス ファイルがマジック 0xCAFEBABE で始まるかどうか、メジャー バージョン番号とマイナー バージョン番号が現在の仮想マシンの処理範囲内にあるかどうかなどです。
2. メタデータの検証 この段階では、バイトコードによって記述された情報に対してセマンティック分析を実行し、記述された情報が Java 言語仕様の要件を満たしていることを確認します。検証ポイントには、このクラスに親クラスがあるかどうか (java.lang.Object を除くすべてのクラスには親クラスがある必要があります)、このクラスが継承が許可されていないクラス (final によって変更された) を継承しているかどうか、およびこのクラスの親クラスは、親クラスまたはインターフェイスに実装する必要があるすべてのメソッドを実装していますか? 3. バイトコードの検証データ フローと制御フローの分析を実行します。この段階では、クラスのメソッド本体が検証され、分析されます。この段階のタスクは、検証対象のクラスのメソッドがセキュリティを危険にさらすアクションを実行しないことを確認することです。実行時の仮想マシン。たとえば、アクセス メソッド本体の型変換が有効であることを確認します。たとえば、サブクラス オブジェクトを親クラスのデータ型に割り当てることは安全ですが、親クラスのオブジェクトをサブクラスのデータ型に割り当てることはできません。ジャンプ コマンドがメソッド本体の外部のバイトコード コマンドにジャンプしないことを確認してください。
4. シンボル参照の検証
シンボル参照内の文字列で記述された完全修飾名が対応するクラスを見つけることができるかどうか、シンボル参照クラス内のクラスかどうか、フィールドとメソッドのアクセス可能性 (プライベート、プロテクト、パブリック、デフォルト)は、現在のクラスからアクセス可能です。
準備フェーズは、クラス変数に正式にメモリが割り当てられ、クラス変数の初期値がメソッド領域に割り当てられるフェーズです。この段階で混乱しやすい点が 2 つあります。まず、この時点でのメモリ割り当てには、オブジェクトがインスタンス化されるときにオブジェクトに従うインスタンス変数ではなく、クラス変数 (静的変更変数) が含まれます。 Java ヒープ。次に、ここで言う初期値は「通常」データ型のゼロ値です。
public static int value = 12; とすると、準備フェーズ後の変数値の初期値になります。は 12 ではなく 0 です。この時点では Java メソッドが実行されておらず、プログラムのコンパイル後に 123 に値を割り当てる putstatic 命令がクラス コンストラクターの
上記の「通常の状況」では、初期値はゼロですが、一部の特殊な場合と比較して、クラスフィールドのフィールド属性テーブルに ConstantValue 属性がある場合、変数の値は ConstantValue 属性に初期化されます。準備段階では、指定された値は次のように定義されます:
public static Final int value = 123;
準備段階では、javac は value の ConstantValue 属性を生成します。 ConstantValue を 123 に設定します。
解析:
シンボリック参照: シンボリック参照は、参照されるターゲット オブジェクトを説明するためのシンボルのセットであり、使用時にターゲットを明確に特定できる限り、シンボルは任意の形式のリテラルにすることができます。シンボリック参照は、仮想マシンによって実装されるメモリ レイアウトとは何の関係もなく、参照されるターゲット オブジェクトは必ずしもメモリにロードされる必要はありません。
直接参照: 直接参照は、ターゲット オブジェクトを直接指すポインター、相対オフセット、またはターゲットを間接的に特定できるハンドルです。直接参照は、仮想マシンのメモリ レイアウトの実装に関連しています。異なる仮想マシン インスタンス上の同じシンボル参照から変換された直接参照は、通常、同じではありません。直接参照がある場合、参照ターゲットはメモリ内にすでに存在している必要があります。
仮想マシンの仕様では、解析フェーズが発生する特定の時間を規定していません。必要なのは、anewarry、checkcast、getfield、instanceof、invokeinterface、invokespecial、invokestatic、invokevirtual、multianewarray、new、putfield、putstatic などの 13 個の操作シンボルのみです。参照されるバイトコード命令の前に、それらの命令で使用されるシンボル参照が最初に解析されるため、仮想マシン実装は、クラスがローダーによってロードされるときに定数プール内のシンボル参照を解析するか、シンボル参照が完了するまで待つかを必要に応じて判断します。使用される直前に解決されます。
解析アクションは主に、クラスまたはインターフェイス、フィールド、クラス メソッド、およびインターフェイス メソッドの 4 種類のシンボル参照に対して実行されます。コンパイル済み定数プール内の 4 つの定数タイプ CONSTANT_Class_Info、CONSTANT_Fieldref_Info、CONSTANT_Methodef_Info、および CONSTANT_InterfaceMethoder_Info にそれぞれ対応します。
1. クラスとインターフェイスの分析
2. フィールドの分析
4. インターフェイス メソッドの分析
クラスの初期化フェーズはクラスの最後のステップですロードプロセスでは、クラス変数にシステムが必要とする初期値が割り当てられます。初期化フェーズでは、プログラマがプログラムを通じて作成した主観的な計画に従って、クラス変数とその他のリソースが初期化されます。別の観点から表現することもできます: 初期化 この段階は、class constructionor
1. new、getstatic、putstatic、または invokestatic の 4 つのバイトコード命令が発生した場合、クラスが初期化されていない場合は、最初にその初期化をトリガーする必要があります。これら 4 つの命令を生成する最も一般的な Java コード シナリオは、 new キーワードを使用してオブジェクトをインスタンス化すること、クラスの静的フィールドを読み取りまたは設定すること (final によって変更され、定数プールに入れられた静的フィールドを除く) です。コンパイラ) )、およびクラスの静的メソッドを呼び出すとき。
3. クラスを初期化するときに、その親クラスが初期化されていないことが判明した場合は、親クラスの最初の初期化
4. jvm が起動すると、ユーザーは実行するメイン クラス (main メソッドを含むクラス) を指定し、仮想マシンは最初にこのクラスを初期化します。
上記の準備フェーズでは、値は public static int value = 12 です。準備フェーズが完了した後の value の値は 0 で、このステージが完了した後、クラス コンストラクター
*クラス コンストラクター
*クラス コンストラクター
*親クラスの
*
*静的ステートメント ブロックはインターフェイスでは使用できませんが、インターフェイスとクラスでは不可能なのは、インターフェイスの
*仮想マシンは、マルチスレッド環境でクラスの
上記は Java Virtual Machine Learning - Class Loading Mechanism の内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。
関連記事: