Java / JVM Architecture (Java21) Interview questions
How do you troubleshoot a memory leak caused by classloader references (classloader leaks)?
A classloader leak shows up as steadily growing Metaspace, or heap, usage across repeated operations that should be memory-neutral - most classically, redeploying a web application to the same application server without ever restarting the JVM, eventually producing OutOfMemoryError: Metaspace.
The root cause is that a ClassLoader, and every class plus their static fields that it loaded, cannot be garbage collected as long as any single live reference to that loader, one of its classes, or an instance of one of its classes exists anywhere in the JVM, including in code that has nothing to do with the old deployment.
- Reproduce and capture a heap dump using
jmap -dump, or automatically on OOM via-XX:+HeapDumpOnOutOfMemoryError, after triggering the suspected leaking operation a few times. - Analyze with a tool like Eclipse MAT, using its "duplicate classes" or classloader-leak report to spot multiple instances of the same class loaded by different, supposedly-retired classloaders.
- Follow the dominator tree / GC-roots path from a leaked classloader to find exactly what is still holding a reference to it - common culprits are an uncleared
ThreadLocal, a JDBC driver left registered inDriverManager, a thread pool or timer the old deployment created but never shut down, or a JDK-level cache likejava.beans.Introspector. - Fix at the source: deregister drivers and shut down thread pools or timers on application undeploy, call
ThreadLocal.remove()in cleanup code, and avoid ever storing an object created by the application's classloader in a cache owned by a classloader-neutral singleton.
Confirm the fix by repeating the redeploy cycle several times while watching Metaspace usage in GC logs - a fixed leak should show usage stabilizing instead of climbing with each cycle.
More Related questions...