Hook: Think of Java class loading like a building with three security desks: the front lobby, the staff desk, and your team’s desk.
Question: What are Bootstrap, Platform, and Application ClassLoaders?
Answer: These are the main built-in class loaders in the JVM. The Bootstrap ClassLoader loads the core Java runtime classes, the Platform ClassLoader loads standard JDK classes outside the core, and the Application ClassLoader loads your application classes from the classpath or module path. In modern Java, they form a parent chain, so a loader asks its parent first before trying to load a class itself.
Interview-Ready Answer: I think of the three default loaders as a parent chain: Bootstrap at the top, then Platform, then Application. Bootstrap is the root loader implemented inside the JVM and it loads core JDK classes like java.lang.String; Platform loads the JDK’s non-core platform modules; Application, also called the system loader, loads my app’s classes. A nice detail is that String.class.getClassLoader() returns null, which really means bootstrap loaded it.
Detailed Explanation: A class loader is the part of the JVM that finds bytecode and turns it into a Class object. The default loaders are arranged in a parent-first chain. That parent-first rule is called delegation, meaning a loader tries its parent before defining the class itself.
null.ClassLoader.getSystemClassLoader().(class name, class loader) identifies the type. This is why two classes with the same fully qualified name can still be treated as different types if they came from different loaders.| Loader | Main job | Java 8 name | API clue |
|---|---|---|---|
| Bootstrap | Core JDK | Same idea | null parent |
| Platform | JDK modules | Extension | getPlatformClassLoader() |
| Application | Your app | System | getSystemClassLoader() |
They want to see whether you know the JVM loading order, the Java 9 module split, and the most common bug: assuming every class has a visible loader. It also checks whether you understand that loading is separate from access control. A class can be found by a loader and still be blocked later by the module system or by visibility rules.
null from getClassLoader(). That also happens for primitive types like int.null.“Core first, platform second, app last.” If you remember that order, you can reconstruct the whole hierarchy under pressure.
Real-World Story: Imagine a checkout service that loads payment plugins from third-party jars. The core payment code lives in the application loader, while a shared JSON library is also present in the app. A plugin accidentally bundles a different version of that same library.
The symptom is often a confusing error like ClassCastException: com.example.JsonMapper cannot be cast to com.example.JsonMapper. Logs show the same class name twice, but one came from the app loader and the other from the plugin loader. Users experience failed payments, retries, or a partial outage because the plugin cannot be wired into the main service.
The lesson: in Java, “same name” is not enough. The class loader is part of the type identity.
import java.util.Objects;
public class BootstrapPlatformApplicationClassLoadersDemo {
// This nested class is loaded by the application class loader in a normal run.
static class LocalType {
}
public static void main(String[] args) {
System.out.println("=== Default class loader chain ===");
printLoader("Application/System loader", ClassLoader.getSystemClassLoader());
printLoader("Platform loader", ClassLoader.getPlatformClassLoader());
printLoader("Bootstrap loader", null);
System.out.println();
System.out.println("=== Which loader loaded each class? ===");
printClassLoader(String.class); // bootstrap -> null
printClassLoader(LocalType.class); // application loader
printClassLoader(int.class); // primitive -> no loader
printClassLoader(String[].class); // array of bootstrap type -> null
printClassLoader(LocalType[].class); // array of app type -> app loader
System.out.println();
System.out.println("=== Delegation and failure path ===");
ClassLoader app = ClassLoader.getSystemClassLoader();
tryLoad(app, "java.lang.String"); // succeeds because app delegates upward
tryLoad(app, "no.such.Class"); // expected failure path
System.out.println();
System.out.println("=== Quick sanity checks ===");
System.out.println("App parent is platform: " + (app.getParent() == ClassLoader.getPlatformClassLoader()));
System.out.println("Platform parent is bootstrap (null): " + (ClassLoader.getPlatformClassLoader().getParent() == null));
}
private static void printLoader(String label, ClassLoader loader) {
System.out.printf("%-30s -> %s%n", label, loaderName(loader));
}
private static void printClassLoader(Class<?> type) {
System.out.printf("%-30s -> %s%n", type.getTypeName(), loaderName(type.getClassLoader()));
}
private static void tryLoad(ClassLoader loader, String className) {
try {
Class<?> clazz = loader.loadClass(className);
System.out.printf("Loaded %-22s via %s%n", clazz.getName(), loaderName(clazz.getClassLoader()));
} catch (ClassNotFoundException ex) {
System.out.printf("Could not load %-16s -> %s%n", className, ex.getClass().getSimpleName());
}
}
private static String loaderName(ClassLoader loader) {
if (loader == null) {
return "bootstrap";
}
return loader.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(loader));
}
}Follow-up & Tricky Questions:
String.class.getClassLoader() return null? Because String is loaded by the bootstrap loader, which is not exposed as a normal Java object, so the API uses null to mean bootstrap.URLClassLoader? No. That was often true in older JDKs, but you should not depend on the concrete implementation in modern Java.ClassLoader instance? No. It is implemented in the JVM, and Java code typically observes it as null.null class loader mean the class failed to load? No. It usually means the class was loaded by bootstrap, especially for core JDK classes and primitive-related cases.Common Mistakes:
null usually means the bootstrap loader, not the absence of loading.Memory Hook: Core first, platform second, app last. Picture three desks in a building: the lobby guards the base rules, the middle desk handles standard staff tools, and your team desk handles your project files.
Cheat Sheet:
null.Practice Tasks:
bootstrap, platform, or application.ClassLoader.getSystemClassLoader().getParent() and explain why that parent is important.