クラスローディングメカニズムクラスは、一度にすべてのクラスをロードするのではなく、実行時に最初に使用されるときに動的にロードされます。一度に読み込むと大量のメモリを消費するからです。 クラスのライフサイクル 以下の 7 つのステージが含まれます。
クラスロードプロセス --- 新しいオブジェクトを作成するプロセス 読み込み、検証、準備、解析、初期化の 5 つの段階が含まれます。 1. ロード 読み込みプロセスでは、次の 3 つのことが達成されます。 バイナリ バイト ストリームは、次の方法で取得できます。
2. 検証 フォーマット検証: クラス ファイルの仕様に準拠していることを確認します。セマンティック検証: final としてマークされた型にサブクラスが含まれているかどうかを確認します。クラスの最終メソッドがサブクラスによってオーバーライドされているかどうかを確認します。親クラスとサブクラスの間に互換性のないメソッド宣言がないことを確認します (たとえば、メソッド シグネチャは同じですが、メソッドの戻り値が異なるなど)。操作検証: オペランド スタック内のデータが正しく操作され、定数プール内のさまざまなシンボリック参照が検証されます (通常は解析フェーズで実行され、シンボリック参照に記述されている完全修飾名を使用して指定された型を見つけることができるかどうか、クラス メンバー情報のアクセス修飾子がアクセスを許可するかどうかなどをチェックします)。 3. 準備 クラス変数は静的に変更される変数です。準備フェーズでは、クラス変数にメモリを割り当て、メソッド領域のメモリを使用して初期値を設定します。
クラス変数が定数の場合、0 ではなく、式で定義された値に初期化されます。たとえば、次の定数値は 0 ではなく 123 に初期化されます。
この段階ではインスタンス変数にメモリは割り当てられません。オブジェクトがインスタンス化されるときに、オブジェクトとともにヒープ内に割り当てられます。 4. 分析 定数プール内のシンボリック参照を直接参照に変換します (メソッドを直接呼び出せるように、メモリ内のクラス、フィールド、またはメソッドのポインターまたはオフセットを取得します)。これは初期化後に実行でき、Java 動的バインディングをサポートできます。 上記の 2、3、4 の 3 つのステージを総称してリンク ステージと呼びます。リンク段階で必要なのは、JVM にロードされたバイナリ バイト ストリームのクラス データ情報を JVM のランタイム状態にマージすることです。 5. 初期化 初期化フェーズは、仮想マシンがクラスコンストラクタを実行するときです。 仮想マシンはクラスを保証する 上記の手順は、簡単に次の 2 つの手順に分けることができます。
最後に、メソッド領域には、クラスの静的変数、クラス初期化コード (静的変数を定義する場合の代入文と静的初期化コード ブロック)、インスタンス変数定義、インスタンス初期化コード (インスタンス変数を定義する場合の代入文インスタンス コード ブロックとコンストラクター)、インスタンス メソッド、および親クラスへのクラス情報参照など、現在のクラスのクラス情報が格納されます。 オブジェクトの作成クラスが初めて使用される場合は、オブジェクトを作成する前に上記のクラス読み込みプロセスを実行する必要があります。 「1.オブジェクトに必要なメモリをヒープ領域に割り当てる 割り当てられたメモリには、このクラスとその親クラスのすべてのインスタンス変数が含まれますが、静的変数は含まれません。 「2. 「すべてのインスタンス変数にデフォルト値を割り当てる」 メソッド領域のインスタンス変数の定義をヒープ領域にコピーし、デフォルト値を割り当てる 「3.インスタンス初期化コードを実行する」 初期化の順序は、最初に親クラスを初期化し、次に子クラスを初期化します。初期化中は、最初にインスタンス コード ブロックが実行され、次にコンストラクターが実行されます。 (クラス内の静的コードが最初に実行され、静的メンバー変数の初期化と静的ステートメント ブロックの実行が含まれます。次に、クラス内の非静的コードが実行され、非静的メンバー変数の初期化と非静的ステートメント ブロックの実行が含まれます。最後にコンストラクターが実行されます。継承の場合は、親クラスの静的コードが最初に実行され、次に子クラスの静的コードが実行され、次に親クラスの非静的コードとコンストラクターが実行され、最後に子クラスの非静的コードとコンストラクターが実行されます) 「4. Child c = new Child() という形式の参照 c がある場合、スタック領域に Child 型の参照変数 c を定義し、それにヒープ オブジェクトのアドレスを割り当てます。」 「各サブクラス オブジェクトは親クラス オブジェクトへの参照を保持する」ことに注意してください。親クラス オブジェクトは super キーワードを介して内部的に呼び出すことができますが、外部からはアクセスできません。 継承がある場合、初期化の順序は次のようになります。
クラス初期化ケースアクティブな引用 仮想マシン仕様では、ロードするタイミングについては制約を課していませんが、クラスを初期化する必要がある状況 (ロード、検証、準備が実行される状況) は次の 5 つだけであると厳密に規定されています。
受動的な引用 上記の動作は、クラスへのアクティブ参照と呼ばれます。さらに、クラスを参照する他のすべての方法では初期化がトリガーされません。これはパッシブ参照と呼ばれます。受動的な引用の一般的な例は次のとおりです。
配列定義を通じてクラスを参照しても、クラスの初期化はトリガーされません。このプロセスは、配列クラスを初期化します。配列クラスは、仮想マシンによって自動的に生成され、配列のプロパティとメソッドを含む Object から直接継承されたサブクラスです。
クラスとクラスローダー2 つのクラスが等しくなるためには、クラス自体が等しく、同じクラス ローダーを使用してロードされている必要があります。これは、各クラスローダーに個別のクラス名前空間があるためです。最終的な等価性には、Class オブジェクトの equals() メソッド、isAssignableFrom() メソッド、isInstance() メソッドからの true の戻り結果と、instanceof キーワードを使用してオブジェクトの所有権関係を判別した結果の true 結果が含まれます。 Java 仮想マシンの観点から見ると、クラス ローダーは次の 2 つだけです。
そして、上記は、BootstrapClassLoader、ExtensionClassLoader、App ClassLoaderの3種類のローダーに分けられます。
起動クラスローダーは、Java プログラムによって直接参照することはできません。ユーザーがカスタム クラス ローダーを作成するときに、読み込み要求を起動クラス ローダーに委任する必要がある場合は、代わりに null を使用できます。
親クラスローダーは Bootstrap です。
開発者はこのクラスローダーを直接使用できます。アプリケーションが独自のクラス ローダーをカスタマイズしていない場合、これは通常、プログラム内のデフォルトのクラス ローダーになります。 親ローダーは ExteClassLoader です。 親委任モデルアプリケーションは、クラスのロードを実現するために連携して動作する 3 つのクラス ローダーによってロードされます。さらに、独自のクラスローダーを追加することもできます。次の図は、親委任モデルと呼ばれるクラス ローダー間の階層関係を示しています。ここでの親子関係は、一般的に継承ではなく委任を通じて実現されます。
クラス ローダーがクラスのロード要求を受信した場合、クラス自体をロードしようとはせず、要求を親クラス ローダーに渡して完了させます。これはクラスローダーのすべてのレベルに当てはまります。したがって、すべてのクラス ロード要求は、最上位の起動クラス ローダーに渡す必要があります。親クラス ローダーがロード要求を完了できない (クラスが検索範囲内に見つからない) と報告した場合にのみ、子クラス ローダーはクラス自体のロードを試行します。
これにより、Java クラスとそのクラス ローダーは優先順位を持つ階層関係を持つことができ、基本クラスが統一されます。 たとえば、java.lang.Object は rt.jar に保存されます。別の java.lang.Object を記述して ClassPath に配置すると、プログラムをコンパイルできます。親委任モデルが存在するため、rt.jar 内のオブジェクトは ClassPath 内のオブジェクトよりも優先順位が高くなります。これは、rt.jar 内のオブジェクトがスタートアップ クラス ローダーを使用するのに対し、ClassPath 内のオブジェクトがアプリケーション クラス ローダーを使用するためです。 rt.jar 内のオブジェクトの方が優先度が高いため、プログラム内のすべてのオブジェクトはこのオブジェクトになります。
以下は、抽象クラス java.lang.ClassLoader のコード スニペットです。このコード スニペットでは、loadClass() メソッドが次のように実行されます。まず、クラスがロードされているかどうかを確認し、ロードされていない場合は、親クラス ローダーでクラスをロードします。親クラス ローダーのロードに失敗した場合は、ClassNotFoundException がスローされ、自分でロードを試みます。
次のコードの FileSystemClassLoader は、java.lang.ClassLoader から継承され、ファイル システムにクラスをロードするために使用されるカスタム クラス ローダーです。まず、クラスの完全な名前に従ってファイルシステム上のクラスのバイトコードファイル (.class ファイル) を検索し、次にファイルの内容を読み取り、最後に defineClass() メソッドを通じてバイトコードを java.lang.Class クラスのインスタンスに変換します。 java.lang.ClassLoader の loadClass() メソッドは、親委任モデルのロジックを実装します。カスタム クラス ローダーは通常これをオーバーライドしませんが、findClass() メソッドをオーバーライドする必要があります。
巨人の肩 プログラマーの春の採用ノートからの抜粋 https://github.com/CyC2018/CS-Notes この記事はWeChatの公開アカウント「Multi-Select Parameters」から転載したものです。以下のQRコードからフォローできます。この記事を転載する場合は、Multi-Select Parameters の公開アカウントにご連絡ください。 |
<<: SaaS をサービスの観点から見ると何がわかるでしょうか?
>>: クラウドのために生まれた Alibaba Cloud がクラウド サーバー オペレーティング システム Alinux3 をリリース: パフォーマンスが最大 40% 向上
新たに設立されたブランドであるMadcityserversは、独自のネットワークと独自のサーバーを運...
friendhostingはバレンタインデーにVPSを1回限り40%割引で提供しており、更新は元の価...
最近、買い物手数料を売り文句とするリベートサイトや共同購入サイトが頻繁に破綻している。浙江省の「万家...
IoT および IIoT デバイスの数が増え続けるにつれて、それらが生成するデータの量と速度も増加し...
2010 年 3 月 5 日の午後、VMware 社長兼 CEO のポール マリッツは中国訪問中に北...
ブログにタグを追加することは、ブログ記事を書くときに最も基本的な習慣の 1 つになっています。これに...
万能のクラウド モデルは、ほとんどの企業にとってもはや実行可能ではありません。企業は、コストを削減し...
世界的に有名なドメイン名登録業者 1API は、.club ドメイン名のプロモーションを実施していま...
インターネットマーケターなら誰でも知っていることですが、2012年5月2日17時頃、Baiduのデー...
6月1日、クラウドチェーンサービスプロバイダーの百山クラウドテクノロジー(以下、「百山」)は、Cラウ...
調査会社IDCも、企業がIoTのメリットを活用したいという意欲が高まるにつれて、IoTが驚異的な成長...
弊社の記者である呉偉群は、マイクロソフトが先日、3月15日からMSNメッセンジャーソフトウェアを正式...
HostCatでは、高級で上品なものから、低級で低俗なものまで、多くのVPSを紹介してきました。とに...
A5ウェブマスターネットワーク(www.admin5.com)は6月10日、国内のビデオ会社であるB...
■NewbarKが高さんの友人に送った返信メールの冒頭で、高さんが問い合わせた靴は偽物だと明確に書か...