Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expand the module path at runtime

I like services. I also like the module system. Unfortunately for me, before I used Java 9 I got in the habit of getting service providers from jars loaded at runtime via URLClassLoader, something like this (I'll use Java 10's var for brevity):

var url = new File("myjar.jar").toURI().toURL();
var cl = new URLClassLoader(new URL[] {url}, getClass().getClassLoader());
var services = ServiceLoader.load(MyService.class, cl);
for (var service : services) {
  ...
}

This works fine, even in Java 9 and beyond, but it loads the jar on the classpath, which means that it uses the old META-INF\services method to find service providers. I would rather use the module-info method, but that requires the jar to be loaded on the module path instead, but I couldn't find any way I might go about doing that. So here I am, hoping someone here who understands the module system more thoroughly will tell me how this can be done (or that it can't, if such is the case).

like image 719
Anonymous Avatar asked Jan 17 '19 02:01

Anonymous


People also ask

Where is Java module path?

$JAVA_HOME/jmods is the directory containing java. base. jmod and the other standard and JDK modules. The directory mlib on the module path contains the artifact for module com.

What is Module Path Java?

A CLASSPATH is a sequence of classes' base paths and JAR files for the Java Compiler or JVM to locate the classes used in the application. Similarly, in JDK 9, a MODULEPATH is a sequence of modules' base paths and Modular JAR files for the Java Compiler or JVM to locate the modules used in the application.

Why use Java modules?

Modules have taken so long because it makes fundamental changes to the way Java has worked since 1.0, and allows Java to move forward. It also allows Java to maintain compatibility while getting rid of legacy baggage (anyone still using RMI and Corba?).


1 Answers

The smallest working example, I could assemble, is

var path = Path.of("myjar.jar");
var cl = new URLClassLoader(new URL[]{path.toUri().toURL()});
var mf = ModuleFinder.of(path);
var cfg = Configuration.resolve(mf, List.of(ModuleLayer.boot().configuration()), mf, Set.of());
var ml = ModuleLayer.defineModulesWithOneLoader(cfg, List.of(ModuleLayer.boot()), cl).layer();
var services = ServiceLoader.load(ml, MyService.class);
services.forEach(System.out::println);

Assuming myjar.jar is a modular jar declaring to provide MyService implementations.

like image 196
Holger Avatar answered Oct 03 '22 19:10

Holger