RedHat Mandrel Makes Java Native
infoq.com
infoq.com
Framework vendors are betting on fact that most Java apps are HTTP/ORM/JSON plus metrics and security etc. So if framework provide transitive closure of these libraries and provide configuration to compile native, it will work.
For my purpose it does not work because I have many more dependencies which do not fit in above framework. Also I prefer to write my code directly with JDK and external libraries without any of these framework.
There are several features in the platform for dynamic code generation that are very hard to make work in an AOT scenario.
Graal native gives up the benefits of JIT for fast startup. It might be a useful tradeoff for some but it is not a universal solution.
I think the next step for Java will be more people shifting to using ZGC which automatically releases unused heap back to the OS where the current default (G1) doesn't.
[0] https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.ht...
You absolutely don't need to use a framework like micronaut. You do however need to understand what libraries you are using, and if/how they use reflection and dynamic class generation.
To the point of: if you want to deploy serverless applications and GraalVM requires you to write Java code that is so fundamentally different than what you have been doing for so long, why would you even stay with Java, you already lost much of the benefit of it being supposedly "the same language", and you may then just as well write your serverless application in Javascript or Python. Instead of using a far from mainstream solution like GraalVM.
I'm even wondering how obvious or subtle the bugs would be if I ever accidentally did something reflective in GraalVM.
I found this video very validating for thoughts I already had about how optimizing Java for use in AWS Lambda is not how I want to be programming Java: https://www.youtube.com/watch?v=ddg1u5HLwg8 What he lays out in this video makes me think back to doing my own memory management in C++. There's surely a place for that: high-level application development just ain't that place, in my mind.
(Myself I'm interested to see how well this handles Scala, since avoiding reflection completely is pretty much the norm there).
Spring, and Spring Boot most egregiously, work only to widen the gap between devs and ops. The developers have no idea what a Boot app is doing internally for 90% of its stack. The ops guys just want to stably deploy something that is well understood and supportable when it falls over. Not to mention the memory management headaches it introduces...
I moved away from JS early on in my career because it's mostly a disaster waiting to happen, but now the Java devs have the same potential to output a steaming pile of crap that they don't understand.
This is the biggest problem by far with Spring Boot. It’s not just hidden default settings or convention or configuration, it’s entire hidden applications.
Could you elaborate on this?
The dev team refused to accept responsibility as though they hadn't fought tooth and nail to use Spring Boot in the first place.
https://github.com/borkdude/babashka is a good place to start
(or https://github.com/taylorwood/lein-native-image if you are using Leiningen)
How so?
Whereas for me Spring Boot has the same feel as the bad old days of early Spring 3.x - lots of magical constructs that were impossible to understand unless you knew all the Spring specifics. A Spring Boot application will behave completely differently based on just which libraries happen to be on the classpath - the exact same code might start up a tomcat server when run one way and not when run another way - and has a whole host of new Spring-specific things that you have to learn if you're going to understand how your application is behaving.
GraalVM is two things. One is a regular but enhanced HotSpot. All existing Java code works on it. You can also run all the Truffle/Graal languages on it fast - it basically turns the JVM into a VM for many languages with good or great performance.
Then there's "native-image"/SubstrateVM. This can also run most Java code, including all code that uses reflection. Reflection isn't missing or broken on this platform, but by default it throws out the metadata you need for it and maybe the code (because it will appear unused). So you have to tell native-image what classes you'll want to reflect over at runtime so it keeps the data. This is well known to mobile developers who used ProGuard because it's the same; you have to say "classes matching these patterns need to be reflectable so don't optimise them".
You can't really have bugs caused by not setting these configurations correctly because if you try to reflect something you didn't pin you immediately get an exception telling you about your mistake.
The thing SubstrateVM cannot do, at least not until a later project that Oracle are working on is released, is run dynamically generated bytecode.
It's bytecode synthesis and plugin loading at runtime, not reflection, that causes the compatibility issues.
SVM/native-image has its place, but currently it's optimised for things like command line apps or servers that people constantly shut down and start up to try and save on huge AWS costs. Actual runtime throughput and latency will be far better on regular OpenJDKs, especially the latest ones with much better garbage collectors.
There is also https://mail.openjdk.java.net/pipermail/discuss/2020-April/0...
nailgun doesn't solve it generally.
leyden is not released yet; its proposal into JDK future is validation of the approaches projects like GraalVM/Mandrel and Quarkus are doing.
Still today, jlink for the above modules won't work (not generating jmods, especially all those jakarta.xxx stuff) with original tool, imagine with GraalVM.
What is hard to understand is Quarkus.
>The Quarkus project was launched in 2019 and provided that evolutionary step needed for Java developers in this new world of Kubernetes and serverless.
And on its webpage
>A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.
So correct me if I am wrong. Quarkus is an umbrella term for all the "selected" Open Source project that works perfectly on tops of Mandrel / GraalVM and Kubernetes?
[1] https://developers.redhat.com/blog/2020/06/05/mandrel-a-comm...
It’s not clear to me if JBoss/Redhat/IBM add anything new to the mix or are simply embracing GraalVM and are trying to make the experience seamless for their customers.
[1] https://www.graalvm.org/docs/reference-manual/native-image/
*update: edited bytecode sentence based on thu2111's comment
So basically RedHat is building this so they have a stable basleline for their Enterprise releases.
Can you tell me what Red Hat is not building for their enterprise releases?
I've used GraalVM and while its a bit fiddly to setup it is great for containerised apps owing to lower memory usage and faster startup - this outweighs (for my use case) the slightly lower throughput vs using regular JVM.
I think the implications of this might be much deeper than just a re-spin of Graal. If Red Hat ports all their applications into a native mode, and starts offering native spinoff of EAP, or of their other software, that might be insanely interesting offer... Hell, keycloak is written in Java...
It now depends on how strongly will RH push internally for GraalVM adoption.
That being said, generics and factory patterns aren't a problem for graal at all. Reflection and dynamic class loading are the biggest offenders.
Do you know about its workings?
Those are purely compile-time constructs.
Which means that the AOT generator has a finite set of classes to.comsider ?
And similarly, all the Spring/Boot dynamic features are a finite combination ?
(I have work on huge JVM systems with huge classpath directories but ultimately these run time polymorphism are finite?)
[1] https://github.com/immunant/c2rust
[2] https://users.rust-lang.org/t/java-to-rust-converter-for-ted...
There's even vestigal text about shipping native versions of dynamically linkable Java libs in the Debian packaging manual: https://www.debian.org/doc/packaging-manuals/java-policy/ch0...
Looks like came around in the early 00's judging by some bug reports in the archives.
Or do they produce the same runtime, but just "more native" implementation?
For example, in the traditional java, there are class loader, hot code reload, reflection, garbage collection and rpc supports. If Mandrel or GraalVM does not provide those runtime features, should them still be called Java?
Difficult in AOT environment and IIRC graal's native-image does a dependency analysis and builds a static binary.
There is dlopen() in C, it is possible to dynamically load libraries. The problem is it doesn't play well with modern deployment scenarios compared to static linked binaries.
> Reflection, GC
These are possible to implement in an AOT language. See Golang.
It's both clear that Oracle is pushing GraalVM hard and that it's what the consumer wants. If performance was identical, I can't think of a single reason why anyone would choose the regular JDK over GraalVM. It's not like people are slinging jars over the network between linux and windows... hell, now with WSL, that's not even a good reason either.
In addition, the JIT can perform optimisations that a native compiler can’t do, because the JIT can take different decisions if a field is null repeatedly, and thus elide the inclusion of code that supports the non null case leading to potential further optimisations due to dead code elimination and additional inlining opportunities. This is something that PGO won’t give you – the native code compiler will have to be defensive and compile everything, not just what it measured on a few runs of test cases.
In the JIT’s case, when an assumption is violated, it falls back to the interpreter and recompiles with the new knowledge of the change and thus includes more code than before.
The speed advantages of the JIT tend not to be seen on comparison sites like Debian’s language shootout because they don’t exclude start up time and rarely run the code a sufficient number of times to trigger the JIT’s compilation (10,000 method calls by default) to become hot. It’s why the JVM world has tools like JMH to do micro benchmarking.
Finally in the Graal case, it’s actually possible to use the Graal compiler as the hotspot replacement so you can see the difference in speed and behaviour between the two. Graal has some nice wins but also some disadvantages; it’s good at fixing some of Scales’s generated code which is why Twitter are big fans, but on regular Java code the advantages are not as pronounced.
The main benefit to Graal is the reduction in startup time, not execution speed at runtime. For long running servers you are better off with the JVM’s JIT for performance; for short start up times (like AWS Lambda) you could be better off with jaotc or Graal.
There are a couple of talks from the .NET team regarding the same issue, and how they are planning that for full support of all .NET features, the way forward is a mix of AOT/JIT.
Android team also learned the hard way that AOT only wasn't as good idea as they thought, hence why ART now does all combinations, interpreted, JIT and AOT with PGO and code cache.
List<String> l = ...
String s = l.get(0);
which looks typesafe, but to pass the verifier and load, the bytecode has to accept an Object and cast it to String before using it, just like Java programmers had to write by hand before generics (this really sucked).There's not even anything stopping you from putting non-Strings in that List instance via reflection or generic casts (if you ignore the warning) or using a really old javac. You could use a checked collection but that just adds a runtime check during writes that ensures the runtime check during reads will never fail (but the bytecode verifier still won't let you remove it!)
Java is quite fast for what it does, and I don't expect any runtime to make it significantly faster (aside the fact that java isn't slow, and its performance problems are memory usage and lack of value types, which native vs. JIT has no impact on).
I can only think of one situation when using Ocaml that I had to think about the GC (I was allocated huge floating point arrays), while I can't even count the number of times I had to deal with a runaway heap or unacceptably long pauses. The last JVM version I've really used was 7, though. Perhaps things have gotten better?
OCaml, Haskell, SML with MLTon, Nim, D, Crystal etc.. have better performance than Java unless one benchmarks a tight numerical loop. Not to mention memory consumption.
JITs are oversold. JIT may be great for optimizing Python or Lua. Moreover java is just poorly designed from a performance standpoint - no value types, virtual by default.
That "better performance" isn't reflecting in market share.
In case of C, on the contrary it lost to Java the majority of the roles it owned during 90's enterprise distributed computing applications.
Scalar replacement got better, and with Graal partial evaluation gives reduced heap allocation rates. Which can have big impacts.
Future is even more bright with inline (value) types going towards even less allocations and better memory layouts.
This is a very broad claim. Do you have data to support it? It would mean comparing production-quality JIT and AOT compilers for the same language, which are hard to find.
I'm vaguely aware that LLVM's JIT ambitions never worked out because compile times were too slow, which (IIRC) they tried to mitigate by running fewer optimizations in JIT mode, which meant the quality of the generated code wasn't as good as AOT. I wouldn't call this production quality though, and even so it wouldn't allow you to make your claim as broadly as you are.
What most developers want is not having to pay for their tools, hence why so much love for GraalVM community edition.
Some form of AOT compilation has been part of commercial JDKs since early 2000's.
In fact, the JIT cache that is now also available for free on OpenJDK traces back to J/Rockit and similarly the JIT code caches now available on OpenJ9 go all the way back to WebSphere Real Time JVM.
Also this is another point, by holding on to Java 8, those JIT caches are not available to those that only want the free JDK variants.
However it is a warm feeling that despite the critic, here is a project that they have kept aliven from Sun Labs (aka MaximeVM) and not only have brought it to production, they have a long term roadmap to replace C2 with it (Project Metropolis).
Well I agree that developers do not want to pay in general. But Graal VM CE/EE are firmly in enterprise domain, so companies have to take a call on Graal.
That happens all the time. Examples:
- Anyone using IDE plugins to IntelliJ, PyCharm, WebStorm or any other developer IDE
- Any team where developers are running a mix of operating systems but work on a shared Java codebase
- Any place developers pull in Java dependencies from Maven Central/JCenter and then use them in an Android app
This is the problem with Java ecosystem. Horribly reinventing simpler things in complex ways, from frameworks to build systems, and selling them as next big thing ™.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
https://docs.microsoft.com/en-us/cpp/code-quality/?view=vs-2...
And most of the time is a lost battle to force people to change, so it is easier to bring in people that have other culture towards security when plugging software into the network.
As for GraalVM support for LLVM, that is mostly for language interoperability purposes.
You might ask: why not run the program on real life input, save the execution profile and optimize GraalVM output depending on that? Indeed that is possible. But Oracle keeps that part of GraalVM proprietary (in fact selling such improvements are probably the most important part of their GraalVM related business, Oracle is not one of those companies which would make open source software just to be nice).
Of course benefit of such optimizations is minimal for containerized server applications that GraalVM is mainly used for, because they are not CPU bound, so for normal users it doesn't really matter. But I think that emulator is one of things where it would actually matter quite a lot.
hotspot is a just-in-time compiler, i.e. it's still compiled to native code; just not the whole codebase at once and prior to startup, but depending on usage statistics which are gathered during interpreted execution (hot code paths). you can leverage similar statistics in AOT with profile guided optimization.
as it stands, native_image starts a lot quicker, needs far less disk space and uses a lot less ram, which is important for CLI- and containerized apps. but it's slightly slower than hotspot, doesn't support dynamic code loading and of course you'll need to recompile your app for different platforms and architectures.
vmware spring: https://github.com/spring-projects-experimental/spring-graal...