[食料品店] JVM#、Java仮想マシンローディング機構

バイトコードへのローカルマシンコードから結果のコードのコンパイルには、ストレージ・フォーマットの開発に小さな一歩ですが、それはプログラミング言語の開発に大きな一歩である - 「Java仮想マシンの深い理解」

メモリ内にクラスファイルからロードされたクラス、及びデータの説明仮想マシンのデータ検証、解析、変換の初期化を Java型を形成するには、仮想マシンのクラスローディング機構である仮想マシンとして使用することができます。

型ローディング、接続および初期化プログラムである実行時間の増加を実行するオーバーヘッドが、それは非常にジャワ、動的ローディング及び簡単な接続の柔軟性を増加するが、完了時。Javaはクラスファイルから取得することができないだけに属している、あなたはまた、大幅にジャワの延性を向上させるなど、直接他の場所からのバイナリストリームデータとしてネットワークを、入手することができます。

チャンス

クラスのライフサイクル

以下に示すように、7の合計後にアンロードプロセスに開始ローディングからクラス。

検証、準備は、総称して接続されている解決方法。また、ローディング、検証、製造、初期化は、このプロセスは、唯一のプロセスの実行の終了後まで待つことなく、同時に実行することができるために、5に始めているアン。例えば、私は終了する準備ができて9時、午前9時10分スタートの初期化、午前9時20分を準備し始めました。

初期化タイミング

そして、唯一、次の5例、それだけで「初期化」と呼ぶことができます。

  1. 新しい、getstatic、putstatic、invokestatic 4つのバイトコード命令に遭遇したクラスは、それが初期化され、初期化されていません発見しました。その新たな理解については、通常のクラスインスタンスの生成に加えて、時に静的メソッド呼び出しは、クラスの初期化をトリガーします。
  2. 呼び出しjava.lang.reflectで反射するパケットのクラスを使用します。
  3. 親クラスを初期化するためのクラスがまだ初期化するために時間を見つけていないときは、最初に親クラスを初期化する必要があります。
  4. メインクラス仮想マシンの起動時の初期化が実行される(クラスmain()メソッド)。
  5. 動的言語サポートのJDK1.7 +バージョンを使用している場合、我々はクラスが初期化初期化を必要としないことがわかりました。

また、クラスのメソッドへのすべての参照は、パッシブリファレンスと呼ばれるように、初期化をトリガしていません。

変数が予め割り当てられている場合、小さな違い、静的クラス・コード・ブロックを開き、使用することができる、唯一の変数代入した後、エラーは静的ブロックで使用される場合。しかし、いつでも割り当ては、限り静的コードブロック内で宣言され、その後、割り当てが許可されます。この例を見てください:

public class Test{
    static{
        i=0;//给变量赋值可以正常编译通过
        System.out.print(i);//这句编译器会提示"非法向前引用"
    }
    static int i=1;
}

インターフェイスのため、唯一の最初の3つのケースが初期化と呼ぶことにします。また、インタフェースは、事前に満たすために必要がない、親インターフェースの初期化時間そうしない限り、あなたの親インターフェイスに役立ちます。

プロセス

徐々に分析読み込み、検証、準備を、見て、これらの5つのプロセスを初期化します。

ロード

ロード・プロセスは、3つのことを行う必要があります。

  1. 定義されたクラスの完全な名前で、バイナリバイトストリームを取得するには。
  2. ランタイムデータ構造領域法に静的記憶構造を表すバイトストリーム。
  3. メソッド領域におけるこのようなオブジェクトの他の一般的な目的とは異なる代表的なメモリのタイプと、このクラスのjava.lang.Classオブジェクトを生成します。

非配列型のために、負荷は、仮想によって提供することができるクラスローダユーザによって負荷をカスタマイズすることができます。配列型の場合は、配列自体は、ローダによってロードされていませんが、直接作成されたJava仮想マシンによって、配列要素は、ローダによって作成されます。

ロード後、メモリは、後続の寝具のために、のjava.lang.Classにオブジェクトクラスを提供します。

検証

ロードが始まる一方で、オープン選択を確認します。検証は、クラスの種を含む情報バイトストリームファイルが満たしていることを確認することです最後の章、仕様について話を仮想マシン自体を危険にさらすことはありません。厳しいかどうかをこの段階では、Java仮想マシンは、その大部分を占めている実行パフォーマンス、仮想マシンのクラスローダサブシステムのワークロードの検証フェーズの観点から、悪意のあるコードを耐えることができるかどうかを決定します。

ファイル形式の検証

まず、このようなマジックナンバー(コーヒー赤ちゃん)などの仕様のクラスファイル形式、準拠を検証する必要が存在するというようにメジャーとマイナーバージョン番号が現在の仮想マシンを実行することができることを、一定のタグ記号の種類と。バイナリバイトストリームに基づいており、これだけの検証段階を介して、バイトストリームを記憶するためにメモリ内メソッド領域に入り、この段階を検証した後、3つのベリファイ後の段階は、すべてのメソッド領域記憶構造に基づいていますもはや直接バイトストリームを操作していません。

メタデータの検証

このプロセスは、親クラスがああああ、継承させ、様々な改質が競合するかどうかに親かどうかを検証することを含みます。

バイトコード検証

プログラムの主な目的のセマンティクスは、正当な論理的である場合、データ・フローと制御フロー解析を判定する。このプロセスは、任意の時点で、オペランドスタックと命令コード列のデータ型が親を確実にするために、変換のタイプが正常であることを保証するために、ジャンプ命令へのジャンプは、メソッド本体以外の命令のバイトコードではないことを保証するために協働することができることを確実にしますフィールドとサブクラスの間ように競合し、そしてません。

データフローは、JDK1.6の初めから消費される時間を遅くすることは非常に複雑な検証であるため、コードは、テーブルの属性が「StackMapTable」属性としてメソッド本体に追加し、属性が実質的にすべてのボディのための方法を説明する属性ブロック。バイトコード検証中に、これらの状態の正当性に係るプログラムをプッシュする必要はありません、唯一のStackMapTable検査記録は、合法性に属性。それは時間のバイトコード検証が保存されます。

シンボリック参照の検証

この段階では、仮想マシンで発生シンボリック参照直接基準時刻に変換され、変換動作は、接続時間の第3段階で解決される起こります。アクセスのなど、指定されたクラスのフィールド記述子フィールドやメソッドと単純名、クラス、メソッド、フィールドに記載された方法かどうか、文字列の完全修飾クラス名を確認する必要性によって見つけることができます。

レディ

準備フェーズは、正式にクラス変数にメモリを割り当て、ステージクラス変数の初期値が設定されています。この時点で、静的変数は、特にコードの値が設定されていないputstatic命令が実行されたとき、特定の必要な値が初期コードを設定し、ゼロ値の初期値に設定されています。修飾されない限り、この静的変数は、この時点で直接設定値コードを有することになる最終あります。

解決

ステージを解析するプロセスへの直接参照によって置換シンボリック参照の定数プールへの仮想マシンです。

符号:参照に記載されるシンボルのシンボル基準目標セット、リテラルシンボルは、任意の形態であってもよく、限り目標を使用するように明確に位置付けることができます。シンボル参照メモリは必ずしもメモリにロードされていないターゲットの参照を達成するために、仮想マシンの分布とは何の関係もありません。

直接参照:直接参照は、オブジェクトへの直接ポインタ、相対オフセットまたは間接的にターゲットを処理するために標的化され得ます。異なる仮想マシン・インスタンスで翻訳関連文献の仮想マシンの実装のメモリレイアウトを直接参照は、一般的にシンボルへの直接参照と同じではありませんです。あなたがその目標基準への直接参照を持っている場合は、すでにメモリ内に存在している必要があります。

invokedynamicの命令に加えて、仮想マシンの実装では、第1の解像度の結果をキャッシュすることができます。invokedynamicの命令は、命令に関連した動的言語サポートで、キャッシングを行うことはできません。

初期化

クラス初期化時のクラスのロードのプロセスの最終ステップ。カスタムクラスローダに加えて、前の操作は、主要な仮想マシンの動作、初期化フェーズで、クラスで定義されたJavaコードの完全な実装を開始しました。

位相初期化処理実行クラスコンストラクタ<クライアント>()メソッド。<クライアント>()メソッドは、コンパイラ自動的に収集クラス割り当て操作によって、それは意思決定のソース・ファイル内の文で出現順にあったブロック合併順次コンパイラコレクション内のすべてのクラス変数と静的ステートメントのステートメントを実装しています。<クライアント>()メソッドは、その設定を表示する必要はありませんコンストラクタの親クラスが良いされている、とのコードの静的ブロックは、静的コードブロックのサブクラスへの最初の親クラスです。そして<クライアント>()メソッドは、ときに実行する連動この方法を実行する異なるスレッドが現象を阻止するスレッドを表示されることがあります。

クラスローダ

この作用を達成するために、Java仮想マシンを実現するために外部にこのアクション「の完全修飾クラス名を通じて、バイナリバイトストリームを取得するには、」仮想マシンの設計チームのクラスローディング相は、コードブロックと呼ばれるクラスローダ

クラスとクラスローダー

任意のクラスのために、私たちは一緒にそのクラスローダとクラス自体をロードすることによって、Java仮想マシンでの一意性を決定する必要があります。クラスが同じであれば、2つのクラスが同じクラスローダにロードする必要があります。本明細書で使用されるクラスが等しくすることができる方法、IsAssignableFrom()メソッドでisinstance()メソッド検証に等しく、instanceofのキーワードは、判定対象の所属を作製するために使用されてもよいです。たとえば、完全修飾名はcom.pjjlt.MyTestです。仮想マシンは、2つのクラスは、オブジェクトのインスタンスは、クラスを所有するのinstanceofキーワードの範囲によってのみ等しくない生成される、ユーザ定義のクラスローダと、独自のクラスローダを装填しますそれは本当です。

両親デリゲートメカニズム

そこで問題は、私がメモリにオブジェクトをロードするために、自己定義されたクラスローダを使用し、それがあること、フル機能のJava廃棄物の全体の基礎を意味しています。実際には、新しいオブジェクトクラスともObjectクラスのネイティブは、同じように扱われます。これは、親のデリゲートメカニズムを必要とします。

仮想マシンの角度は、唯一の仮想マシンのクラスローダとユーザ定義型が記載されています。ユーザーの場合、クラスローダ(拡張クラスローダ)、アプリケーションクラスローダ(アプリケーションクラスローダ)ほんの数を拡大する起動クラスローダー(ブートストラップクラスローダ)、があり、彼らは親ローダーと組み合わせて複雑な関係にあります。

両親デリゲートメカニズムが機能します。クラスローダは、クラスが要求を受け取っロードする場合、それは最初にこのクラスをロードしようとするために所有していませんが、親ローダに委譲するクラスローダの各レベルを完了するためにありますそう、したがって、すべてのロード要求は、それだけでは、自分の時間のフィードバックをロードできない子ローダー負荷を与える、最終的トップレベルのブートローダーのクラスに送られるべきです。

人々は独自のクラスローダー、ローダーが、ロードされた親レイヤーを書き込むことによってロードされませんので、あなたは、作成したオブジェクトのクラスローダと同じのネイティブを書いた理由も説明しています。

おすすめ

転載: www.cnblogs.com/pjjlt/p/11615748.html