Why is it so hard to do this in Java? If you want to have any kind of module system you need to be able to load JAR files dynamically. I\'m told there\'s a way of doing it b
In case anyone searches for this in the future, this way works for me with OpenJDK 13.0.2.
I have many classes that I need to instantiate dynamically at runtime, each potentially with a different classpath.
In this code, I already have an object called pack, that holds some metadata about the class I am trying to load. The getObjectFile() method returns the location of the class file for the class. The getObjectRootPath() method returns the path to the bin/ directory containing the class files that include the class I am trying to instantiate. The getLibPath() method returns the path to a directory containing the jar files constituting the classpath for the module the class is a part of.
File object = new File(pack.getObjectFile()).getAbsoluteFile();
Object packObject;
try {
URLClassLoader classloader;
List classpath = new ArrayList<>();
classpath.add(new File(pack.getObjectRootPath()).toURI().toURL());
for (File jar : FileUtils.listFiles(new File(pack.getLibPath()), new String[] {"jar"}, true)) {
classpath.add(jar.toURI().toURL());
}
classloader = new URLClassLoader(classpath.toArray(new URL[] {}));
Class> clazz = classloader.loadClass(object.getName());
packObject = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return packObject;
I was using the Maven dependency: org.xeustechnologies:jcl-core:2.8 to do this before, but after moving past JDK 1.8, it sometimes froze and never returned being stuck "waiting for references" at Reference::waitForReferencePendingList().
I am also keeping a map of class loaders so that they can be reused if the class I am trying to instantiate is in the same module as a class that I have already instantiated, which I would recommend.