System classloader を次のようにオーバーライドできることがわかっています。
Java -Djava.system.class.loader=com.test.MyClassLoader xxx
その後、com.test.MyClassLoader
自体はクラスで、誰がロードしますか?
この「メタ」クラスローダーのクラスファイルを取得するにはどうすればよいですか?
ClassLoader.getSystemClassLoader
のJavadocから:
このメソッドが最初に呼び出されたときにシステムプロパティ「Java.system.class.loader」が定義されている場合、そのプロパティの値は、システムクラスローダーとして返されるクラスの名前と見なされます。 クラスは、デフォルトのシステムクラスローダーを使用してロードされ、委任の親として使用されるClassLoader型の単一パラメーターを取るパブリックコンストラクターを定義する必要があります。
デフォルトのシステムクラスローダー自体は、JVM実装に固有です。
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インスタンスの親です。
§ ..そのプロパティの値は、システムクラスローダーとして返されるクラスの名前と見なされます。クラスは、デフォルトのシステムクラスローダーを使用してロードされます。
..したがって、クラスローダーがシステムクラスローダーとしてXを置き換える場合、クラスローダーの親はデフォルトのシステムクラスローダーであるXになります。
(Xは Sun.misc.Launcher$AppClassLoader
のようなタイプです。)
詳細は docs.Oracle.com-Java Launcher Finds Classes :で確認できます。
Javaランチャー、Java、Java仮想マシンを開始します。仮想マシンは次の順序でクラスを検索してロードします:
Bootstrap classes-Javaプラットフォームを構成するクラス。rt.jarのクラスと他のいくつかの重要なjarファイルを含む。
拡張機能クラス-Java拡張メカニズムを使用するクラス。これらは拡張機能ディレクトリにある.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
(ClassCL of MyCL)のクラスローダー:null
MyCL
のクラスローダーは Sun.misc.Launcher$AppClassLoader
であることがわかります。これはデフォルトのシステムクラスローダーです。
(上記のOracleの他の引用にある言語によると、デフォルトのシステムクラスローダーは「User Classes」のクラスローダーとも呼ばれます。同じものに2つの名前を付けます。)
適切な答えは次のとおりです。
そして、これも元の質問を明確にします。
すると、
Java -Djava.system.class.loader = com.test.MyClassLoader xxx
-Dオプションは、JVM起動の一部としてロードされるJava.lang.SystemインスタンスのPropertiesオブジェクトでシステムプロパティを設定するためのものです。このオプションは、メモリ内のプロパティのみを変更します。クラスXXXまたは他のクラスの次の呼び出しで、Systemクラスの一部としてのデフォルトプロパティが再度読み込まれます。ここでは、Java.system.class.loaderプロパティを値com.test.MyClassLoaderに設定しています。つまり、クラスXXXのこの呼び出しのために、デフォルトのシステムクラスローダー(bootstrapクラスローダーとも呼ばれます)を新しいシステムクラスローダーでオーバーライドします。デフォルトのシステムクラスローダーは、これは、JVM起動の一部として読み込まれ、メモリ内のJava.system.class.loaderプロパティを検索して、オーバーライドしているシステムクラスローダーの名前を検索します(設定されている場合(MyClassLoaderに設定します))。これは、デフォルトでは作業ディレクトリー(XXXを含む必要があります)のルートであるクラスパスから、または-cpまたは環境変数CLASSPATH(定義されている場合)としてのクラスパス変数内のルートです。
クラスXXXのmainメソッドに書き込む場合
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(MyClassLoader.class.getClassLoader());
見るべき
MyClassLoader
(XXXをロードする新しいシステムクラスローダー)
Sun.misc.Launcher$AppClassLoader
(新しいシステムクラスローダーをロードしたデフォルトのシステムクラスローダー)