6 ms·
Compiling Java into native binaries with Graal and Mill
- p2detar 2y ago> Graal can only create native binaries targeting the system on which it is running. That means that if you want to create binaries for {Linux,Windows,Mac}x{Intel,ARM}, you need 6 different machines in order to build the 6 binaries and somehow aggregate them together for publication or deployment. This is not a blocker, but can definitely be inconvenient v.s. some other toolchains which allow you to build native binaries for all targets on a single machine. To me this is a huge downside. One of the reasons I like Go so much is that I can build binaries for any platform I want to support on my Mac or with Docker.
- jeswin 2y ago> To me this is a huge downside. One of the reasons I like Go C# with NativeAOT might be an easier path for Java developers. Some might like the expressiveness as well over Go.
- pragmatick 2y agoI don't think you'd be a Java developer anymore.
- neonsunset 2y agoThat made me laugh out loud for some reason haha Indeed!
- pjmlp 2y agoWhy not? Both ecosystems complement themselves, some stuff Java ecosystem does much better than .NET, like multiple implementations, with various kinds of GC and JIT implementations, wider support of hardware deployments, tooling like Graal, industry standards, IDE implementations, a mobile OS,... Other things the .NET ecosystem does better, support for value types, low level programming, SIMD, desktop development, game engines. To this day they keep copying features from each other, and if either C# or Java isn't one's taste, there are still several other options on each platform. Hence why I am confortably at home using them both, complemented by JS/TS for FE, and C++ for fiddling with their runtimes, or plugging into native libraries.
- neonsunset 2y agoWhat features is C# copying from Java?
- pjmlp 2y agoMost of C# 1.0 for starters, given that it was born from the lawsuit and J++ extensions, J/Direct, COM interop, events and Windows Foundation Classes. More recently, default interface methods, apparently the ongoing discriminate union design seems to now be settling on similar Scala/Java approach, I still have to spend some time delving into it. Not delving now on the CLR, versus the various JVM implementations, regarding GC, JIT, PGO, tiered compilation, escape analysis,...
- deleted 2y ago[deleted]
- brabel 2y agoI've been using Dart instead. Not too far from Java, but can compile to executable without any cerimony.
- josefx 2y agoHow is the cross platform UI situation on C#? Anything official?
- neonsunset 2y agoThere is a good selection of multi-platform GUI frameworks: AvaloniaUI, Uno Platform, MAUI and smaller more focused alternatives.
- cratermoon 2y ago> this is a huge downside. Also the compiler can only do static analysis and code generation. I'd much rather a hotspot VM analyze the running code and identify the optimizations on the fly.
- Yasuraka 2y ago>I'd much rather a hotspot VM analyze the running code wasting gigabytes of ram and fast startup times >and identify the optimizations on the fly and still get gapped by statically compiled languages. I guess these are a cheap price to pay for the benefit of ... having to install and patch runtimes.
- forty 2y ago> still get gapped by statically compiled languages. Which statically complicated languages are you referring to? :)
- pragmatick 2y agoNative Image requires so much more work to have a medium-sized java project properly run when compiled the price gets a lot higher.
- sgammon 2y agoMore of this configuration is automatic with every release
- gf000 2y agoUnused RAM is wasted. If you have plenty available then doing useless memory releases (including dropping/destroying objects with RAII, which can end up doing a lot of work in case of a data structure containing other objects that have to be dropped) will just hurt your throughput. Nonetheless, Java has a pretty trivial single flag to set an appropriate heap size if you are not happy with the default. -- You are thinking of AOT compiled, but does that AOT language support arbitrary class loading to expand functionality, live observability while taking almost zero overhead for that? -- So what do you do if a statically linked library of yours has a vulnerability?
- deleted 2y ago[deleted]
- taurknaut 2y agoAgreed, this is definitely an odd and very unnecessary constraint on builds.
- sgammon 2y agoWell, it's also not true. But aside from that, plenty of software builds in its native environment. Cross-compiling is straight up hard for many toolchains.
- flakes 2y agoI wonder if you could wrap this process in something like qemu for a cross-architecture build setup?
- taraparo 2y agoYou can e. g. create ARM builds on x86 using qemu but the compilation takes ages.
- rixed 2y agoGCJ could do that, as well as JET I believe, but both are long dead. The history of native compilation for java I find fascinating: Nothing looks like a normal, boring programming language as much as java, yet somehow it resists being treated as a normal, boring programming language, and needs its own galaxy of special idioms and tools, like it was some smalltalk or lisp.
- chii 2y agobecause java is not designed for it. It's retrofitted in, because of trends. There's actually, imho, no need for native compilation for java tbh. Why isn't shipping the runtime with the code a more common practise? it's how intellij or eclipse worked. People today ship electron apps for god sakes! If you _need_ native, for one reason or another and it's non-negotiable, then choose a native compiled language.
- brabel 2y agoAbsolutely. > Why isn't shipping the runtime with the code a more common practise? Well, Java has jlink which is meant to do exactly that (ship the parts of the JVM you actually need, which is easy to figure out as there are tools to do that), and that's the recommended approach today for shipping anything Java.
- p2detar 2y ago> Why isn't shipping the runtime with the code a more common practise? That's what I actually do for our product. The JRE is shipped with it as well as startup scripts and services registration bridge for Windows. I guess the native compile thing is more for "Java on the Cloud" which tbh is not where Java shines. I say this as a long-term Java developer. Java is great for monoliths - on premises customers are supper happy. Java on the cloud seems like a waste of resources to me.
- xxs 2y agoWhile not a fan of the cloud - in case of java; package it in docker or whatever deployables along with the JRE (or even JDK) and call it a day. Compile to native makes sense only for very fast startup cases. As for wasted resources - there are cases where the servers have to be deployed in specific jurisdictions (compliance) - it's easier to use AWS than manage tons of small sites. Still I don't see any need for native compilation.
- pragmatick 2y agoWhile I agree I think most use cases aren't for releasing end-user software that needs to run on many architectures and OSes but rather building enterprise software for one certain combination, usually x86 and linux, to deploy on a server or containerized in a hyperscaler. But to contradict myself, I actually use windows, WSL and oracle cloud to build for windows x86, linux x86 and linux ARM64 to build a java desktop application. Of course I'd prefer it if I could just use my main machine and OS to build all those like Go can.
- ltbarcly3 2y agoYou realize you can run Linux, Windows, Mac x intel, arm builds on docker right? Right on your Mac.
- sgammon 2y agohttps://github.com/oracle/graal/issues/8350 https://github.com/oracle/graal/issues/8350 Plz upvote
- sgammon 2y agoAlso, I don't believe this is fully true. GraalVM depends on the underlying C compiler to generate native code, so if properly configured with target triples and flags (just like any cross-compiling setup) it should work.
- gf000 2y agoGraalVM reuses the normal java class loading logic which is platform-dependent. So e.g. on windows it will load some windows-specific File subclasses and the like, so this is more of an architectural problem to a certain degree. (It really does loadClass everything reachable based on the code to be compiled)
- ludovicianul 2y agoYou can do the same with GraalVM on Mac for Java.
- theflyinghorse 2y agoMill looks like an interesting option to try all around.
- wiradikusuma 2y ago"Almost every Java program, library, and framework uses some degree of reflection and dynamic classloading, and so you do have to spend the effort to configure Graal appropriately." -- this is by far the biggest problem with native binary compilation. Imagine spending 15+ minutes building an exe, and it stopping at minute 15 because some things needed to be added in the config. Or, after waiting 30 minutes to have the exe ready, it refused to run because of the same problem. The issue is we don't know what we don't know. You don't "forget to include something" because you don't know what to include (and even after seeing the error, you still don't lol). I just wished all 3rd party libraries put their "include this config to include my lib in your exe", just like OSGi manifest (https://www.ibm.com/docs/en/wasdtfe?topic=overview-osgi-bundles https://www.ibm.com/docs/en/wasdtfe?topic=overview-osgi-bund...). For example, an issue still open for almost 2 years: https://github.com/firebase/firebase-admin-java/issues/800 https://github.com/firebase/firebase-admin-java/issues/800
- killingtime74 2y agoWe've been using it at work for a few years. A cli tool, builds in about 6 minutes. We compile it to Linux, Mac ARM and Mac Intel. You're correct about configuring libraries but I found those to be the minority. Most work without configuration. I do this because I will not use Golang if given a choice and Rust is not allowed.
- Jabihjo 2y agoWhat's your issue with Golang? (Not hating, just curious)
- killingtime74 2y ago(sorry it's probably it an unpopular opinion) the error handling is hard to read, they purposely didn't incorporate any syntax sugars and innovations of previous years. They were one of the first popular languages with go routines although Project Loom in Java will soon have preemptive multi threading as well.
- 2y ago
- deleted 2y ago[deleted]
- neonsunset 2y agodotnet publish /p:PublishAot=true :)
- Alifatisk 2y agoWill this produce a cross-platform standalone binary?
- diggan 2y agoNo, and neither will one invocation of GraalVM.
- neonsunset 2y agoIt will be completely standalone. The same way it works with Rust, Go, etc. The binary size will be smaller than Go but bigger than Rust. Portability is by definition not possible with natively compiled binaries however. It is a choice - either produce an assembly (still single-file, .NET can do this unlike JVM offerings) that is completely portable, or produce a self-contained executable targeted at a particular OS and ISA.
- diggan 2y ago> It will be completely standalone Sure, but not cross-platform, which the previous comment seemed to indicate that GraalVM could, which it cannot. Both tools need to compile on the platform they target, compared to Go/Rust where you can target other platforms even though you're not compiling on them.
- pjmlp 2y agoCross compilation is a toolchain feature, not a programming language capability. As for GraalVM, it has plenty of modes, the AOT one that is being talked about here, is native image. Which can also use a JAR file as input, so even though it doesn't yet support cross-compilation, you can use the JAR file as single source, and then have a couple of build environments in e.g. Github pipelines. https://blogs.oracle.com/developers/post/building-cross-platform-native-images-with-graalvm https://blogs.oracle.com/developers/post/building-cross-plat... Does it take a couple of more steps? Yes it does. To the end user it doesn't matter as long as they get their shinny executable available, and it only has to be done once as a project template. Also note that cross-compiling only really works without issues for whatever compiled language, if the toolchains have access to every single library from the target system on the host environment, and no dependencies FFI into other languages.
- dkjaudyeqooe 2y agoI'm under the impression that the Community Edition version of GraalVM is neutered by a limited garbage collector and some other limitations when producing native binaries. Anyone know if this true?
- quikoa 2y agoCould Oracle neuter it more in an update to push the commercial edition?
- sabas123 2y agoIIRC there base kit like garbage collector and runtime are all the same between community and enterprise. The biggest feature that comes to mind that is behind the enterprise-only wall (or at least used to be) is Profile Guided optimization.
- sgammon 2y agoThis is partly true. CE has the "serial GC," yes, and no access to G1 GC by default. But Oracle GraalVM (formerly "GraalVM Enterprise Edition," which no longer exists) was released under a much less restrictive license: https://blogs.oracle.com/java/post/graalvm-free-license https://blogs.oracle.com/java/post/graalvm-free-license So, yes, GraalVM CE is slightly nerfed (the performance difference across all EE features is like 30% maximum, at peak, in limited circumstances). You also do not need to use GraalVM CE in as many places anymore, and Oracle GraalVM with G1 is a free download. Many free projects like Pkl use the full-blown VM. https://www.graalvm.org/latest/reference-manual/native-image/optimizations-and-performance/MemoryManagement/ https://www.graalvm.org/latest/reference-manual/native-image... Serial GC is still very performant. It's great for things like command line tools which don't need a low-pause long-running GC like G1.
- dkjaudyeqooe 2y agoSo the runtime and libraies incorporated into native applications compiled by Oracle GraalVM is freely licensed? I tried to find that information but it's all a sea of legalese.
- neuroelectron 2y agoJava had a huge reflection exploit a long time ago and most places blacklisted that library as a result so not a big loss there.
- neuroelectron 2y agoWell, wow. Apparently people are still blindly using reflection. A lot of people, in fact. Have you thought about literally any other language to build services?
- rf15 2y agoIt's less a problem of the language and more of popular frameworks using reflections excessively. (usually for no gain other than creating platforms that are not controlled by normal readable/tracable code flow but annotations)
- deleted 2y ago[deleted]
- deleted 2y ago[deleted]