Search code examples
javapluginsdependenciesclassloaderdependency-management

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


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?


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).