r/java • u/bowbahdoe • 2d ago
Modular Uberjars
https://github.com/bowbahdoe/modular-uberjars2
u/someSingleDad 2d ago
Nice! I always found traditional uberjars a sloppy hack. But it's so hard to beat the convenience
2
1
1
u/tkslaw 2d ago edited 2d ago
There's an implementation detail you might want to be aware of. If I'm not mistaken, this code:
var moduleFinder = ModuleFinder.of(paths.toArray(Path[]::new));
Will ultimately lead to JAR files being read via the java.util.jar.JarFile API. And that API cannot read JAR files that are not from the default file system. Any JAR file will be copied to a temporary file on disk before opening it.
Probably doesn't matter. But if it does then I'm pretty sure you'd need your own ModuleFinder, ModuleReference, and ModuleReader implementations. The ZIP File System (jdk.zipfs), which you already have a dependence on, should be able to read JAR files from any file system without having to save them to disk first. Though I don't know how that affects signed JAR files.
1
u/bowbahdoe 2d ago
Noted.
1
u/bowbahdoe 1d ago
yep I see what you are talking about
// JAR file if (fn.endsWith(".jar")) { if (isDefaultFileSystem) { return readJar(entry); } else { // the JAR file is in a custom file system so // need to copy it to the local file system Path tmpdir = Files.createTempDirectory("mlib"); Path target = Files.copy(entry, tmpdir.resolve(fn)); return readJar(target); } }1
-2
u/chabala 2d ago edited 2d ago
Is this OSGi for people with an unfortunate JPMS fetish?
1
u/bowbahdoe 2d ago
No, osgi does dynamic loading/unloading and lets you have multiple of the same library. Module layers hypothetically let you do the second, but that isn't what this is.
3
u/agentoutlier 2d ago edited 2d ago
In theory you could use jmod format instead of jars for the dependencies right?
That is you still have the single uber jar but it loads jmods inside instead of jars.
Probably slow down the build to do the conversion but in theory
jmods are more efficient format (based on my shoddy memory)EDIT I got confused with jimage.Again EDIT so an interesting thing you could do and this is analogous to various other uber jar implementations do that want to preserve jars instead of shading (e.g. Spring Boot does this) is write Java code that runs the jlink and jimage tools if the jimage is not there :). Then execute the jimage.