Venting About GraalVM - From Today's Attempt to Combine Spring Reactive + Spring Native + mongoReactive
I have to say, every time I compile to an executable with Native-Image, I feel uncertain, wondering if I've introduced some package that can't be included causing build failure, or if a third-party package contains AWT references, or uses reflection...
At times like these, I always think of how smooth Rust builds are - no need to worry about these issues. But Rust's development speed is something I find frustrating - writing it always feels a bit off compared to Java, which I've been writing for a long time.
And now it's 2023, when building backend services with full reactive programming Spring Native + mongodb, the results are still quite unpleasant. I encountered a series of problems that are the kind where you don't know how to start solving them. If anyone sees this article and knows the solution, please leave a comment (Finally solved it, just changed a configuration, here: GraalVM mongodb-reactive SpringNative, Java runs normally but compiled...)
Let me vent about some frustrating points:
1. CPU Maxed Out During Compilation and Long Build Times
My computer specs: Apple M1 16 GB, macOS 13.4 Ventura
Here's a result from using maven native compile:

You can see it took over 3 minutes, CPU usage was maxed during compilation, and memory usage was also quite high throughout. My computer was constantly hot to the touch - not pleasant at all.


Adding a temperature monitoring screenshot during compilation:

2. Java Code Is No Longer "Write Once, Run Anywhere"
I can accept installing GraalVM on each device for compilation - that's at most the difficulty of installing a JDK, and worst case Docker can solve these problems. But I can't accept writing code, having it compile successfully, but not being able to run it, unable to troubleshoot where the problem is, then going back to try "removing certain dependencies", "upgrading dependency versions", "changing how certain code is written", "spending lots of time searching if anyone has encountered the same problem", and so on.
People write Java because Java has a rich community and mature solutions, so you can always pull out decent libraries, stitch them together into an initial product, and launch. But clearly GraalVM breaks this experience - you can't know if the libraries you're using will work, whether your code needs modification, and modifying original designs based on test results from compiled executables is itself destructive. You need to spend more time thinking about compatibility, code robustness, and searching for alternatives then rethinking the entire architecture.
At least Spring Native and Quarkus under GraalVM haven't reached out-of-the-box status yet. Not discussing hello world scenarios here. Meanwhile, Rust is already shining in multiple fields and can even cross-compile - truly enviable. What I hope for is using Java's syntax while covering similar compilation scenarios as Rust, at least supporting the three major platforms: Linux, macOS, and Windows. I don't even require Rust's performance - maintaining the same performance as under JVM would already be asking a lot.
3. Problem-Solving Difficulty Increases Dramatically
Before, when Java code was wrong, you could search online and most blogs had already covered it. Now there's even ChatGPT, whose knowledge covers 80% of Java development scenarios - you just need to keep asking it until you get a suitable solution.
But when GraalVM compilation fails, solving the error isn't that simple. First you Google to see if anyone has encountered the same problem. If you're lucky, someone has already stepped on this mine, then you see the issue date - how is this still a 2018 problem? But at least the status is closed, meaning someone solved it, then based on the content, you try changing GraalVM JDK versions or some settings. That's the ideal scenario.
But more often, no one has encountered your problem, ChatGPT doesn't know either, submitting issues to GraalVM who knows when there'll be a reply. For example, the current problem I'm facing - the Java version code works perfectly, compilation passes, but using the executable to connect to mongo throws AuthenticationFailed. I searched online and only found one similar problem, and that person's issue was just wrong username/password.
After all these experiences, it really discourages me from continuing to use Spring Native. You'll feel uncertain about your code, not knowing if 1+1 will equal 2 in the end. This problem is only considered the first step of success after successful compilation + successful execution. After all, you don't know if there'll be problems after running for a while. If you're using reactive programming + GraalVM, when troubleshooting errors, you'll experience the "joy" of having no call stack printed, or printing but going to Native methods - so "joyful" you want to give up treatment.
4. Better to Switch to Rust
GraalVM's vision is really good. I really hope to combine industrial sweetener Kotlin + GraalVM + reactive programming to get a fast-starting, low-footprint, high-performance executable. Or write most logic in Java, system operation logic in Rust, then call Rust through GraalVM.
But the actual experience makes me feel it's a bit too idealistic. Plus there seem to be very few people doing this domestically - most enterprises are still playing with JDK 8. If that day ever comes, it'll probably be a long, long time from now. Better to learn Rust first - it's really great!
