I want to load and reload a service provider in a jar which is a module. It is my understanding that this can be achieved by loading the module in a new ModuleLayer
.
Following the advice in this answer and the example in the docs, I have succeeded in loading the module at runtime and using the service provider.
var finder = ModuleFinder.of(Path.of("/path/to/module/"));
var bootLayer = ModuleLayer.boot();
var pluginLayer = bootLayer.defineModulesWithOneLoader(
bootLayer.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp")),
ClassLoader.getSystemClassLoader());
ServiceLoader.load(MyService.class, pluginLayer.findLoader("myapp"))
.findFirst()
.ifPresentOrElse(
__ -> System.out.println("Found provider."),
() -> System.out.println("Couldn't find provider."));
The only thing I am unsure about is how I should go about eventually unloading the module and reloading a new version of it. The linked answer says that the unloading happens when the ModuleLayer
is GC'd. With some testing, I have confirmed this, though this feels very finicky. Obviously, I cannot control exactly when the layer will be garbage collected, even once it is unreachable.
What would be the best approach for allowing quick reloading of the module?