Java仮想マシンのクラスローディング機構 - クラスローダの機会

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

JVMクラスのライフサイクルにおいて:
負荷- >確認- >準備- >分析- >初期化- >使用- >アン
前記ベリファイ- >準備- >分析まとめ接続部。

どのような状況下では、それがロードされますか?JVMの仕様は、特定の仮想マシンに、義務をしません自由に把握することができます。しかし、5例があり、すぐにクラスを初期化する必要があります:
1、あなたはクラス内で初期化されている場合は、これらの4つのバイトコード命令invokestatic、あなたが彼らの最初のをトリガーする必要がある場合、新しいgetstatic、putstatic遭遇。時間の(静的フィールドの定数プールにコンパイルされている結果を除いて、最終的な変更、)新しい新しい使用、読み取りまたはクラスの静的フィールドを設定すると、呼び出し:これは4つの最も一般的なシナリオがあるバイトコード命令を生成し、ときに、クラスの静的メソッド。
2、java.lang.reflectのパッケージアプローチと呼ばれるクラスを反映するときにクラスが初期化されていないされている場合、あなたはその初期化をトリガーする必要があります。
私たちは、その親が初期化されていない見つけた場合3、クラスが初期化されるとき、あなたは親クラスの初期化をトリガーする必要があります。
仮想マシンが起動されたときに図4に示すように、ユーザが実行するメインクラス(そのクラスのmain()メソッドが含まれている)、このマスタークラスを初期化する仮想マシンを指定する必要があります。
図5に示すように、動的言語サポートJDK1.7、方法はjava.lang.invoke.MethodHandleインスタンス最終的な分析結果REF_getStatic、REF_putStatic、REF_invokeStatic、および初期化されていないクラスに対応する、この方法のハンドルを扱う場合、あなたは、その初期化をトリガーする必要があります。

次の3つの例:
実施例1

public class SubClass extends SuperClass {
//子类
    static {
        System.out.println("SubClass init!");
    }
}
public class SuperClass {
//父类
    static {
        System.out.println("SuperClass init");
    }
    public static int value = 123;
}
public class test {
    public static void main(String[] args){
    //通过子类调用父类的静态字段,不会进行初始化
        System.out.println(SubClass.value);
    }
}

コードの出力は、
スーパークラスのinit
123

理由:静的フィールドの場合、唯一のフィールドを初期化するクラスを定義する指示、したがってサブクラスを初期化するトリガすることなく、親クラスで定義された静的フィールドは、それが唯一の親クラスの初期化をトリガーするそのサブクラスによって参照。

実施例2は、
実施の形態SuperClssクラス1に従っ

public class test {
    public static void main(String[] args){
        SuperClass[] a = new SuperClass[10];
    }
}

出力されていないスーパークラスのinit。スーパークラスが初期化されていないことを意味します。

原因:このコードは、継承Objectクラスが初期化されるようになります。初期化クラスを自動的に、直接オブジェクトから継承されたJVMによって生成された一次元アレイである、NEWARRAYによってトリガアクションを作成します。

例3

public class Const {

    static {
        System.out.println("ConstClass init!");
    }
    static {
        System.out.println("ConstClass init 222!");
    }

    public Const(){
        System.out.println("调用Const的构造函数");
    }

    public static final String HW = "HelloWorld";
}

public class NoInitialization {
    public static void main(String[] args){
        System.out.println(Const.HW);
    }
}

出力:HelloWorldの
これはconstとして意味が初期化されていません

理由:定数Const.HWへNoInitialization参照がにされた後、コンパイル時にJavaソースコード内の参照定数のConstクラスが、実際には、定数伝播の最適化を通じて、これは、定数プールNoInitializationクラスに一定に保たれています自身への一定の基準。これは、クラスファイルNoInitialization実際には、クラスの入り口に兆候のconst参照はありません。

クラスローダとインタフェースをロードすると、わずかに異なっています。インタフェースの初期化が、インターフェイスは、シーン、異なるシナリオで初期化されなければならない第三のクラス初期化されなければならないという点で異なります。クラスの初期化が行われた場合、親クラスのすべての要件は、初期化されているが、インターフェースではなく、インターフェースは、親を必要としません。すべては、(このような参照としてインターフェイスで定義された定数は、)初期化されますときに使用する唯一の本当の親インターフェイスを初期化されています。

おすすめ

転載: blog.csdn.net/huqianlei/article/details/90723532