Alternative to fatJar - modular solution?
Ioi Lam
ioi.lam at oracle.com
Sat Oct 9 06:19:27 UTC 2021
A module can indicate its main class by setting the ModuleMainClass
attribute in its module-info.class. This can be done by running with
"jar --main-class=xxx" when creating a modular JAR file.
The module system allows you to enumerate all the modules in a
ModuleLayer. For each module, you can call
java.lang.module.ModuleDescriptor::mainClass() to find out the main class.
The module system provides many other ways for inspecting the modules. E.g.,
- You can iterate over all the packages of a module with
java.lang.Module::getPackages().
- You can iterate over all the contents (classfiles, resources, etc)
using java.lang.module.ModuleReader::list().
Given the introspection support of the module system, I am not sure why
there's a need to scan all the class. But if there's a need to do that,
we can probably do it as efficient as SprintBoot can today with
non-modularized Uber-JARs (my extremely slow inefficient implementation
of uber: protocol notwithstanding).
I would go out on a limb and say that using modularized Uber-JARs can be
as efficient as using "java --module-path=modulesdir". If all the
contents of the Uber-JAR are uncompressed, the contents of the embedded
JAR files can be accessed with DirectBuffer, etc.
Note:
- I am not pro or against using Uber-JARs for modularized apps
- All I am saying is -- if this is the direction one wants to go, there
doesn't seem to be a performance barrier for doing so. And the Java core
API already has the underpinnings for a possible implementation.
Thanks
- Ioi
On 10/8/21 9:34 PM, Samuel Audet wrote:
> One problem is that frameworks like Spring Boot need to scan the
> classes that are available in a module, to get a list of the names of
> all the classes, among other things. The JDK provides no standard way
> to do that. For example, how would you implement a class like this one?
>
> https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java
> <https://urldefense.com/v3/__https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java__;!!ACWV5N9M2RV99hQ!YbVLiZRxgAhtRJbb20kgZBxN1NdNgoJThcrTXFWAToYem9oFPXJDIgKJQVzd6A$>
>
> Samuel
>
> On Sat, Oct 9, 2021, 10:21 Ioi Lam <ioi.lam at oracle.com
> <mailto:ioi.lam at oracle.com>> wrote:
>
> As a proof of concept, I wrote a quick-and-dirty demo that can load
> Jigsaw modules from a Uber-JAR file:
>
> https://github.com/iklam/tools/tree/main/jigsaw/uberjar
> <https://urldefense.com/v3/__https://github.com/iklam/tools/tree/main/jigsaw/uberjar__;!!ACWV5N9M2RV99hQ!YbVLiZRxgAhtRJbb20kgZBxN1NdNgoJThcrTXFWAToYem9oFPXJDIgLt6Q8uqw$>
>
> Glavo, would something like this fit your needs?
>
> I think something like this could be done outside the JDK (in
> frameworks
> like SpringBoot) or inside the JDK (as some sort of extension to
> "java
> -jar", for example).
>
> As the demo shows, we already have the core API support to enable
> this.
> I would encourage other member of the Java community to experiment
> with
> it and see if we should proceed further in this direction.
>
> Thanks
> - Ioi
>
> On 10/7/21 9:31 PM, Ioi Lam wrote:
> > I am wondering if there are 3rd party solutions that support
> loading
> > Jigsaw modules from uber jars. The JDK should have all the APIs to
> > support such a solution.
> >
> > E.g., I looked at SpringBoot, which has uber jar support, but it
> > doesn't seem to support modules ("java.lang.module" doesn't
> appear in
> > any of the source files).
> >
> > Thanks
> > - Ioi
> >
> > On 10/7/21 6:43 AM, Gregg Wonderly wrote:
> >> The URL class loader is the easiest way to solve conditional
> >> loading. In Jini, now Apache River, we’ve long used this
> mechanism
> >> to “get” the implementation of all interfaces that a remote client
> >> application needed to talk to a particular server (versioning
> makes
> >> this necessary and powerfully easy as a solution). But the
> security
> >> manager didn’t seem useful as of late and the removal of the
> security
> >> manager support for managing per jar security is a bit problematic
> >> for this kind of mobile code use in Java. Yet, this is the
> primary
> >> way that javascript works in the web browser as the mobile code
> >> interface to remote services. It really feels like Oracle and the
> >> Java team have no interest in what the desktop environment
> represents…
> >>
> >> Gregg Wonderly
> >>
> >>> On Oct 7, 2021, at 7:41 AM, Glavo <zjx001202 at gmail.com
> <mailto:zjx001202 at gmail.com>> wrote:
> >>>
> >>>> *Bandwidth optimization and rare machines.* This is interesting
> >>>> because
> >>>> it's a requirement that feels like it may be more common in
> China than
> >>>> elsewhere. I'd be keen to learn more about your bandwidth
> constraints,
> >>>> unless this is more of a theoretical concern?
> >>>
> >>> Ah, in fact, in Chinese mainland, server bandwidth is a very real
> >>> problem. In China, many websites such as GitHub and cloudflare
> cannot
> >>> provide services normally. The cost of civil broadband is low, but
> >>> commercial bandwidth is more expensive, which costs several
> times or
> >>> even more than ten times higher than other parts of the world.
> >>> Our average income level also lags behind that of developed
> countries,
> >>> so we will pay more attention to the cost of bandwidth.
> >>>
> >>> Mike Hearn <mike at plan99.net <mailto:mike at plan99.net>>
> 于2021年10月7日周四 下午7:31写道:
> >>>
> >>>> Thanks for your insightful reply, Glavo. Here are some
> thoughts. I
> >>>> should
> >>>> note that I don't work for Oracle or on OpenJDK, in case that
> wasn't
> >>>> already clear.
> >>>>
> >>>> *Forum.* Although it's logical that you ended up on this list,
> >>>> realistically the JPMS is "done" and not being worked on
> since Java
> >>>> 9. Any
> >>>> solutions or improvements have to come from the user
> community so
> >>>> it may
> >>>> make more sense to have this discussion on Reddit, or some other
> >>>> Java forum.
> >>>>
> >>>> *Alternative approach. *Given this constraint, it can make
> sense to
> >>>> think
> >>>> wider or bigger than just updating previous approaches. Would
> your
> >>>> needs be
> >>>> met or even met better by a re-imagining of Web Start, but one
> >>>> suitable for
> >>>> servers and the CLI? For example:
> >>>>
> >>>> $ alias glavos="jrun glavos-cool-app.com
> <https://urldefense.com/v3/__http://glavos-cool-app.com__;!!ACWV5N9M2RV99hQ!YbVLiZRxgAhtRJbb20kgZBxN1NdNgoJThcrTXFWAToYem9oFPXJDIgK30k-y9g$>"
> >>>> $ glavos --flag --another-flag
> >>>>
> >>>> Here an imaginary "jrun" command (re)downloads an app and
> stores it
> >>>> to a
> >>>> local cache, perhaps downloading an appropriate JVM/jlinked
> image
> >>>> alongside
> >>>> it if none is available already locally. It's given a URL but
> in a
> >>>> convenient form for typing, e.g. with assumed protocols and
> paths
> >>>> if only a
> >>>> domain name is specified. The tool would occasionally check for
> >>>> updates and
> >>>> run from the cache the rest of the time. This doesn't make
> apps into a
> >>>> single file but it tackles other problems you mention having to
> >>>> roll your
> >>>> own solutions for, like writing your own update checker and
> asking
> >>>> users to
> >>>> download the right file. Unlike tools like apt-get or brew there
> >>>> would be
> >>>> no notion of adding a repository beforehand, so for CLI / server
> >>>> apps, it
> >>>> retains its usability.
> >>>>
> >>>> For desktop apps a simple .jrun file association could be
> used to
> >>>> do the
> >>>> same thing.
> >>>>
> >>>> For building Docker images you could have:
> >>>>
> >>>> $ jrun --cache-only glavos-cool-app.com
> <https://urldefense.com/v3/__http://glavos-cool-app.com__;!!ACWV5N9M2RV99hQ!YbVLiZRxgAhtRJbb20kgZBxN1NdNgoJThcrTXFWAToYem9oFPXJDIgK30k-y9g$>
> >>>>
> >>>> which would populate a cache during the docker build, but not
> run the
> >>>> program itself.
> >>>>
> >>>> I've often wished for such a tool. At one point I built one that
> >>>> did Maven
> >>>> resolution, but it for GUI apps. Although my new venture is about
> >>>> self-updating desktop/server app packages, I've been planning an
> >>>> extension
> >>>> in this direction later because once you can distribute a
> generic
> >>>> runtime
> >>>> as a self-updating "app" you can easily bring back the JRE model
> >>>> for those
> >>>> who want it.
> >>>>
> >>>> *Jimage.* In your first mail you proposed a new kind of fat-jar
> >>>> based on
> >>>> the jimage format the modules file uses. JImage isn't a
> documented
> >>>> format,
> >>>> or rather, it's documented only in the source code, but it
> has quite a
> >>>> clever design. The upside is that it's highly optimized. The
> >>>> downsides are:
> >>>>
> >>>> 1. Write only. ZIPs have some basic support for editing but
> jimage
> >>>> doesn't. This is a pain for things like config files, where
> you may
> >>>> want to
> >>>> make specialized versions of an app by adjusting the internal
> >>>> files. It can
> >>>> be easily fixed using a classloader that checks local disk for
> >>>> resources
> >>>> first.
> >>>>
> >>>> 2. No built-in support for native code libraries. There was a
> related
> >>>> discussion of this problem a week or so ago on this list. Of
> >>>> course, JARs
> >>>> have the same problem.
> >>>>
> >>>> 3. No support for multiple versions of the same JAR in the same
> >>>> file, even
> >>>> though the core JPMS *can* support this via the
> >>>> defineModulesWithManyLoaders API, and even though this would
> be a very
> >>>> useful thing to support. Fat JARs have the same problem so
> this is
> >>>> not a
> >>>> downside compared to the status quo.
> >>>>
> >>>> 4. The format is deliberately undocumented so it can be
> changed in
> >>>> future
> >>>> JVM versions. Thus using it would actually mean cloning it,
> and/or
> >>>> rewriting parts of the code because otherwise the GPL2 might
> kick in.
> >>>>
> >>>> Overall, the downsides are not that big! The worst is the
> need to
> >>>> clone
> >>>> the format to avoid depending on JVM internals. On the other
> hand,
> >>>> ZIPs
> >>>> work well enough and don't require writing any new code except a
> >>>> little
> >>>> stub entry point that uses custom classloaders.
> >>>>
> >>>> *Bandwidth optimization and rare machines.* This is interesting
> >>>> because
> >>>> it's a requirement that feels like it may be more common in
> China than
> >>>> elsewhere. I'd be keen to learn more about your bandwidth
> constraints,
> >>>> unless this is more of a theoretical concern?
> >>>>
> >>>> You mention you actually have users on LoongArch64 for example.
> >>>> Indeed,
> >>>> the chances that non-Chinese developers will produce jlinked
> images
> >>>> for
> >>>> this CPU any time soon is very low.
> >>>>
> >>>> *Product potential.* As mentioned, I'm setting up a new venture
> >>>> that is
> >>>> starting with app distribution, and particularly distribution
> for
> >>>> the JVM
> >>>> world. JPackage is good as far as it goes, but it doesn't
> solve all
> >>>> the
> >>>> problems developers face. Given your list of target machines it
> >>>> feels like
> >>>> you're probably a commercial organization with a wide customer
> >>>> base. If
> >>>> you're in the market for better approaches please send an
> email to
> >>>> mike at hydraulic.software and maybe your needs can influence
> our product
> >>>> direction.
> >>>>
> >>>>
> >>>>
> >
>
More information about the jigsaw-dev
mailing list