0

I'm using Java's ServiceLoader to load plugins into my app. The plugins are provided as JARs on the classpath when starting the app. Now, if these plugins contain classes or resources with the same name, there may be conflicts.

Thus, what's the proper way to load plugins via ServiceLoader in an isolated way, so that

  • plugin A cannot "see" the classes / resources of plugin B after loading them into the app
  • the app can use the same dependency as a plugin does, but in a different version (i.e the plugin's dependencies do not leak into the app)

Is it as easy as passing a custom classloader (that's based on the app's classloader) to ServiceLoader.load()? Can anyone provide a concrete example?

sschuberth
  • 28,386
  • 6
  • 101
  • 146
  • Yes, passing a new ClassLoader should suffice. For example, `new URLClassLoader(new URL[] { Path.of("/path/to/jarfile").toUri().toURL() })` – VGR Mar 31 '23 at 15:30
  • Does that mean the plugin JAR must not be on the classpath when running the app (like any other dependency), but the app must load it manually via an `URLClassLoader`? – sschuberth Mar 31 '23 at 20:33
  • Your first statement is correct: it should not be on the classpath. However, the application doesn’t need to load it manually; that’s the job of the ServiceLoader. – VGR Mar 31 '23 at 20:35
  • Right. But in order for the `ServiceLoader` to load the JAR successfully, it'd need to be a "fat JAR" that bundles all dependent JARs, right? At least I guess that would make loading simpler. – sschuberth Apr 01 '23 at 08:09
  • 1
    The `URLClassLoader`’s constructor accepts an array of `URL` instances, so why should there be a need to create a “fat jar”? – Holger May 30 '23 at 12:57
  • I guess it depends on how you organize your JARs on the filesystem. If you have one directory per plugin JAR plus its dependencies, then yes, you can probably just iterate over the files in that directory and load them all via one `URLClassLoader`. – sschuberth May 30 '23 at 13:48

0 Answers0