问题
We know that we can override the System classloader with:
java -Djava.system.class.loader=com.test.MyClassLoader xxx
Then, since com.test.MyClassLoader itself is a class, by whom is it loaded?
How do we get the class file of this "meta" classloader?
回答1:
From the Javadoc for ClassLoader.getSystemClassLoader:
If the system property "java.system.class.loader" is defined when this method is first invoked then the value of that property is taken to be the name of a class that will be returned as the system class loader. The class is loaded using the default system class loader and must define a public constructor that takes a single parameter of type ClassLoader which is used as the delegation parent.
The default system class loader itself is specific to the JVM implementation.
回答2:
Bootstrap classloader is the parent of all classloaders and loads the standard JDK classes in lib directory of JRE (rt.jar and i18n.jar). All the java.* classes are loaded by this classloader.
Extensions Classloader is the immediate child of Bootstrap classloader. This classloader loads the classes in lib\ext directory of the JRE.
System-Classpath classloader is the immediate child of Extensions classloader. It loads the classes and jars specified by the CLASSPATH environment variable
You could try to inject your custom class loader by means of the "java.system.class.loader" property (see ClassLoader#getSystemClassLoader).
Default System class loader is parent for MyClassLoader instances,
回答3:
Tldr:
§ ..the value of that property is taken to be the name of a class that will be returned as the system class loader. The class is loaded using the default system class loader..
..Thus, if your classloader replaces X as the system class loader, then your classloader's parent will be X, the default system class loader.
(X is of a type like sun.misc.Launcher$AppClassLoader.)
More info can be found at docs.oracle.com - How the Java Launcher Finds Classes:
The Java launcher, java, initiates the Java virtual machine. The virtual machine searches for and loads classes in this order:
Bootstrap classes - Classes that comprise the Java platform, including the classes in rt.jar and several other important jar files.
Extension classes - Classes that use the Java Extension mechanism. These are bundled as .jar files located in the extensions directory.
User classes - Classes defined by developers and third parties that do not take advantage of the extension mechanism. You identify the location of these classes using the -classpath option on the command lineor by using the CLASSPATH environment variable.
Tsmr:
We can prove that X is really the parent of our 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);
}
}
This is our main code:
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);
}
}
This is the output (on my system) when run using the command java -Djava.system.class.loader=MyCL Main (cf. Eclipse run config):
getSystemClassLoader(): MyCL@1888759
Classloader of MyCL: sun.misc.Launcher$AppClassLoader@7fdcde
..and its type: class sun.misc.Launcher$AppClassLoader
Classloader of (Classloader of MyCL): null
We can see that MyCL's classloader is sun.misc.Launcher$AppClassLoader, which is the default system classloader.
(Per the language as seen in Oracle's other quote above, the default system classloader is also called the classloader of "User Classes". Screw Oracle for coming up with 2 names for the same thing.)
回答4:
An appropriate answer would be:
And this also clarifies the original question.
When you do,
java -Djava.system.class.loader=com.test.MyClassLoader xxx
The -D option is for setting system properties in the Properties object of the java.lang.System instance that gets loaded as part of JVM startup. The option only changes the in-memory properties. On a next invocation of the class XXX or some other class, the default properties as part of System class would be loaded again. Here, you have set the java.system.class.loader property to the value com.test.MyClassLoader. In other words, you want to override the default system class loader (also called the bootstrap class loader) with your new system class loader for this invocation of your class XXX. The default system class loader, which was loaded as part of JVM startup, would lookup the in-memory java.system.class.loader property to find the name of your overriding system class loader--if set(in your case, set to MyClassLoader)--and load it from your classpath, which is, by default, the root of your working directory (that should contain XXX) or the one in the classpath variable, either as -cp or as environment variable CLASSPATH, if defined.
If your write in the main method of your class XXX
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(MyClassLoader.class.getClassLoader());
You should see
MyClassLoader
(the new system class loader that loads XXX)
sun.misc.Launcher$AppClassLoader
(the default system class loader that loaded your new system class loader)
来源:https://stackoverflow.com/questions/11395074/what-loads-the-java-system-classloader