Systemクラスローダーを次のようにオーバーライドできることがわかっています。
java -Djava.system.class.loader=com.test.MyClassLoader xxx
では、com.test.MyClassLoader
それ自体がクラスなので、誰がロードするのでしょうか。
この「メタ」クラスローダーのクラスファイルを取得するにはどうすればよいですか?
Systemクラスローダーを次のようにオーバーライドできることがわかっています。
java -Djava.system.class.loader=com.test.MyClassLoader xxx
では、com.test.MyClassLoader
それ自体がクラスなので、誰がロードするのでしょうか。
この「メタ」クラスローダーのクラスファイルを取得するにはどうすればよいですか?
Bootstrap classloader
すべての親でありclassloaders
、JRE の lib ディレクトリ (rt.jar および i18n.jar) に標準の JDK クラスをロードします。すべての java.* クラスは、この によってロードされますclassloader
。
Extensions Classloader
Bootstrap クラスローダの直接の子です。このクラスローダは、JRE の lib\ext ディレクトリにクラスをロードします。
System-Classpath classloader
Extensions クラスローダーの直接の子です。CLASSPATH
環境変数で指定されたクラスとjarをロードします
「java.system.class.loader」プロパティを使用して、カスタム クラス ローダーの挿入を試みることができます ( ClassLoader#getSystemClassLoaderを参照)。
Default System class loader
MyClassLoader インスタンスの親であり、
のJavadocからClassLoader.getSystemClassLoader
:
このメソッドが最初に呼び出されたときにシステム プロパティ「java.system.class.loader」が定義されている場合、そのプロパティの値は、システム クラス ローダーとして返されるクラスの名前と見なされます。クラスは、デフォルトのシステム クラス ローダーを使用してロードされ、委譲の親として使用される ClassLoader 型の 1 つのパラメーターを受け取るパブリック コンストラクターを定義する必要があります。
デフォルトのシステム クラス ローダー自体は、JVM 実装に固有です。
§ ..そのプロパティの値は、システム クラス ローダーとして返されるクラスの名前と見なされます。クラスは、デフォルトのシステム クラス ローダーを使用してロードされます。
..したがって、クラスローダがシステム クラス ローダとして X を置き換える場合、クラスローダの親はデフォルトのシステム クラス ローダである X になります。
(X は のような型ですsun.misc.Launcher$AppClassLoader
。)
詳細については、docs.oracle.com - How the Java Launcher Finds Classesを参照してください。
Java ランチャーである java は、Java 仮想マシンを開始します。仮想マシンは、次の順序でクラスを検索してロードします。
ブートストラップ クラス- Java プラットフォームを構成するクラス。rt.jar 内のクラスやその他のいくつかの重要な jar ファイルが含まれます。
拡張クラス- Java 拡張メカニズムを使用するクラス。これらは、extensions ディレクトリにある .jar ファイルとしてバンドルされています。
ユーザー クラス- 拡張メカニズムを利用しない、開発者およびサード パーティによって定義されたクラス。コマンド ラインで -classpath オプションを使用するか、CLASSPATH 環境変数を使用して、これらのクラスの場所を特定します。
X が実際に の親であることを証明できますClassloader
。
/** run with -Djava.system.class.loader=MyCL to use this classloader */
public class MyCL extends ClassLoader {
public MyCL(ClassLoader parent) { // this constructor must be public, else IllegalAccessException
super(parent);
}
}
これは私たちのメインコードです:
public class Main {
public static void main(String args[]) {
System.out.println("getSystemClassLoader(): " + ClassLoader.getSystemClassLoader());
ClassLoader cl = MyCL.class.getClassLoader();
System.out.println("Classloader of MyCL: " + cl);
Class type_of_cl = cl.getClass();
System.out.println("..and its type: " + type_of_cl);
ClassLoader cl_of_cl = class_of_cl.getClassLoader();
System.out.println("Classloader of (Classloader of MyCL): " + cl_of_cl);
}
}
これは、コマンドを使用して実行したときの (私のシステムでの) 出力ですjava -Djava.system.class.loader=MyCL Main
(cf. Eclipse run config ):
getSystemClassLoader(): MyCL@1888759 MyCL
のクラスローダー: sun.misc.Launcher$AppClassLoader@7fdcde ..
およびそのタイプ: クラス sun.misc.Launcher$AppClassLoader クラスローダー
(MyCL のクラスローダー): null
MyCL
のクラスローダはsun.misc.Launcher$AppClassLoader
、デフォルトのシステム クラスローダであることがわかります。
(上記のOracleの他の引用に見られる言語によると、デフォルトのシステムクラスローダーは「ユーザークラス」のクラスローダーとも呼ばれます。同じものに2つの名前を考え出すためにOracleをねじ込みます。)