How do I make the java ClassLoader aware of available classes?

classloader, dependencies, dependency-management, java, plugins

Solution

You need to use your main application's classloader as a parent:

ClassLoader mainLoader = ThisClass.class.getClassLoader(); // some class in the main application
ClassLoader pluginLoader = URLClassLoader.newInstance(new URL[]{jarFile.toURL()}, mainLoader);

Then classes loaded by the plugin classloader will have access to classes loaded by the main classloader (as well as that classloader's parent, if it has one, and so on).

Problem

I am trying to create Java plugins for an existing application. The plugins would like to re-use a lot of the already existing code-base in the main application (e.g. logging, error handling, etc). I am trying to load plugins as `.jar` files like this: ``` String localPath = "..."; String pluginName = "..."; File jarFile = new File(localPath); ClassLoader pluginLoader = URLClassLoader.newInstance(new URL[]{jarFile.toURL()}); pluginLoader.loadClass(pluginName).newInstance(); ``` The problem I am having is that the classes I would like to import inside the plugin can not be found, even though they exist in the main app, I am getting errors like this: ``` NoClassDefFoundError: com/foo/exception/FooException at com.foo.plugins.PluginManager.loadPlugin(PluginManager.java:187) at com.foo.plugins.PluginManager.loadPlugins(PluginManager.java:86) ... ``` `com/foo/exception/FooException` is used everywhere in the code, but I didn't want to have to include this class (and many many others) in the plugin jar file. Instead I would like the `ClassLoader` to somehow be aware of the locally existing classes. Is this possible? If so, how can I do it?

Original source