This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

Question: How do I load JAR files dynamically at run time?

Why is this requirement so difficult to implement in Java? If you want to use any type of modular system, you need to be able to load JAR files dynamically. I’ve been told that there is a way to do this by writing your own ClassLoader method. But it was a lot of work, and I expected it to be as simple as adding a parameter.

Answer 1:

The reason it’s hard is security. Class loaders are immutable. You should not randomly add classes to it at run time. In fact, I was surprised that the system classloader could be used this way. Here’s how to make your own subclass loader:

URLClassLoader child = new URLClassLoader(
        new URL[] {myJar.toURI().toURL()},
        this.getClass().getClassLoader()
);
Class classToLoad = Class.forName("com.MyClass".true, child);
Method method = classToLoad.getDeclaredMethod("myMethod");
Object instance = classToLoad.newInstance();
Object result = method.invoke(instance);
Copy the code

Answer 2:

The following solution is somewhat shocking because it uses reflection to bypass encapsulation, but it works perfectly:

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);
Copy the code

Answer 3: What about the framework for the JCL class loader? I have to admit, I haven’t used it, but it looks promising.

Usage Examples:

JarClassLoader jcl = new JarClassLoader();
jcl.add("myjar.jar"); // Load jar file  
jcl.add(new URL("http://myserver.com/myjar.jar")); // Load jar from a URL
jcl.add(new FileInputStream("myotherjar.jar")); // Load jar file from stream
jcl.add("myclassfolder/"); // Load class folder  
jcl.add("myjarlib/"); // Recursively load all jar files in the folder/sub-folder(s)

JclObjectFactory factory = JclObjectFactory.getInstance();
// Create object of loaded class  
Object obj = factory.create(jcl, "mypackage.MyClass");
Copy the code