What loads the Java system classloader?
Asked Answered
B

4

32

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?

Bohol answered 9/7, 2012 at 12:32 Comment(2)
Bootstrap load itself and to others - javabench.in/2012/02/java-class-loading.htmlKarlee
"Amusing" edge case: Under a custom system ClassLoader, MySysCl, that doesn't delegate loading of application classpath classes to its parent, MySysCl.class.getClassLoader().getClass().equals(ClassLoader.getSystemClassLoader().getClass()) == true. :)Alcott
U
23

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.

Ulrike answered 9/7, 2012 at 12:38 Comment(4)
So, our com.test.MyClassLoader's parent is the default system class loader? The default system class loader is still used? even if we overrided the system class loader?Bohol
@James.Xu: Yes, the parent is still the default system class loader, but you can always override the loadClass implementation to bypass that.Ulrike
See https://mcmap.net/q/205299/-replacement-system-classloader-for-classes-in-jars-containing-jars/632951 for more info on how to do this with code instead of cmd settings.Bromine
Always refer the documentation first , something i relearn every time I read a correct answer in SO.Recessional
V
28

The 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.

The Extensions Classloader is the immediate child of the Bootstrap classloader. This classloader loads the classes in lib\ext directory of the JRE.

The System-Classpath classloader is the immediate child of the 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).

The Default System class loader is the parent for MyClassLoader instances.

Visor answered 9/7, 2012 at 13:38 Comment(0)
U
23

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.

Ulrike answered 9/7, 2012 at 12:38 Comment(4)
So, our com.test.MyClassLoader's parent is the default system class loader? The default system class loader is still used? even if we overrided the system class loader?Bohol
@James.Xu: Yes, the parent is still the default system class loader, but you can always override the loadClass implementation to bypass that.Ulrike
See https://mcmap.net/q/205299/-replacement-system-classloader-for-classes-in-jars-containing-jars/632951 for more info on how to do this with code instead of cmd settings.Bromine
Always refer the documentation first , something i relearn every time I read a correct answer in SO.Recessional
B
9

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.)

Bromine answered 24/8, 2014 at 23:59 Comment(0)
O
0

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)

Overtime answered 4/8, 2019 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.