Fundamentals 16 min read

Understanding Java Class Loaders and the Parent Delegation Model

This article explains the Java class‑loading mechanism, reviews the load‑link‑initialize process, describes the built‑in Bootstrap, Extension and Application class loaders, introduces the parent‑delegation model, shows its execution flow with code examples, and discusses how to customize or break the model.

IT Services Circle
IT Services Circle
IT Services Circle
Understanding Java Class Loaders and the Parent Delegation Model

Review of the Class Loading Process

The JVM loads classes in three stages: Loading → Linking → Initialization . Linking itself consists of Verification → Preparation → Resolution . During loading, the binary byte stream of a class is obtained, transformed into runtime data structures, and a Class object is created in the method area.

Class Loader

What Is a Class Loader?

A class loader is an object responsible for loading classes. The abstract class ClassLoader defines the contract. Each loaded class has a reference to the loader that defined it, while array classes are created automatically by the JVM.

Loading Rules

When the JVM starts, it loads classes lazily – only when they are needed. If a class has already been loaded, the same ClassLoader instance returns the existing Class object; otherwise it attempts to load it.

public abstract class ClassLoader {
    private final ClassLoader parent;
    private final Vector
> classes = new Vector<>();
    // ... other members ...
    public final ClassLoader getParent() { return parent; }
}

Built‑in Class Loaders

BootstrapClassLoader (implemented in C++): loads core JDK libraries from %JAVA_HOME%/lib and any path specified by -Xbootclasspath .

ExtensionClassLoader : loads JARs from %JRE_HOME%/lib/ext and directories defined by java.ext.dirs .

AppClassLoader : loads classes from the application classpath.

All three inherit from ClassLoader . Since BootstrapClassLoader is part of the JVM, it appears as null in Java code.

Parent Delegation Model

Concept

Each ClassLoader has an associated parent. When asked to find a class or resource, it first delegates the request to its parent. The bootstrap loader has no parent and sits at the top of the hierarchy.

Execution Flow

The core logic resides in java.lang.ClassLoader.loadClass() :

protected Class
loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        Class
c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) { }
            if (c == null) {
                long t1 = System.nanoTime();
                c = findClass(name);
                // performance counters omitted
            }
        }
        if (resolve) resolveClass(c);
        return c;
    }
}

The loader first checks if the class is already loaded, then delegates to the parent. Only when the parent cannot find the class does the loader invoke findClass() (or a custom implementation) to load it itself.

Benefits

The model prevents duplicate loading, ensures that core API classes (e.g., java.lang.Object ) are loaded only by the bootstrap loader, and protects the integrity of the Java runtime.

Breaking the Delegation Model

Custom loaders can override findClass() to keep the delegation intact, or override loadClass() to bypass the parent entirely. Tomcat’s WebAppClassLoader does the latter to achieve web‑application isolation.

Example: Printing the Loader Hierarchy

public class PrintClassLoaderTree {
    public static void main(String[] args) {
        ClassLoader cl = PrintClassLoaderTree.class.getClassLoader();
        StringBuilder prefix = new StringBuilder("|--");
        while (cl != null) {
            System.out.println(prefix + cl);
            cl = cl.getParent();
            prefix.insert(0, "\t");
        }
        System.out.println(prefix + "null");
    }
}

Running on JDK 8 prints the hierarchy: AppClassLoader → ExtClassLoader → null (Bootstrap) .

Further Reading

"深入拆解 Java 虚拟机" (Deep Dive into the JVM)

Baeldung – Class Loaders in Java

Oracle Javadoc – ClassLoader

JavaJVMClassLoaderCustom ClassLoaderParent Delegation
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.