JarClassLoader contains logic that sets the thread context classloader before loading
commences. This logic fails when applications rely on the thread classloading.
An example is jetty, but presumably also other web applications. They create a WebAppContext
(or similar) with a particular class loader, and then call some initialize() method on the
context. First, however, they set the thread context classloader, so that the initialization()
code actually sees the proper (configured) class loader.
However, when JarClassLoader() forces itself as the Thread context classLoader, the logic
falls apart.
:::java
/*
* Override to ensure that this classloader is the thread context classloader
* when used to load a class. Avoids subtle, nasty problems.
*
/
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
// Set the context classloader in case any classloaders delegate to it.
// it would default to the sun.misc.Launcher$AppClassLoader which
// is used to launch the jar application, and attempts to load through
// it would fail if that code is encapsulated inside the one-jar.
Thread.currentThread().setContextClassLoader(this);
return super.loadClass(name, resolve);
}
Btw, the following might actually be enough to make things work, though I'm not entirely sure:
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(this);
return super.loadClass(name, resolve);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}