Class loading is the first step in Java program execution. Understanding how classes are loaded provides insights into the JVM's operation and helps developers implement more efficient applications.
Another important reason to study class loading mechanisms is to enable dynamic control over class loading, such as hot deployment, which enhances applicaiton flexibility and adaptability.
1. Basic Process
Java programs run in memory. When executing the command 'java ExampleClass' from the command line,
the JVM loads the ExampleClass.class file into memory and creates a Class object called ExampleClass.class.
The class loading process follows these steps:
(1) Locate the JRE directory, find jvm.dll, and initialize the JVM;
(2) Create a Bootstrap Loader;
(3) The Bootstrap Loader automatically loads the Extended Loader and sets the Bootstrap Loader as its parent;
(4) The Bootstrap Loader automatically loads the System Class Loader and sets the Extended Loader as its parent;
(5) Finally, the System Class Loader loads the ExampleClass.
This represents the most common class loading process.
2. Loading Details
Each class loader searches specific directories:
Bootstrap Loader: Loads paths or JARs specified by System.getProperty("sun.boot.class.path").
Extended Loader (ExtClassLoader): Loads paths or JARs specified by System.getProperty("java.ext.dirs"). When running Java programs, you can also specify its search path,
for example: java -Djava.ext.dirs=d:\projects\testproj\classes ExampleClass
System Class Loader (AppClassLoader): Loads paths or JARs specified by System.getProperty("java.class.path"). When running Java programs, you can use -cp to override the original Classpath setting,
for example: java -cp ./myproject/classes ExampleClass
ExtClassLoader and AppClassLoader are preserved in the JVM after startup, and their search paths cannot be changed during program execution. To load classes from other search paths at runtime, new class loaders must be created.
3. Class Loader Characteristics
1. When running a program, the System Class Loader always begins by loading the specified class.
2. When loading classes, each class loader delegates the task to its parent first. If the parent cannot find the class, the loader attempts to load it itself.
3. The Bootstrap Loader is the top-level class loader, and its parent loader is null.
4. Obtaining Class Loaders
public class ExampleClass {
public static void main(String[] args) {
ExampleClass instance = new ExampleClass();
Class clazz = instance.getClass();
ClassLoader loader = clazz.getClassLoader();
System.out.println(loader);
System.out.println(loader.getParent());
System.out.println(loader.getParent().getParent());
}
}
Output:
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$ExtClassLoader@addbf1
null
The results show that we cannot obtain the parent of ExtClassLoader. This is because the Bootstrap Loader is implemented in C, and there's no defined way to return its parent loader, so it returns null.
5. Class Loading Methods
There are three ways to load classes:
1. Automatic loading by the JVM when starting an application from the command line
2. Dynamic loading using Class.forName() method
3. Dynamic loading using ClassLoader.loadClass() method
These methods differ significantly. Let's examine an example:
public class ExampleClass {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader loader = ExampleClass.class.getClassLoader();
System.out.println(loader);
// Using ClassLoader.loadClass() to load a class doesn't execute the initialization block
loader.loadClass("TestClass");
// Using Class.forName() to load a class executes the initialization block by default
//Class.forName("TestClass");
// Using Class.forName() to load a class with a specified ClassLoader,
// without executing the static block during initialization
//Class.forName("TestClass", false, loader);
}
}
public class TestClass {
static {
System.out.println("Static initialization block executed!");
}
}
Different output results will be observed when switching between loading methods.
An important point about ClassLoaders:
A class file loaded by the same ClassLoader has only one Class instance.
However, if the same class file is loaded by different ClassLoaders, there will be two different ClassLoader instances (proivded these two loaders don't share the same parent loader).