Javaのクラスローディング機構

 

1.Javaクラスローディング機構の両親委託モード 

クラスのロードシーケンス図

ロード・フェーズ

クラスローダによってクラスローディング段階は、JVM内部の流れのクラスの完全なクラス名に応じて、バイナリバイトの読み出しを担当し、ゾーン法を実行しているメモリ領域に格納され、ターゲット・タイプに変換します対応のjava.lang.Class
オブジェクトインスタンスは、アクセスエントリークラスのデータのような様々な分野のための方法として、将来の意志オブジェクト。

二種類のJVMのクラスローダ、すなわち、ブートストラップクラスローダ(ブートストラップクラスローダ)とカスタムクラスローダ(ユーザー定義のクラスローダ)

拡張クラスローダ、アプリケーションクラスローダ3クラスローダを:我々は、使用していました。

ブートストラップクラスローダ:

      C ++言語で書かれた、およびJVM内にネストスタートクラスローダは、それがロードの主な原因であるJAVA_HOME/lib、すべての種類のディレクトリを。

   C ++で書かれたルートクラスローダは、クラスのすべてのjre / libにロード$ JAVA_HOMEに責任があります

拡張クラスローダ:

     ExtClassLoaderは、Java、負荷のextフォルダ(JRE \ libに\ extに)内部を担当するクラスで書かれた、ClassLoaderを導出しました。

これは、JRE拡張ディレクトリ、クラスのlib / extにをロードするか、システムプロパティのjava.ext.dirs JARディレクトリのパケットによって指定する責任があります。 

アプリケーションのクラスローダ:

     AppClassLoaderは、提供される環境変数のパスとして、クラスパスローダアプリケーションレベルの電荷に、Javaで書かれ、ClassLoaderを導出しました。

    これは、メモリ内に(そのクラスの意味、現在のパスと参照サードパーティのライブラリのパス内のディレクトリのjava -classpathまたは-Djava.class.pathも変数)ユーザクラスパスにライブラリをロードする責任があります。

 

2.両親デリゲートメカニズム:
それが動作クラスが要求を受け取ったクラスローダがロードならば、それは自分自身の負荷に行きませんが、実行するために、親クラスローダに要求を委託するということです。
親クラスローダの親クラスローダがある場合は、さらに順次再帰的にアップ委任、要求は最終的にトップ・ブートクラスローダに到達します。
親クラスローダクラスローダが正常にタスクを完了返すことができる場合は、負荷への親クラスローダは、このタスクを完了できない場合は、子ローダは、独自のをロードしようとします。

利点の両親はメカニズムを任命:
親の利点の使用は、モデルが、一緒になって、優先度の階層関係とそのクラスとしてのJavaクラスローダで委任された
とき、父、オフレベルのこの種は、繰り返し荷重を避けるために、クラスがロードされたとき、再びロードされた不要の子クラスローダはありません。
安全上の理由から、続いてのJava APIは、コアの種類を任意に置換されない定義されたネットワークを介してjava.lang.Integerのクラスという名前のパスを想定し、
それがモードを委託して、ブートクラスローダの親に送信され、ブートクラスローダクラスの名前は、クラスがロードされたことがわかった、コアのJava APIで見つかった、と我々はコアAPIを防ぐことができますのでこと、Integer.classから直接ロード返し、java.lang.Integerの上を通過したネットワークをリロードしませんライブラリが改ざんされています。

両親委託モード

一種類の機構設立設計者はJVMのクラスローダにロードされます。モードによって委託規則の両親に従っては、ブートクラスローダに加えて、各クラスローダでのプログラムは、アプリケーションクラスローダとして、スーパークラスローダを持つべきである
スーパークラスローダは拡張クラスローダ、カスタムローダーの開発者でありますスーパーは、クラスローダの負荷がタスクを受信し、すぐに負荷を拡張していない場合、アプリケーションクラスローダである
が、それぞれの層を実行するために、スーパークラスローダによってそれに割り当てられたタスクをロードしますが、ローダを使用していますアップデリゲートまでブートクラスローダの先頭に、このように、スーパークラスがクラスをロードできない場合、それはその次のレベルに戻ったクラスの内容をロードする
負荷にローダーを。効果的に持っているクラスのグローバル一意性を確保するために:利点は、親がモードを委託ということです。

 
両親委託モード

注:Java仮想マシンが明示的に親の信頼モデルを使用しなければならないのローディング機構クラスローダが必要ですが、お勧めします、としていないTomcatデフォルトのクラスローダがロードタスクを受信したときに真ん中、それは最初に作られた
、それを自動的に読み込みます負荷に失敗した場合、クラスが実行するためにそのスーパークラスローダに委譲され、これはServlet当たり前提案練習。

接続フェーズ

検証フェーズで接続され、用意し、3つの段階の設定を決議いたしました。

検証

主なタスクは、それが有効なバイトコードファイル、妥当性確認及び検証クラスカバーデータ形式、意味解析、動作検証があるかどうか、検証JVM仕様クラスの情報かどうかを検証することです

レディ

準備フェーズ主なタスクは、すべてのクラスの静的変数のためのメモリ空間を割り当てることで、セットに(被験者が発生していないので、したがってしません、このインスタンス変数の動作範囲内の)初期値

解決

主なタスクは、Java仮想マシン仕様が明示的に解決フェーズを必要としないため、直接参照に変換し、その全体がシンボリック定数プール参照のすべてのステージを解決するためにある初期化フェーズが解決できるようになるまでそう待って、順番に実行されなければならない
後の時間に。

初期化フェーズ

初期段階では、JVMを使用すると、静的変数を実行している場合、それはJVM内で設定される前に、それは準備フェーズをカバーするためにユーザーが指定した値を使用しますが、再び実行するためにすべての静的キーワードのすべてを識別し、コードのクラスになります初期値、
実行する場合はstatic代码块 JVMが静的コードのすべての操作を実行します。

 ======

JVMクラスローダ
クラスのロード処理
ロードするために
、このLoaderクラスは、通常はJVMによって行われている私たちは、クラスローダClassLoderを実装することによってカスタマイズすることができ、提供。
これは、オブジェクトのjava.lang.Classを作成するためにそれらのメモリにクラスファイルの読み込みのクラスを参照し、誰。
接続が
検証
接続フェーズが最初のステップであることを確認、このステップは、現在のファイルのバイトストリームクラス会うに関する情報は、現在の仮想マシンに含まれている要件を確実にするために、仮想マシンが自分自身の安全を危うくしませんです。
ファイル形式を確認1.
先頭のマジックナンバー(0xCAFEBABE)かどうか-
メジャーとマイナーバージョン番号が現在の仮想マシン処理の範囲内である-
-サポートされていないタイプ定数(定数タグのチェックマーク)プール内の定数があるかどうか
-定数ポインティングさまざまなインデックス値一定のポイントがある場合、存在しないか、定数のタイプを満たしていません。
- UTF8でエンコードされたデータCONSTANT_Utf8_infoタイプ定数とそこに準拠していないです。
-他のまたは追加の情報がある場合は、ファイルとファイル自体の各部分のクラスが削除されます。
- ......
2.メタデータの検証
-クラスは親クラスを持っていることを確認し、java.lang.Objectのに加えて、他のクラスは親クラスを持っている必要があります。
-このクラスは、(例えば、最終的な修飾クラスとして)継承クラス継承することを許可されていない
-これは、すべての要件が親クラスまたはインタフェースの実装の方法を達成するかどうか、抽象クラスではない場合。
-クラス属性は、親クラスの属性と競合持っていたかどうか(たとえば、親クラスの最終的な特性をカバーするように、例えば、メソッドのオーバーロードの規則に準拠しますが、同じ一貫性のあるメソッド名パラメータリストはありません)
- ......
3.バイトコード検証
セマンティック分析へのデータ・フローと制御フローによっては、メイン論理オブジェクト有効です。この段階では、(クラスを検証するために、主にメタデータ検証)メソッド本体を確認します。
クラスは、実行時に仮想マシンに害を及ぼさないであろうことを保証するために検証されます。
-任意の時間は、命令のコード配列とオペランドスタックのデータ・タイプは、協働できることを保証します。これは、ローカル変数テーブルに記憶されたデータの長いタイプを有し、オペランドスタックに配置されint型のデータを意味します。
-ジャンプはメソッド本体以外の命令のバイトコードジャンプ命令ではないことを確認します。
-変換方法は、その効果的であることを確認します。たとえば、サブタイプに割り当てられた親オブジェクト・クラスのために、オブジェクトは、オブジェクト・タイプの割り当てとは無関係のように得ました。
- ......
シンボリック参照の4.検証
シンボルは、コードをクラスファイルにコンパイルされたとき、コンパイラはだけにして、実際のメモリアドレス参照先のクラスを知らない、他のクラスへの参照、クラスで参照されています表現するために独自の記号を使用しています。
解像度位相参照シンボルで直接参照することによって置き換えられます。
場合は、このステップが正しくアクセスできるクラスへの主な記号参照を確保するために、クラスはアクセスできなく、不正アクセスは表示されません。
-シンボル参照は、完全修飾名の文字列でクラスに見つけることができます。
-フィールド名と指定されたクラスの簡単な説明に記載された方法に沿った方法がある場合。
-アクセスクラス、フィールド、シンボリック(パブリック、プライベート、保護され、デフォルトで参照する方法 ) 現在のクラスにアクセスできるかどうか。
- ......

準備
このフェーズでは、メモリクラスの静的変数を割り当てることで、デフォルトの初期値を設定します。
注:初期値は、実際のコードのデフォルト値を設定し、例えばINT = 1でない、値1は、この時点で設定が、0(整数、デフォルト0ため)であるれていません。
解決
この段階を直接参照によって置き換えクラス主にシンボリック参照です。
直接参照:ターゲットへのポインタ、または直接オフセットハンドルを位置決めすることができます。参照は、メモリレイアウトと関連している、してロードに来てください。
初期
この位相割り当てられた値、初期デフォルト値を調製するために割り当てられた値に静的変数、異なる値とここでFUの準備処理を割り当てることであり、ここでは実際の値でコードです。
注:初期化の順序であり、初期化コードの順序がダウンして書かれました。そして、静的変数にアクセスすることはできません変数が初期化されていません。

//この書き込みは、最終値I 0の後に初期化します。1の最初のiの値は、その後、静的コードブロックiが値0を有するからです。
INT iが1つの静的=、
静的{
I = 0;
}

//この書き込み、I 1の最終的な値の後に初期化。静的コードがブロックので、私は値0が割り当てられます。そして、1のI値。
{静的
I 0 =;
}
静的INT I = 1;

//この書き込み、System.out.print(I)この行のエラー。
//彼らはアクセスが変数の値を初期化されていないことができないため。しかし、それは、(i 0は、ケース2の結果として、上書きライン変数割り当ての値が割り当てられます=)割り当てることができる
{静的
; I = 0
System.out.print(I)の;
}
。静的INTを1 = I。

 

おすすめ

転載: www.cnblogs.com/awkflf11/p/12628360.html