Under The Hood
backend java JDK 9+ (modules, Platform ClassLoader)

ClassLoader: Bootstrap, Platform, App & Parent Delegation

Last updated
Prerequisites:
Java class loading basics
Understanding of JVM startup and the classpath
  • java
  • classloader
  • bootstrap
  • platform
  • parent-delegation
  • jvm

Read at your depth

The practical view

The JVM loads classes with three built-in loaders: the Bootstrap ClassLoader (JDK core classes like java.lang, java.util — implemented natively, no parent), the Platform ClassLoader (JDK modules, previously called Extension), and the Application/System ClassLoader (your classpath). The parent-delegation model: when asked to load a class, a loader first asks its parent, and only tries to load it itself if the parent fails. This ensures core classes are always the JDK's version. Custom loaders (ClassLoader subclasses) can break delegation by overriding loadClass, useful for plugin systems and hot reload.

The same idea in other frameworks

react equivalent
N/A — JVM runtime concern.

Legacy vs modern

Classpath conflicts with multiple versions vs consistent delegation

Without delegation, two loaders could load different versions of the same class, breaking type identity; parent-first delegation guarantees one canonical version.

before → after
Duplicate class versions on the classpath
lib-a/lib/log4j.jar:1.2  lib-b/lib/log4j.jar:1.1  # ❌ OLD: two versions, chaos
Isolated custom classloaders for versioned plugins
class PluginLoader extends ClassLoader {
  // ✅ NEW: child-first for plugin libs, parent-first for JDK classes
}

Interview gotchas

Context

This tests the core delegation rationale — interviewers want the type-identity model and why breaking delegation causes ClassCastException, a classic debugging trap.

The mechanical answer

Parent-first delegation means loadClass asks the parent before searching its own namespace, so a class name resolves to the FIRST loader up the chain that can provide it — giving one canonical definition per class name in the hierarchy. Class identity in the JVM is (classloader, fully-qualified-name): two loaders that both load com.example.Foo define two DISTINCT types, even with identical bytecode. If a parent-loaded class references a class defined by a child loader and vice versa, casts between them fail with ClassCastException (or you get LinkageError on conflicting definitions). This is why plugin systems and app servers isolate each deployment with its own loader while delegating shared/JDK classes upward — the delegation boundary is exactly the type-identity boundary.

Trap

The naive answer is 'delegation prevents loading the same file twice'. It prevents two DIFFERENT loaders from defining the same name when a parent can provide it, which is about type identity, not file caching. Another trap: seeing ClassCastException and assuming a logic bug — it's often a loader mismatch (e.g. a class loaded by the app loader vs a child loader). Candidates who mention the (loader, name) identity tuple show real understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.