目次
JVMクラスロードメカニズム
JVM クラスのロードの仕組みは、ロード、検証、準備、解析、初期化の 5 つの部分に分かれており、これら 5 つのプロセスを個別に見てみましょう。
- ロード
ロードはクラスのロード プロセスの段階であり、この段階では、このクラスを表す java.lang.Class オブジェクトがメモリ内に生成され、メソッド領域内のこのクラスのさまざまなデータのエントリ ポイントとして機能します。これは必ずしも Class ファイルから取得する必要はなく、ZIP パッケージから読み取ることもできます (jar パッケージや war パッケージから読み取るなど)。実行時に計算して生成することもできます (動的プロキシ)。または、他のファイル生成 (JSP ファイルを対応するクラス クラスに変換するなど) によって生成することもできます。 - この段階での検証
の主な目的は、クラス ファイルのバイト ストリームに含まれる情報が現在の仮想マシンの要件を満たしており、仮想マシン自体のセキュリティを危険にさらさないことを確認することです。 - 準備
準備段階は、クラス変数に正式にメモリを割り当て、クラス変数の初期値を設定する段階です。つまり、これらの変数が使用するメモリ空間をメソッド領域に割り当てます。ここでの初期値の概念に注意してください。たとえば、クラス変数は次のように定義されます。public static int v = 8080;
実際、準備フェーズ後の変数 v の初期値は 8080 ではなく 0 です。 v を 8080 に割り当てる put static 命令は、プログラムのコンパイル後にクラス コンストラクターの <client> メソッドに格納されます。
ただし、宣言が次の場合には注意してください。public static final int v = 8080;
コンパイル フェーズでは、v の ConstantValue 属性が生成されます。準備フェーズでは、仮想マシンは ConstantValue 属性に基づいて v を 8080 に割り当てます。
- 解決
解決フェーズとは、仮想マシンが定数プール内のシンボル参照を直接参照に置き換えるプロセスを指します。シンボル参照はクラス ファイル内にあります。
1. CONSTANT_Class_info
2. CONSTANT_Field_info
3. CONSTANT_Method_info
およびその他のタイプの定数。 - 記号の参照
- シンボリック参照は仮想マシン実装のレイアウトとは何の関係もなく、参照先をメモリにロードする必要はありません。さまざまな仮想マシン実装のメモリ レイアウトは異なる場合がありますが、受け入れ可能なシンボル参照は一貫している必要があります。これは、シンボル参照のリテラル形式が Java 仮想マシン仕様のクラス ファイル形式で明確に定義されているためです。
- 直接見積もり
- 直接参照は、ターゲットへのポインタ、相対オフセット、またはターゲットを間接的に特定するハンドルです。
直接参照がある場合、参照されるターゲットはメモリ内にすでに存在している必要があります。
- 直接参照は、ターゲットへのポインタ、相対オフセット、またはターゲットを間接的に特定するハンドルです。
- 初期化
初期化フェーズはクラス ロードの最後のフェーズであり、前のクラス ロード フェーズの後は、ロード フェーズ中にクラス ローダーをカスタマイズできることを除き、他の操作は JVM によって支配されます。初期段階では、クラスで定義された Java プログラム コードの実際の実行が始まります。
クラスコンストラクター<クライアント>
- 初期化フェーズは、クラス コンストラクターの <client> メソッドを実行するプロセスです。<client> メソッドは、クラス内のクラス変数の代入操作と静的ステートメント ブロック内のステートメントを自動的に収集するコンパイラーによって結合されます。仮想マシンは、子の <client> メソッドが実行される前に、親クラスの <client> メソッドが実行されていることを確認します。クラスに静的変数割り当てまたは静的ステートメント ブロックがない場合、コンパイラは <client> を生成する必要はありません。 ()メソッド。
- 次の状況ではクラスの初期化は実行されないことに注意してください。
1. サブクラスを介して親クラスの静的フィールドを参照すると、サブクラスではなく親クラスの初期化のみがトリガーされます。
2. このクラスの初期化をトリガーしないオブジェクト配列を定義します。
3. 定数は、コンパイル中に呼び出しクラスの定数プールに保存されますが、本質的には、定数が定義されているクラスを直接参照することはなく、定数が定義されているクラスをトリガーすることもありません。
4. クラス名を通じて Class オブジェクトを取得しても、クラスの初期化はトリガーされません。
5. Class.forName を介して指定されたクラスをロードするとき、指定されたパラメータの初期化が false の場合、クラスの初期化はトリガーされません。実際、このパラメータは仮想マシンにクラスを初期化するかどうかを指示します。
6. ClassLoader のデフォルトのloadClass メソッドは初期化アクションをトリガーしません。
クラスローダー
仮想マシン設計チームは、アプリケーションが必要なクラスを取得する方法を決定できるように、JVM の外部でロード アクションを実装します。JVM は、次の 3 種類のローダーを提供します。
- ブートストラップ クラスローダーは
、JAVA_HOME\lib ディレクトリ、または -Xbootclasspath パラメーターで指定されたパスにクラスをロードし、
仮想マシン (rt.jar などのファイル名で識別される) によって認識されます。 - Extension ClassLoader は、
JAVA_HOME\lib\ext ディレクトリまたは java.ext.dirs システム変数で指定されたパスにクラス ライブラリをロードします
。 - アプリケーション クラスローダー:
ユーザー パス (クラスパス) にクラス ライブラリをロードする役割を果たします。JVM は親委任モデルを通じてクラスをロードします。もちろん、java.lang.ClassLoader を継承してカスタム クラス ローダーを実装することもできます。
保護者代表団
クラスがクラス ロード リクエストを受信すると、最初にクラス自体をロードしようとするのではなく、リクエストを親クラスに委任して完了します。これはすべての階層クラス ローダーに当てはまります。そのため、すべてのロード リクエストが送信される必要があります。起動クラスローダーでは、親クラスローダーがリクエストを完了できない(必要なクラスがロードパスに見つからない)と報告した場合にのみ、子クラスローダーはそれを単独でロードしようとします。
親委任を使用する利点の 1 つは、たとえば、rt.jar パッケージにあるクラス java.lang.Object をロードするときに、どのローダーがこのクラスをロードしても、最終的には最上位の起動クラス ローダーに委任されることです。これにより、異なるクラス ローダーを使用しても、最終的には同じ Object オブジェクトが得られます。
OSGI(ダイナミックモデリングシステム)
OSGi (Open Service Gateway Initiative) は、Java の動的モデル システムであり、Java 動的モジュラー システムの一連の仕様です。
- 動的に構成を変更する
OSGiサービスプラットフォームは、各種ネットワーク機器の構成を再起動せずに動的に変更する機能を提供します。結合を最小限に抑え、管理しやすくするために、OSGi テクノロジは、これらのコンポーネントが動的に相互に検出できるようにするサービス指向アーキテクチャを提供します。 - モジュール式プログラミングとホットプラグ
OSGi は、Java プログラムのモジュール式プログラミングのための基本条件を提供することを目的としています。OSGi ベースのプログラムは、モジュールレベルのホットプラグ機能を実装できる可能性があります。プログラムがアップグレードおよび更新される場合、それは可能です。プログラムの一部をインストールして起動することは、エンタープライズ レベルのプログラム開発にとって非常に魅力的な機能です。
OSGi は、美しいモジュール型の開発目標を示し、この目標を達成するために必要なサービスとアーキテクチャを定義しており、実装サポートのための成熟したフレームワークも備えています。ただし、すべてのアプリケーションが OSGi をインフラストラクチャとして使用するのに適しているわけではなく、OSGi は強力な機能を提供しますが、クラス読み込みの親委任モデルに準拠していないため、さらに複雑になります。