[] Java仮想マシンの初期化クラスの-depth理解を

クラスの初期化処理

ロードクラス.PNGファイル

  • ロード

    クラスファイルは、バイナリ形式でメモリにロードされます

  • 検証

    クラスチェックファイルのセキュリティは、適切に変更されているかどうか、など

  • レディ

    デフォルト値を設定するクラス変数のためのアプリケーションメモリが(intなどの変数を初期化するためのデフォルト値は0に初期化され、参照がnullに初期化されます)が、初期クラスが真の値に初期化する前に達していません。

ゼロ値.PNGファイル

  • 解決

    シンボリック参照を直接参照に変換されます。

  • 初期化

    収集し、静的コードブロックを実行し、そして 実行方法は、 静的コードブロックの静的変数

  • 使用

    新しいオブジェクト用のアプリケーションメモリは、変数のデフォルト設定の一例として、正しい初期値が設定されている物体の例である。生成 方法

  • アンインストール

    実行時にはプラスの仮想マシンのパラメータは、+XX:+TraceClassLoading同じ情報を表示するようにアンロード、クラスのロードに関する詳細な情報を見ることができ、あなたが使用することができます-XX:TraceClassUnloading

引用されたアクティブおよびパッシブリファレンス

アクティブリファレンス

  • 初期化されていない場合は、プログレッシブ初期化、時間の新しい、getstatic、putstatic、invokestaticバイトコード命令に遭遇
  • 場合など、反射型:は、System.load( "xxxx.xxxx.xx")。
  • クラスを初期化しますが、(インターフェースの初期化がすべて初期化する親インターフェイスを必要としない)場合は、このクラスの親が初期化されていません
  • マスターJVMクラスが実行されます
  • 動的言語のサポートを経験したとき

パッシブリファレンス

  • 親クラスのサブクラスを参照する静态变量静态方法、親クラスを初期化できません。サブクラスを使用するためのイニシアチブをとるのではなく、親の積極的な使用を表し子クラスで親クラスの静的プロパティを参照
  • 型の配列を構築することにより、このように初期化されていません
  • 時間のクラスの種類ではなく、初期化に必ずしも直接参照

サンプルコード

class SuperClass {
  public static String msg = "Hello,World";

  static {
    System.out.println("SuperClass.static initializer");
  }
}

class SubClass extends SuperClass {

  public static String msg2 = "Hello,World";

  static {
    System.out.println("SubClass.static initializer");
  }
}
  • 親クラスのサブクラスで初期化しないで、サブクラスの一定の参照を確認してください
   // 验证通过子类引用父类的常量并不会初始化子类
    System.out.println(SubClass.msg);
  • 親クラスを初期化しますサブクラス同じ時間を初期化することを確認
    System.out.println(SubClass.msg2);
  • 配列の初期検証タイプが初期化されていない場合タイプ

親クラス・オブジェクト、2次元配列型[Lxxx.xxx.xxx.SubClassと同様に、タイプが動的に操作JVM、タイプ[Lxxxx.xxxx.xxxx.xxxx.SubClasss中に生成されるアレイタイプ、のため;オブジェクト型の親。

    SubClass[] subClasses = new SubClass[1];

参照定数プール

  • ソース
public class ReferenceExample002 {

  public static void main(String[] args) {
    //    实际运行的是 System.out.println(Hello, World);
    // 对于只有运行期才能确定的值,仍然会初始化类
    System.out.println(ExampleClass.msg);
  }
}

class ExampleClass {

  public static final String msg = "Hello, World";

  static {
    System.out.println("ExampleClass.static initializer");
  }
}
  • 情報逆コンパイルコードがでExampleClassへの直接参照を削除しました

public class ReferenceExample002 {
    public ReferenceExample002() {
    }

    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}
  • 次のようにニーモニック情報逆コンパイルのReferenceExample002は以下のとおりです。

javap -c xxx.xxx.xxx次のような逆コンパイルコマンド

public class com.zhoutao.example.ReferenceExample002 {
  public com.zhoutao.example.ReferenceExample002();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #4                  // String Hello, World
       5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

コンパイル時の定数値が初期化されますクラスの不確か

package com.zhoutao.classload;

import java.util.UUID;

public class ReferenceExample003 {

  public static void main(String[] args) {

    System.out.println(ExampleClass.uuid);
  }

  static class ExampleClass {
   
    // 此处引用的并非真正的常量值
    public static final String uuid = UUID.randomUUID().toString();

    static {
      System.out.println("ExampleClass.static initializer");
    }
  }
}

でExampleClass静的コードブロックが実行されます:UUID値を決定することができないとコンパイラが、それはまだ対応するクラスを初期化します、と注意定数値は区別コンパイル時に決定しました。

定数インタフェース

インタフェースの初期化時には、親が初期化、クラスの初期化時間を完了するために、インタフェースを必要とし、要求していない場合は、親クラスが初期化され、クラスの親クラスの初期化を初期化するために必要な時間が終了しました

public class ReferenceExample005 {

  public static void main(String[] args) {
    System.out.println(SubInterface.b);
  }

  static interface ParentInterface {
    public static int a = 1;
  }

  static interface SubInterface extends ParentInterface {
    public static int b = 2;
  }
}

インターフェイスおよびサブインターフェイスまたはこのクラスのない初期設定として、JVMの親が初期化され、それだけで使用该接口的静态变量的时候才会进行初始化

初期化処理の方法

Javaはクラスごとに生成されます 静的変数のための方法は、出産を与えます 方法

public class ReferenceExample006 {

  public static void main(String[] args) {
    ExampleClass exampleClass = ExampleClass.getInstance();
    System.out.println("a = " + ExampleClass.a);
    System.out.println("b = " + ExampleClass.b);
  }

  static class ExampleClass {
    public static int a;

    public static int b = 0;

    private static ExampleClass exampleClass = new ExampleClass();

    private ExampleClass() {
      a++;
      b++;
    }

    public static ExampleClass getInstance() {
      return exampleClass;
    }
  }
}

上記のコードの場合、あなたは簡単に出力値があるかを知ることができます。

a = 1
b = 1

でExampleClass Bに定義でExampleClassは、プライベートコンストラクタメソッドを置いた後場合、出力値は次のようになります。

a = 1
b = 0

これは、あります 定義および方法は、プライベートコンストラクタで、bは1の値を割り当てられることになるため、に従って行われる収集静的ブロックは、次のステップで public static int b = 0; 再びBと定義します

ファイル

こうした運用プラットフォームとしてのブログからこの記事では、大量のテキストを複数のツールOpenWriteをリリース

おすすめ

転載: www.cnblogs.com/zhoutao825638/p/12388864.html