Live data from Hacker News

Using jlink to cross-compile minimal JREs

jakewharton.com

11–20 of 66 posts

Re: Using jlink to cross-compile minimal JREs

#11
post #8

Earlier quoted context omitted.

Is there something that can do the tree-shaking of the Java program?

I think if you do Graal native compilation then you'd effectively get that. The linker should chuck unused code. (though tbh I haven't tried it myself) But to just say "no reflection" and tree shake your JVM code - not that I'm aware of unfortunately! I'd love to just treeshake entire unused dependencies. At the moment I do it manually - but it's a chore and it's hard to do comprehensively. Now that post- Java8 you'r…

I've used proguard to remove unused classes from dependencies.

Re: Using jlink to cross-compile minimal JREs

#13
post #6

Earlier quoted context omitted.

It's only tree shaking the JRE itself, not your whole program (unfortunately..). So as I understand it, it means no dynamically calling arbitrary classes in the JRE, but that's a much narrower limitation. Final binary size is naturally vastly reduced b/c you won't have the whole JRE, but last I tested you still end up with very chunky executables (minimal JFX GUIs were coming out to 100-200 MB)

Is there something that can do the tree-shaking of the Java program?

Proguard is usually the tool to do that (commonly used on Android with its newest incarnation named R8).

You do need to manually annotate classes used by reflection so it doesn't remove (or obfuscate) them.

Re: Using jlink to cross-compile minimal JREs

#14
post #6

Earlier quoted context omitted.

It's only tree shaking the JRE itself, not your whole program (unfortunately..). So as I understand it, it means no dynamically calling arbitrary classes in the JRE, but that's a much narrower limitation. Final binary size is naturally vastly reduced b/c you won't have the whole JRE, but last I tested you still end up with very chunky executables (minimal JFX GUIs were coming out to 100-200 MB)

Is there something that can do the tree-shaking of the Java program?

There's proguard, originally intended for obfuscation but also serves well for dumping unused code from your project and most importantly from third party libraries. Virtually every Android app has it in its build pipeline, or these days actually a proguard reimplementation by Google (R8) that reads proguard's rather byzantine but effective configuration syntax (you usually need to keep some stuff in libraries that talk to themselves only via reflection)

Re: Using jlink to cross-compile minimal JREs

#15
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 engineering-wise to include a little shim that downloads the JRE if neccessary, or the OS could do it itself.

And why stop with Java? Why not have the OS detect the most common cases of "hey you are about to open " (where thing is a Python / Java / .NET app, or a document you can't open yet) "click here to install the needed bits and pieces from a trusted source, it will take 300 MB and 3 minutes". I think this is a case of perfect is the enemy of the good. This is a relatively simple addition that would make computers much nicer IMO.

Re: Using jlink to cross-compile minimal JREs

#16

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…

Yeah, I have trouble believing a private runtime image per app isn't going to add up to more than one complete runtime image provided by the system package manager or shared Docker layer.

Re: Using jlink to cross-compile minimal JREs

#17
post #12

curious if it also improves startup time? For me that would be more of a win than the size.

It does a little bit, depending on how much of your app is modularized. The win isn't large.

A bigger win is AppCDS but most apps don't use that due to workflow issues. It's usually about a 30% startup time improvement, in my experience.

The biggest win is native-image but that's also the biggest compatibility hit. Jlink and AppCDS are compatible with all (bytecode based) JVM apps.

Re: Using jlink to cross-compile minimal JREs

#18

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…

Yeah, I have trouble believing a private runtime image per app isn't going to add up to more than one complete runtime image provided by the system package manager or shared Docker layer.

But unfortunately the state would be having `n` complete runtime images for different versions. This is not a Java problem, Java just followed suit, and seemingly the preferred way of delivering executables is bundling everything.

Re: Using jlink to cross-compile minimal JREs

#19
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?

If you have a module-info file, you have all the used modules listed there and this jlink only has to look at that. If you use jdeps then it indeed can in itself find only the statically known modules.

Re: Using jlink to cross-compile minimal JREs

#20
post #4
post #3

Reflection or any other kind of dynamic execution (JNI?) will break this, no?

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.

GraalVM can use reflection just fine, with the caveat that you have to specify which classes can potentially be targeted (so no dynamically loading a random class file and reflection on that is possible)
Post reply on HN