Every time you create an instance of a Java class, the class must first be loaded into memory. The JVM uses a class loader to load classes. The class loader normally searches some core Java libraries and all directories included in the CLASSPATH environment variable. If it does not find the required class, it throws a ClassNotFoundException.
Starting from J2SE 1.2, the JVM employs three class loaders: bootstrap class loader,extension class loader, and system class loader. Each of the three class loaders has a parent-child relationship with each other, in which the bootstrap class loader sits at the topmost of the hierarchy and the system class loader at the bottom.
The bootstrap class loader is used to bootstrap the JVM. It starts working whenever you call the java.exe program. As such, it must be implemented using the native code because it is used to load the classes required for the JVM to function. Also, it is responsible for loading all the core Java classes, such as those in java.lang and java.io packages. The bootstrap class loader searches the core libraries such as rt.jar, i18n.jar, etc. Which libraries are searched depends on the version of the JVM and the operating system.
The extension class loader is responsible for loading classes in a standard extension directory. This is to make the programmer’s life easier because they can just copy jar files into this extension directory and the jar files will be searched automatically. The extension library differs from one vendor to another. Sun’s JVM’s standard extension directory is /jdk/jre/lib/ext.
The system class loader is the default class loader and searches the directories and jar files specified in the CLASSPATH environment variable.
So, which class loader does the JVM use? The answer lies in the delegation model,which is there for security reasons. Every time a class needs to be loaded, the system class loader is first called. However, it does not load the class right away. Instead, it delegates the task to its parent, the extension class loader. The extension class loader also delegates it to its parent, the bootstrap class loader. Therefore, the bootstrap class loader is always given the first chance to load a class. If the bootstrap class loader can’t find the class needed, the extension class loader will try to load the class. If the extension class loader also fails, the system class loader will perform the task. If the system class loader can’t find the class, a ClassNotFoundException is thrown. Why the round trip?
The delegation model is very important for security. As you know, you can use the security manager to restrict access to a certain directory. Now, someone with malicious intents can write a class called java.lang.Object that can be used to access any directory in the hard disk. Because the JVM trusts the java.lang.Object class, it
won’t watch its activity in this regard. As a result, if the custom java.lang.Object was allowed to be loaded, the security manager would be easily paralyzed. Fortunately, this won’t happen because of the delegation model. Here is how it works.
When the custom java.lang.Object class is called somewhere in the program, the system class loader delegates the request to the extension class loader, which delegates to the bootstrap class loader. The bootstrap class loader searches its core libraries, and finds the standard java.lang.Object and instantiates it. As a result, the custom java.lang.Object will never be loaded.
The great thing about the class loading mechanism in Java is that you can write your own class loader by extending the abstract java.lang.ClassLoader class.