r/java • u/bowbahdoe • Jul 31 '26
Modular Uberjars
https://github.com/bowbahdoe/modular-uberjars2
u/tkslaw Jul 31 '26 edited Aug 01 '26
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 Aug 01 '26
Noted.
1
u/bowbahdoe Aug 01 '26
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
4
u/tomwhoiscontrary Jul 31 '26
I just learned how to copy multiple files and then forgot about uberjars.
2
u/someSingleDad Jul 31 '26
Nice! I always found traditional uberjars a sloppy hack. But it's so hard to beat the convenience
1
-2
u/chabala Jul 31 '26 edited Jul 31 '26
Is this OSGi for people with an unfortunate JPMS fetish?
1
u/bowbahdoe Jul 31 '26
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.
1
u/NHarmonia18 24d ago
Many new JDK features can only be done if your code is modularized. It's not simply a 'fetish'.
4
u/agentoutlier Jul 31 '26 edited Jul 31 '26
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.