検討:java Class.forName()とClassLoader.loadClass()の違い

1811 ワード

この2つの違いを理解する前にjavaクラスのロードメカニズムを明らかにする必要があります.
≪マウント|Load|emdw≫:クラスの全制限名でバイナリ・バイト・ストリーム(バイナリのclassファイル)を取得し、バイナリ・バイト・ストリームをメソッド領域のランタイム・データ構造に変換し、メモリにJava.lang.classオブジェクトを生成します.このとき、このタイプはメモリが割り当てられておらず、デフォルト値が設定されておらず、初期化されていません.
接続:次の検証、準備、および解析ステップを実行します.ここで、解析ステップは選択できます.
1.検証:インポートクラスまたはインタフェースのバイナリデータの正確性を検査する;(ファイル形式検証、メタデータ検証、バイトコード検証、シンボル参照検証)
2.準備:クラスの静的変数に記憶領域を割り当て、初期化する.
3.解析:定数プールのシンボル参照を直接参照に変換する.
≪初期化|Initialization|emdw≫:準備フェーズでは、クラス変数費に空間が割り当てられ、デフォルト値が初期化されますが、初期化フェーズでは、ソース・コードの文の前後順にクラス変数の付与文および(または)静的文ブロックが実行されます.
Class.forNameには、2つのリロード方法があります.
public static Class> forName(String name, boolean initialize, ClassLoader loader)
        throws ClassNotFoundException

 public static Class> forName(String className) throws ClassNotFoundException

説明:
name:com.org.prj initialize:trueの場合、Classオブジェクトを返す前に、このタイプに接続、検証、初期化操作を行います.(staticブロックのコードを実行するなど)、initializeのデフォルトでは初期化が必要です.loader:カスタムクラスローダでこのタイプを要求します.もちろんnullにも伝わりbootstrapローダで
Class.forNameのデフォルトでは初期化が必要なため、初期化するとターゲットオブジェクトのstaticブロックコードの実行がトリガーされ、staticパラメータも再初期化されます.ClassLoader.loadClassにも2つのリロード方法があります.
protected synchronized Class> loadClass(String name, boolean resolve)
    throws ClassNotFoundException

public Class> loadClass(String name) throws ClassNotFoundException 

解釈:name:クラスの全限定名、例えば:com.org.prj
resolve:このタイプに接続する必要があるかどうかを示します.接続のみ(classファイルの検証、メモリの割り当ての準備、タイプ定数プールの置き換えが含まれている)では、このタイプは初期化されません.
resolveのデフォルトはリンクされていません.リンクされていないことは、初期化などのカラムステップを含まないことを意味します.静的ブロックと静的オブジェクトは実行されません.
まとめ:
1.class.forNameが返すClassオブジェクトは、初期化するかどうかを決定します.一方、ClassLoader.loadClassが返すタイプは絶対に初期化されず、最大接続操作しかできません.  2.Class.forNameは、このタイプを要求するclassLoaderを決定します.ClassLoader.loadClassは現在のclassLoaderで要求されます.