Live data from Hacker News

Using jlink to cross-compile minimal JREs

jakewharton.com

21–30 of 66 posts

Re: Using jlink to cross-compile minimal JREs

#22

It's a pity that system wide JREs are not a thing anymore. I understand that it was difficult to get an updated JRE on the system in the early 2000s, but nowadays almost every computer is online - certainly one where you are currently downloading an application on - and automatic updates are commonplace. You used to be able to just double click on a .jar, and that was a Java application. And it would be trivial engin…

We already have that, it's called a package manager. The concept has a number of problems (multiple runtime versions for multiple programs, who pays for and controls the repository, etc etc).

Re: Using jlink to cross-compile minimal JREs

#23
You don't need to run jlink yourself to avoid shipping the entire JDK. Here's a java19 runtime docker image at 62MB: https://hub.docker.com/_/eclipse-temurin/tags?page=1&name=19...

Not customizing the runtime per build or per app also potentially helps reuse of docker image layers across your container registries and clusters.

Re: Using jlink to cross-compile minimal JREs

#24
post #10

These days, all Java runtimes are created with jlink, including the one that's bundled in the JDK, so it's worth it to take a few minutes to learn how to do it yourself for a custom image. The result is not only drastically smaller, but more secure, as the potential attack surface area is much smaller. If your application is modularised, it can become a part of the image, but, as the article shows, creating a custom…

How is modularization progressing in practice?

Stuff like Hibernate, Spring, the big libraries.

How easy is it for the average greenfield enterprise to start as a modular app?

How easy is it for the average brownfield enterprise app started 10 years ago to convert to a modular app?

Re: Using jlink to cross-compile minimal JREs

#25

You don't need to run jlink yourself to avoid shipping the entire JDK. Here's a java19 runtime docker image at 62MB: https://hub.docker.com/_/eclipse-temurin/tags?page=1&name=19... Not customizing the runtime per build or per app also potentially helps reuse of docker image layers across your container registries and clusters.

You're adding the whole of Docker as a dependency if you do that.

Not everyone wants that.

Re: Using jlink to cross-compile minimal JREs

#26

JLink is a pretty nice tool - easy to use and understand, relatively fast, big app size wins. A few misc thoughts: Figuring out what modules you need to ship can be done with the jdeps tool, but, you have to watch out for some gotchas. One is that you have to run it on each JAR or set of jars. It's slow so it helps to do this incrementally. Another is that some critical JVM functions are implemented as 'plugins' that…

I know that you're hawking your own software, but it looks quite cool. However, I wouldn't want to be a pioneer. Who uses it and for what? Do you have testimonials?

Or maybe other HNers, have you used it?

Re: Using jlink to cross-compile minimal JREs

#27
post #5
post #4

Earlier quoted context omitted.

No. You are thinking of GraalVM native image which will compile java to native machine code. jlink is more similar to tree shaking: it strips the JRE of anything your program don't need.

But I think the parent's point is given reflection, how can jlink statically know the complete set of classes that your program needs?

[deleted]

Re: Using jlink to cross-compile minimal JREs

#28
post #24
post #10

These days, all Java runtimes are created with jlink, including the one that's bundled in the JDK, so it's worth it to take a few minutes to learn how to do it yourself for a custom image. The result is not only drastically smaller, but more secure, as the potential attack surface area is much smaller. If your application is modularised, it can become a part of the image, but, as the article shows, creating a custom…

How is modularization progressing in practice? Stuff like Hibernate, Spring, the big libraries. How easy is it for the average greenfield enterprise to start as a modular app? How easy is it for the average brownfield enterprise app started 10 years ago to convert to a modular app?

First, just to repeat, you don't need to modularise your app to use jlink. You modularise to enjoy additional security and evolution benefits.

> How easy is it for the average greenfield enterprise to start as a modular app?

As easy as a non-modularised one.

> How easy is it for the average brownfield enterprise app started 10 years ago to convert to a modular app?

This one is harder to answer because you can only modularise (i.e. encapsulate in modules) code that is actually modular (cleanly separates API and implementation into different packages, no circular dependencies among components that are to become modules etc.). So it depends on how modular your codebase already is. In many situations it could require a not-insignificant refactoring, and so worth it if you really want the best security and encapsulation (which was the case for the JDK itself, which is now fully modularised). In other situations it could make sense to leave things alone and only modularise new project components (modules and code outside modules can mix).

Either way, modular or not, using link to produce a custom runtime is a good idea!

Re: Using jlink to cross-compile minimal JREs

#29
post #26

JLink is a pretty nice tool - easy to use and understand, relatively fast, big app size wins. A few misc thoughts: Figuring out what modules you need to ship can be done with the jdeps tool, but, you have to watch out for some gotchas. One is that you have to run it on each JAR or set of jars. It's slow so it helps to do this incrementally. Another is that some critical JVM functions are implemented as 'plugins' that…

I know that you're hawking your own software, but it looks quite cool. However, I wouldn't want to be a pioneer. Who uses it and for what? Do you have testimonials? Or maybe other HNers, have you used it?

Yeah, hawking things is a bit of a new world to me. Good timing for the question, though. We've been collecting testimonials just last week and have a brands block for the website ready to go, pending one more approval. So that's coming RSN.

Some firms who said we can point to their usage of it (these are all JVM based):

- HEBI Robotics. They make robot kits and ship apps that allow you to control them with Conveyor.

- GoToTags. They make NFC tags and just launched an app to work with them.

- IonSpin. "mementō is a simple and modern file management solution". They aren't fully launched yet I think.

- AdCentral. An app for managing various kinds of ad campaigns in physical stores (if I understood correctly).

There are others, that's just a subset of the ones we've asked for testimonials. There's also some open source projects that use it. So far there's definitely a theme of apps that do things with specialist hardware, which isn't a big surprise.

We also dogfood it for systemd managed servers, but that's kinda experimental. I'm still trying to figure out if there's anything useful to do there, like to go from a build.gradle to a set of pushed/updated servers in one step without Docker (or maybe with Docker). Like it'd make a linked standalone app, upload the files to the server(s), integrate it with systemd then start the apps. But maybe nobody would find that useful. Server ops is such a heavily invested-in space already.

Re: Using jlink to cross-compile minimal JREs

#30
I wonder how this would play out in a container context, aside from the benefits mentioned in regards to including only what you need and other things like that, but focusing purely on distribution sizes and space reuse. For example, if you would have your application built as a .jar (perhaps with an embedded app server), but use a separate full JDK install, then the latter could be cached on the nodes running the containers and re-used, which would be often if it doesn't change much.

With this setup, deliveries would look a bit like the following:

  #  SIZE     WHAT
  1  ~100 MB  base OS image (reused if not changed, cached)
  2  ~340 MB  JDK image (reused if not changed, cached)
  3  X MB     the app .jar file (changes with every release)
Whereas with the approach in the article, it would look a bit like the following:

  #  SIZE     WHAT
  1  ~100 MB  base OS image (reused if not changed, cached)
  2  Y MB     minimal JRE + the app (changes with every release)
For example, consider the example in the article:

   36M    zulu-hello-jre-linux-x64
  338M    zulu19.30.11-ca-jdk19.0.1-linux_x64
While it's hard to speak of how any given app would look like if it was just a .jar (or what other real world examples would be like, not just a "Hello world" program), it would only take 10 individual releases to exceed the size of the JDK. In this case, if you deploy once every day, then by the end of the first month, you'd be using ~2X more space for the minimal JRE approach. However, if you would update your JDK version more than once a month, then that might as well go out of the window.

So it appears that it all depends on how much you care about space in the first place, as well as what technologies you use, since the above example only seems relevant for container technologies that have the whole layer mechanism, and only then if you don't squash them for up front space savings for individual container images. On the other hand, if you update your base image and/or the runtime often, then using jlink makes a lot of sense, since the approach with the separate JDK would send the whole thing often anyways.

Post reply on HN