アノテーションとリフレクション 04 -- クラスのロード

Javaメモリ分析

ここに画像の説明を挿入

クラスロードプロセスを理解する

プログラムが特定のクラスをアクティブに使用する場合、そのクラスがメモリにロードされていない場合、システムは次の 3 つの手順でクラスを初期化します。
ここに画像の説明を挿入

クラスのロードと ClassLoader の理解

1. ロード: クラス ファイルのバイトコード コンテンツをメモリにロードし、これらの静的データをメソッド領域のランタイム データ構造に変換して、このクラスを表す java.lang.Class オブジェクトを生成します。
2. リンク: Java バイナリ コードを JVM の実行状態にマージするプロセス。
(1) 検証: ロードされたクラス情報が JVM 仕様に準拠しており、セキュリティ上の問題がないことを確認します。
(2) 準備:クラス変数(静的)のメモリ確保とデフォルトのクラス変数初期値の設定を正式に行う段階で、これらのメモリはメソッド領域に確保されます。
(3)解析:仮想マシン定数プール内のシンボリック参照(定数名)を直接参照(アドレス)に変換する。
3. 初期化:
(1) クラスコンストラクター()メソッドを実行する処理。クラス コンストラクター () メソッドは、コンパイル時の自動モバイル クラス内のすべてのクラス変数のコピー アクションと静的コード内の雨具をマージすることによって生成されます。(クラス コンストラクターは、そのクラスのオブジェクトを構築するコンストラクターではなく、クラス情報を構築します)。
(2) クラスを初期化する際に、その親クラスが初期化されていないことが判明した場合は、まず親クラスの初期化を開始する必要があります。
(3) 仮想マシンは、クラスの () メソッドがマルチスレッド環境で正しくロックされ、同期されていることを保証します。

public class Test02 {
    
    
    public static void main(String[] args) {
    
    
        A a = new A();
        System.out.println(A.m);
    }
}

class A{
    
    
    static {
    
    
        System.out.println("A类静态代码初始化");
        m = 300;
    }

    static int m = 100;

    public A(){
    
    
        System.out.println("A类的无参构造初始化");
    }
}

実行後、A の値が 100 であることがわかります。出力結果から、クラス A の静的コードが最初に初期化されるため、m は最初に 300 に等しく、次に 100 に等しくなります。
ここに画像の説明を挿入

クラスの初期化はいつ行われますか

1. クラスのアクティブ参照 (クラスの初期化は必ず行われます)
(1) 仮想マシンが起動すると、まず main メソッドが配置されているクラスを初期化します
(2) クラスのオブジェクトを新規作成し
ます (3) クラスのオブジェクトを呼び出しますクラスの静的メンバー (最後の定数を除く) と静的メソッド
(4) java.lang.reflect パッケージのメソッドを使用して、クラスへのリフレクション呼び出しを行います
(5) クラスを初期化するとき、その親クラスが初期化されていない場合2.クラスの受動
参照(クラスの初期化は行われません)
(1) static フィールドにアクセスする場合、実際にそのフィールドを宣言しているクラスのみが初期化されます。たとえば、親クラスの静的変数がサブクラスを通じて参照される場合、その変数はサブクラスによって初期化されません。
(2) 配列を介したクラス定義の参照は、このクラスの初期化をトリガーしません。
(3) 参照定数は、このクラスの初期化をトリガーしません (定数は、リンク中に呼び出し側クラスの定数プールに格納されます)段階)

public class Test03 {
    
    

    static {
    
    
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //主动引用
        Son son = new Son();

        //不会产生类的引用方法
        System.out.println(Son.b);
    }
}

class Father{
    
    
    static int b = 2;

    static {
    
    
        System.out.println("父类被加载");
    }
}

class Son extends Father{
    
    
    static {
    
    
        System.out.println("子类被加载");
    }
}

クラスローダー

クラスローダーの役割

クラス ローダーの役割: クラス ファイルのバイトコード コンテンツをメモリにロードし、これらの静的データをメソッド領域のランタイム データ セクションに変換し、このクラスを表す java.lang をヒープ内に生成します。 、メソッド領域のクラスデータへのアクセスエントリとして。
クラス キャッシュ: 標準の JavaSE クラス ローダーは、必要に応じてクラスを検索できますが、クラスがクラス ローダーにロードされると、一定期間ロード キャッシュを維持します。ただし、JVM ガベージ コレクション メカニズムはこれらの Class オブジェクトを再利用できます。
ここに画像の説明を挿入
クラス ローダーの役割は、クラス (クラス) をメモリにロードすることです。JVM 仕様では、次のタイプのクラス ローダーが定義されています。
(1) ブート クラス ローダー: C++ で記述され、JVM に付属するクラス ローダーで、Java プラットフォームのコア ライブラリを担当し、コア クラスのロードに使用されます。図書館。このローダーは直接入手できません。
(2) 拡張クラス ローダー: jre/lib/ext ディレクトリ内の jar レポート、または -D java.class.path で指定されたディレクトリ内の jar レポートを作業ライブラリにロードする役割を果たします。 (3) サブクラス ローダー : java-classpath を担当します
。または -D java.class.path は、ディレクトリ内のクラスおよび jar パッケージを参照します。これは、最も一般的に使用されるローダーです。

おすすめ

転載: blog.csdn.net/cang_ling/article/details/131977230