JVM & Memory

99. ClassLoader Hierarchy and Dynamic Loading

Java loads compiled classes dynamically via a hierarchical ClassLoader delegation model (Bootstrap, Platform, Application), maintaining security, isolation, and modular runtime boundaries.

Java 21+ (JPMS integration)

Explanation

In Java, classes are loaded on-demand at runtime by instances of java.lang.ClassLoader. When code refers to a class for the first time, the JVM coordinates three phases: Loading (reading bytecode into memory), Linking (Verification, Preparation of static fields with defaults, and Resolution of symbolic references), and Initialization (executing static initializers <clinit> and static variable assignments).

The standard HotSpot ClassLoader hierarchy follows the parent-delegation model: 1. Bootstrap ClassLoader: Implemented in native C/C++ inside the JVM core. Loads base modules (java.base, java.logging) from the runtime image (jimage). Represented by null in Java reflection. 2. Platform ClassLoader (formerly Extension ClassLoader): Loads JDK extensions and optional platform modules (java.sql, java.compiler). 3. Application (System) ClassLoader: Loads classes from the application classpath (-cp) or modulepath (-p).

When a ClassLoader is asked to find a class, it delegates to its parent first. Only if all ancestor loaders fail to find the class does the child loader invoke its own findClass(name). This ensures system classes (like java.lang.String) cannot be overridden by malicious classpath classes. Application servers and plugin engines (OSGi, Spring Boot devtools) leverage custom class loaders to enable hot-reloading and dependency isolation.

Example

public class ClassLoaderHierarchy {
    public static void main(String[] args) {
        // 1. Application ClassLoader
        ClassLoader appLoader = ClassLoaderHierarchy.class.getClassLoader();
        System.out.println("App ClassLoader: " + appLoader);

        // 2. Platform ClassLoader
        ClassLoader platformLoader = appLoader.getParent();
        System.out.println("Platform ClassLoader: " + platformLoader);

        // 3. Bootstrap ClassLoader (returns null in Java API)
        ClassLoader bootstrapLoader = platformLoader.getParent();
        System.out.println("Bootstrap ClassLoader: " + bootstrapLoader + " (native core)");

        // 4. Core JDK class (loaded by Bootstrap)
        ClassLoader stringLoader = String.class.getClassLoader();
        System.out.println("String ClassLoader: " + stringLoader + " (Bootstrap)");

        // 5. Dynamic class loading with Class.forName
        try {
            Class<?> clazz = Class.forName("java.util.ArrayList");
            System.out.println("Dynamically loaded: " + clazz.getName() + 
                               " via " + clazz.getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Sources