60 ms·
JEP 544: Ahead-of-Time Code Compilation
- java-man 7d agoI hope at some point we'll get AOT-only mode (or compile to native) and maybe even cross-compilation.
- invalidname 7d agoWe have that in Codename One, yes it's not really "Java" but it compiles bytecode AOT and cross compiles to some of the platforms.
- nirvdrum 7d agoIf you haven't checked it out yet, GraalVM's Native Image [1] already let's do AOT compilation suitable for distribution. You have to do some configuration to deal with reflection and dynamic class loading since there's no JVM in the produced build, but it comes with tooling to simplify that. And that restriction is being addressed by Project Crema [2]. [1] -- https://www.graalvm.org/latest/reference-manual/native-image/ https://www.graalvm.org/latest/reference-manual/native-image... [2] -- https://github.com/oracle/graal/issues/11327 https://github.com/oracle/graal/issues/11327
- Twirrim 6d agoThe slight drawback is that AOT compiled Java code's performance isn't as good as the JIT compiled form running on the JVM. There's a reason why folks keep coming back to JIT compilation. It's hard to beat the value that can be gained from actually gathering data on how the code is actually used, which leads to a whole set of potential optimisations (which is the problem Profile Guided Optimisation attempts to solve for AOT compiled code.) The JVM is arguably one of the most advanced and capable JITing runtimes. As with anything it's a trade off. Fast start times, pretty fast running (I think maybe less memory usage?); vs the full JIT speed you can get on the JVM at the cost of start-up speed and memory consumption. All depends on what you want to use the application for. If you're talking something like a serverless function, go native. If you're talking production server where you're measuring runtime in more than dozens of minutes, probably better to stick to the JVM & JIT.
- bebop 6d agoFull agreement with everything you said. Just one detail to add on serverless (and potentially in a scheduled environment like k8s), startup time can be an order of magnitude or more faster in a native build. For instance, I have some quarkus applications that can take 10 seconds to ready running via the jre that take 10ms or less to start as a graalvm built binary.
- pjmlp 6d agoDepends on how much effort, like on C and C++, you are willing to put into PGO metadata for the compiler and linker.
- samus 5d agoEven if you can gather that PGO metadata a running application won't be able to adapt to changes in that data.
- pjmlp 5d agoIt works well enough for systems software written in C and C++, where Java still remains a niche option, even when it could deliver.
- samus 4d agoJava has many dynamic features where runtime optimization is required to remove the overhead. Virtual method calls are opt-out instead of opt-in, and there is an open world assumption. The possibility of doing stack allocation of objects depends on the call hierarchy (in the future it will get a bit easier with value objects). Also, C/C++ are not managed languages, therefore the effects of bad optimization don't hurt as much.
- exabrial 7d agoprogress, not perfection! Java is on fire right now with new stuff landing. We'll get there!
- layer8 7d agoThat would place significant limitations on the applications that can be compiled. As the JEP explains: “Features such as dynamic class loading, dynamic linkage, dynamic dispatch, and dynamic reflection bring vast expressive power, and have been fundamental to the platform's success. HotSpot handles these features naturally, while static compilers struggle with them. Even heroic amounts of static analysis cannot make up for the fact that these features require many decisions to be made at run time. Implementors of static compilers for Java code have therefore resorted to incompatible constraints, such as closed-world assumptions, and to putting significant burdens on developers, such as having to identify in advance the classes eligible for reflection.” Therefore I don’t see AOT-only becoming an integral part of standard Java in the foreseeable future.
- java-man 6d agowe are not talking about fully supporting dynamic loading, because it's not needed in all the cases, and in some cases, the list of allowed classes in the application can (or must) be limited. i guess what i am saying is that AOT-only case is not "standard java", but something that will make a (more) useful replacement for things like c/c++.
- samus 6d ago> i guess what i am saying is that AOT-only case is not "standard java", but something that will make a (more) useful replacement for things like c/c++. What is the objective here? Startup latency or throughput? Both will be vastly improved by JEP 544.
- jasomill 6d agoIt works pretty well for greenfield projects on .NET, so long as you can live without third-party libraries that don't support AOT. Existing code bases can be a pain, though, especially applications that heavily rely on things like C++/CLI and COM Interop that basically need to be rewritten from scratch. Which is not to say that it's intended to replace the traditional JIT runtime in applications where it isn't troublesome, because it's not.
- samus 6d agoThat won't be necessary when 544 lands. The only thing you'd gain is not having to ship the JIT compilers in a jlink build. Also, I'm fairly certain that the JIT compilers can be turned off with some combination of runtime flags to ensure only the AOT generated code is executed.
- za3faran 6d agoGraalVM native-image already provides an AOT-only executable.
- cyberax 7d agoExcelsior JET did that 25 years ago: https://en.wikipedia.org/wiki/Excelsior_JET https://en.wikipedia.org/wiki/Excelsior_JET It's a shame that Sun/Oracle never partnered with them to bring native apps. This could have saved Java on the desktop.
- patwolf 7d agoIBM's J9 had AOT for a long time too. I wonder how JEP 544 compares.
- samus 6d agoIMHO the most interesting feature of OpenJ9 is the compile server. One node decides to optimize, sends over the traces, and the compile server sends optimized native code to all nodes. Or a new node joins and could be brought up to speed within a very short time.
- pjmlp 5d agoAzul also has a similar feature, as added info.
- wahern 7d agoDon't forget GCJ. It wasn't removed from GCC until about 2016, a nearly 20-year long run, though interest had waned many years prior. I don't remember if GCJ supported loading and running code dynamically with a built-in JIT or interpreter. I think it was just pure AOT, which caused some compatibility headaches.
- java-man 7d agoGCJ was great - I wrote a handset UI entirely in java for a startup in the early 2000's, basically android before android existed, using GCJ. I remember their native interface was somewhat more convenient to use than JNI. I wish we had GCJ resurrected, now that the java libraries are GPL'd.
- SillyUsername 7d agoSo we've gone full circle again? I suppose write once run anywhere is no longer a goal either. "It is not a goal to support all CPU architectures currently supported by HotSpot." This pretty much validates the point of view that VM design is now baggage, as a sandbox it has been flawed, for performance it's been prohibitive, and cross platform portability by virtue of being virtual, was just a convenient byproduct. AI now handles the portability, sandbox security hasn't changed (cf. docker still has sandbox problems, LLMs have sandbox problems, it's always an ongoing concern) and that just leaves Java, as always, chasing performance.
- nirvdrum 7d agoThe very next sentence after the one you posted is "We expect normal porting activities to eventually add support for all major architectures." Goals and non-goals inform the scope of the proposal. Given this is effectively an "add-on", I don't think it's unreasonable to prioritize the most popular platforms. Others will continue to execute Java perfectly fine in JVM mode.
- randomUUID 7d agoI don't get your point. This is what JEP says: - "Improve startup and warmup time by making optimized native code for an application instantly available when the HotSpot Java Virtual Machine starts." - "If the workload changes in production, regenerate native code dynamically for continued peak performance, providing the best of both ahead-of-time (AOT) and just-in-time (JIT) compilation." - "Ensure that shifting from AOT-compiled code to JIT-compiled code is invisible to applications." That is JEP544 doesn't substitute JVM and JIT optimizations. It just changes the nature of the JIT's outcome.
- pjmlp 7d agoNot at all, this is OpenJDK getting JIT cache feature like OpenJ9 has since 2008, or ART since Android 7.
- ledo9915 7d agoData point from a small side project: I run user code in a Piston sandbox for a coding challenge site. A trivial Java program costs 2.5-3 s wall clock on a 4 vCPU box, almost all of it javac plus JVM startup. Go takes about 1.7 s for build plus run, and Swift running through the interpreter is at 0.4 s. Java is the reason I had to put a global rate limit on compiled languages at all. If AOT gets the JVM side down to a few hundred ms, that changes what a small box can serve.
- xxs 6d agoif that's any help: (guessing) you have tons of dependencies in multiple jars, if you bundle them all in a single jar (i'd not even compress it), the startup time would massively decrease. Stuff like dependency injection, makes the issues worse. Lots of the strautup time is class resolution/loading. With that being said - some time last year I ended up optimizing on the main application servers developers run with startup time being over 90s (and often times close to 3min), down to 11seconds (still tons of access of database configurations, secrets, discoveries, and what not). One of the main optimizations was runtime build up of a single jar with the classes being loaded, and then concurrently verifying the classes/resources have not changed.
- samus 6d agoHow much of these 3s is javac? JEP 544 will only help reduce javac's overhead, not that of the compiled program.
- cogman10 6d agoLeyden has been relying pretty heavily on training runs which I get, but man is that a pretty hard burden to setup. The tooling for doing these sorts of training runs doesn't really exist, you end up needing to do something more bespoke as part of your build pipeline if you want it there. That can be especially tricky with more complicated applications like the ones I maintain. I like what these can deliver, but dislike the effort needed to get it going.
- jgon 6d agoI completely agree. I know that there has been some work on command line ergonomics for this stuff, but my hope is that after the bulk of the Leyden work is done, another project starts up aimed at unifying all of the various disparate tools that modern Java now has. You have training runs to generate bytecode/compiled code, you have jlink to create a distributable JRE for your app, leaning on jdeps and various other tools to correctly create it, you have the venerable jar file, but all in all the process of actually getting a java project ready to distribute in a way that doesn't presuppose a relevant pre-installed JRE on the user's side, and which takes advantage of the various facilities available to modern Java is still a pretty bespoke and painful process. Compared to Go and Rust, and just throwing a static binary to someone or some server, Java kind of sucks. And that's unfortunate because the language, the runtime, and even the dependency situation all feels pretty competent, there's not some huge gulf that makes Java "old". Its really just the every about setting up a project and then distributing it, so the "start" and "end" of a project, that currently sucks, and I fear that so much of the great work the Java team is doing is going to go largely unused if they don't work to make it easier for the average developer to utilize it.
- tadfisher 6d agoAre you describing jpackage? I'm not sure how you would make it less bespoke, given you are essentially creating a Java runtime for your program. Maybe the Java folks could tree-shake the runtime for you so you wouldn't have to care about their weird module system, but it's not the worst thing to learn.
- treyd 6d agoWhat are the architectural differences between this and Android's ahead-of-time runtime?
- Skinney 6d agoThis JEP is essentially about caching the JIT's generated code for later runs. The JIT is still free to discard the cache if it deems it worthwhile.
- hn_submit 6d agoA little late, isn't it? .NET has had this for over 20 years (pre-compile).
- pjmlp 5d agoJava as well, since 2000, one year before .NET public announcement in 2001. Java is an ecosystem like C and C++, there were always multiple implementations to choose from, some of them required money for the goodies like AOT.
- stevefan1999 6d agoWelcome to ngen and GAC, Java
- pjmlp 6d agoOnly as free beer, Java has had similar commercial offerings before .NET was created out of J++ lawsuit, like Excelsior JET.
- jayd16 6d agoThe .NET implementation also has a similar AOTCache with ReadyToRun. That's a public and old enough to have pros and cons shake out in the real world that would be worth talking about. I'm not sure the pissing contest is really relevant, nor do I think Excelsior JET is all that common but if that is a similar system and you would like to talk about the real world impact please expand on it. https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run https://learn.microsoft.com/en-us/dotnet/core/deploying/read...
- pjmlp 5d agoI hate the traditional pissing context between Java and .NET ecosystems, because I work with both since they exist, and the whole reason .NET exists in its presence form was Sun's lawsuit, otherwise it would still be J++ alongside COM. Excelsior JET wasn't the only commercial vendor, only one example, there were others, two surviving ones are PTC and Aicas, meanwhile IBM open sourced Websphere Real Time JVM AOT as part of Open J9. A big difference between .NET and Java world, is that since early days Sun licensed the technology, thus the ecosystem is like C and C++, with plenty of options to choose from, each with its own set of JIT, AOT and GC flavours. Even Android, while not being Java, has had JIT cache + AOT since Android 7, after trying to be pure AOT on Android 5, when Dalvik was replaced by ART. .NET has had NGEN since day one, however it has been rather basic in optimizations, designed for quick startup of Windows Forms applications and little else. Sing# and System C# were quite interesting, but they never left Microsoft Research into regular .NET. Mono was the one caring about proper AOT compilation and JIT caches, then .NET Native was created by the Windows team which was more interested into using COM to replace what was left of .NET on Windows since Longhorn than anything else. Java and .NET only started caring about offering free beer AOT compilation, JIT caches, due to return of AOT compiled languages and the adoption competition in the server room from those languages. Ideally, they should have supported proper AOT compilation, and value types (in Java's case) since day one, given languages like Oberon, Modula-3 or Eiffel, that predated them. Instead, both platforms are now catching up with those 1990's languages.
- harlan_pdx 6d agoStartup time being the main benefit means simple training runs get you most of the value. Going for peak throughput is where the setup gets heavy.
- rerdavies 5d agoWhy would you not AOT compile at install time?! That would allow the compile to use CPU-specific features? And put a compiled preamble for class initialization on applicable functions that patches the VTABLE to skip the class initialization code.
- samus 5d agoThere is no install time in Java. If you want something to happen at install time you'd have to ship a shell script with the installer that does a brief training run when the application is first started.
- ptx 5d agoThere is with jpackage. The packages it builds could include install scripts (or custom actions in the case of MSI) to run at install time. The script wouldn't have to do the training run at install time, as I understand it, just the AOT compilation. See the section on "AOTMode=record" vs "AOTMode=create" in the JEP.