Understanding Java Class Loading, the Parent Delegation Model, and Tomcat’s Custom ClassLoaders
This article reviews Java’s default class loading mechanism and parent‑delegation model, explains how the model can be broken, and details Tomcat’s custom classloader architecture—including Common, Catalina, Shared, Webapp, and JSP loaders—showing why Tomcat deviates from the standard delegation hierarchy.
This article explains Java’s class loading mechanism, the parent‑delegation model, ways the model can be broken, and how Tomcat implements its own classloader hierarchy that intentionally violates the standard delegation rules.
1. What is the class loading mechanism?
The Java Virtual Machine loads class bytecode from .class files, verifies it, parses it, and initializes it so that the VM can use the resulting Java types. The component that performs the loading is called a java.lang.ClassLoader .
2. What is the parent delegation model?
From the JVM’s perspective there are two kinds of classloaders: the native Bootstrap ClassLoader and all other classloaders that inherit from the abstract class java.lang.ClassLoader . In practice developers encounter three system classloaders:
Bootstrap ClassLoader : loads core libraries from JAVA_HOME/lib (e.g., rt.jar ).
Extension ClassLoader : implemented by sun.misc.Launcher$ExtClassLoader , loads JARs from JAVA_HOME/lib/ext or the java.ext.dirs system property.
Application (System) ClassLoader : implemented by sun.misc.Launcher$AppClassLoader , loads classes from the application classpath.
Why use the model?
It guarantees that fundamental classes such as java.lang.Object are loaded by a single, trusted classloader, preventing multiple incompatible definitions of core types.
How is it implemented?
The delegation logic resides in java.lang.ClassLoader ’s loadClass method: it first checks if the class is already loaded, then delegates the request to the parent loader, and only if the parent fails does it attempt to find the class itself.
3. How can the parent delegation model be broken?
There have been three major ways to bypass the model:
Before JDK 1.2, the model did not exist.
When a parent loader cannot load a Service Provider Interface (SPI) implementation that resides in the application’s classpath, developers use the thread‑context classloader via java.lang.Thread.setContextClassLoader to load those classes.
For hot‑swap scenarios (e.g., JSP recompilation), a separate classloader is created for each generated class so that updating the source replaces the old loader with a new one.
4. Tomcat’s classloader design
Tomcat cannot rely on the default mechanism because a web container must isolate applications, share common libraries, keep container libraries separate, and support hot‑reloading of JSPs. Therefore Tomcat defines its own hierarchy:
commonLoader : loads classes from /common/* (or lib after Tomcat 6) and is visible to both the container and all web apps.
catalinaLoader : loads container‑only classes from /server/* , invisible to web apps.
sharedLoader : loads classes from /shared/* , visible to all web apps but not to the container.
WebappClassLoader : one instance per web application, loads classes from /WEB-INF/* and isolates them from other apps.
JasperLoader (JSP classloader): created per JSP file; when the JSP changes, the old loader is discarded and a new one is instantiated to achieve hot‑swap.
Because Tomcat’s WebappClassLoader does not delegate to its parent for classes under /WEB-INF , it intentionally violates the parent delegation principle to achieve isolation and independent versioning of libraries.
In summary, Tomcat’s custom classloader hierarchy breaks the standard parent‑delegation model to provide application isolation, shared libraries, and hot‑reloading capabilities.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.