I have an application that loads jar files in runtime dynamically using the following solution:
File file = ...
URL url = file.toURI().toURL();
URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, url);
This was done using the answer at How to load JAR files dynamically at Runtime?
I now want a solution that works JDK11+ that is equivalent to the original solution I used. Thus doing it programmatically without the need for third-party libraries/frameworks or loading/invoking single classes.
I tried the following:
- Created a DynamicClassLoader that extends the UrlClassLoader:
public final class DynamicClassLoader extends URLClassLoader {
public DynamicClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public DynamicClassLoader(String name, ClassLoader parent) {
super(name, new URL[0], parent);
}
public DynamicClassLoader(ClassLoader parent) {
this("classpath", parent);
}
public void addURL(URL url) {
super.addURL(url);
}
}
- I then start my application wit java.system.class.loader flag:
java -Djava.system.class.loader=com.example.DynamicClassLoader
Then I have a jar file as a path object which I call with the following method:
public void loadJar(Path path) throws Exception {
URL url = path.toUri().toURL();
DynamicClassLoader classLoader = (DynamicClassLoader)ClassLoader.getSystemClassLoader();
Method method = DynamicClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, url);
}
When this method is called I get the following cast class exception:
class jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to class com.example.classloader.DynamicClassLoader (jdk.internal.loader.ClassLoaders$AppClassLoader is
in module java.base of loader 'bootstrap'; com.example.classloader.DynamicClassLoader is in unnamed module of loader 'app')
I am using Spring Boot (2.4) on OpenJDK11 (build 11.0.10+9).