Each Java Class
is loaded by a ClassLoader
. Once a class has been loaded, it is impossible to unload this class from a class loader. The only possibility of getting rid of a class is to loose all references to all instances of classes that this class loader has loaded and to the reference to the classloader itself.
Class loader's are organized in a hierarchy. By default, each class loader first asks its parent class loader to load a class. Only if the parent class loader is unable to load a class, the original class loader will attempt to do so. You could override this behavior in order to load your JAXB classes.
This is not that easy though: Assume you have a class MyObject
that was loaded with class loader A. If you load the same class with class loader B then MyObject.class != MyObject.class
for the two classes. This would also cause MyObject o = getMyObjectFromOtherClassLoader()
to throw a ClassCastException
.
Stackoverflow provides an example of a child first class loader. The only thing remaining is to run your application without classes being loaded before the class loader gets active. This, you could do as follows (unverified code):
class StartupWrapper {
public static void main(String[] args) throws Exception {
Class.forName("com.company.Main", true,
new ParentLastURLClassLoader(Arrays.asList(new URL("./new-JAXB.jar"))))
.getMethod("main", String[].class).invoke(null, args);
}
}
This wrapper would start your normal application's public static void main(String[])
method of the class com.company.Name
using the child-first class loader that considers your library first. Make sure that you do not load com.company.Main
before your explicit load. (Thus the reflective approach.)
Are you using a build tool like Maven? Can't you explicitly exclude the old library's dependeny? The legacy application will probably have similar problems with the new JAXB as your application has with the old one.