Languages like C and Rust do not have any equivalent to JVM tuning.
In Java's case if you have all the class files, all you need is the JVM for your architecture. You don't need the program's author to compile it for your architecture.
And finally, JVM tuning does not need to be performed by the user, but can be performed by the user. The most frequent tuning needed to be done by the user was the maximum memory that the JVM could allocate, but that hasn't been needed for a long time (since Java 8, I think). Now the JVM, by default, has the sensible behavior to allocate as much memory as the OS will let it, when asked by the application.
My experience is not that you can run 99% of Java applications without running out of memory or something like that. That's why I avoid Java these days when I have the option. I don't think things would have changed much that much in recent years, making my experience no longer valid.
I've been using Java daily for years at this point. The only time I've had that sort of issue is when the program I was writing dealt with large files in memory, and it was solved with a simple -Xmx16G.
Admittedly even with a C program the size of a problem requiring 16GB might not run well in a 2GB machine, but the fact remains that Java applications are often much more memory hungry than comparable C/C++ implementations. And if you have the memory they will just use it without any Xmx. That sounds really like computing in the 1960/70s that you need to allocate memory in advance. (I'm old enough to have seen such stuff, although not when it was new.)
Is there a concept that the search machine would find, which has brought the radical change you mention?
Regarding OpenJDK, other JVM vendors have improvements of their own.
G1 has had ~700 improvements since JDK 8 and is now very different: https://archive.fosdem.org/2020/schedule/event/g1/
ZGC, the low-latency collector (which gives a ~1-2ms max pause times on heaps of up to 16TB in JDK 16) was introduced in 11 and made production-ready in 15.
In general, the way the GCs work is just very different from 8.
Plus, there have been lots of improvements to CDS and startup time in general due to how the VM loads classes and initialises data (~30 ms to run Hello, World on a cold VM in 15) -- https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.ht..., https://twitter.com/cl4es/status/1311335253139771393, https://www.morling.dev/blog/building-class-data-sharing-arc...
And, of course, now everything lies on top of the module system.
I have run operations for programs written in Java, C++, and Go. I've done it both at small companies and large companies, for everywhere from a rack of dedicated servers running Apache Tomcat to thousands of virtual machines running a mixture of C++ and Go microservices.
The constant thread is... over the last ten years... the people running JVMs complain about tuning the JVM, and always have stories to tell about it. The JVM is fantastically tuneable, and when people online complain about GC pauses or memory problems, there's often some way to tune the JVM to fix those problems. The JVM is amazing, it's a marvelous piece of technology.
But there's also a bunch of people who don't know how to do it and just turn knobs. Like, oh, customers are calling in to complain about latency, so I'll increase the size of the Java heap. (Which, for those not familiar with GC, will make throughput better but make latency worse.) Running services on the JVM means that "working with the JVM" is now a skill you need to select for whatever operations team you have, and if you're a company running a mix of different services (like, I don't know, some databases, memcache, load balancers, etc) then "knowing how to tune the JVM" competes with several other skills you'd like your team to learn.
Or those that complain about RDBMS queries being slow, without having normalized their data or written proper indexes.
There is always bunch of people that don't know how to do things, and then there are those among them, that care to improve their skill set and get to know how to turn those knobs.
It’s not a question of whether there are knobs to turn. It’s about the typical experience of an actual person running a JVM app versus, say, C or Go, and those experiences are quite different.
And we’re also talking about running someone else’s app. If your database queries are slow, that’s a conversation between the DBA and the devs. If you’re running some Apache app, you’re probably not talking to the devs.
This hasn't been my experience at all after running java on production servers for over a decade.
That said you probably can’t get very far in c/c++ without worrying about memory the whole way through. So, you only worry about tuning when writing your code.
Most of the time defaults just work.
(You can read a disk 10 times in series or 100-1000 times in parallel in 1ms; it’s practically an eternity.)
I found the comments really clueful but also appreciate when others like e.g. @_msw_ are very overt with disclosure of their employment and interests whilst talking about $employer's stuff on HN (and in his case that'd be AWS and EC2).
Edit: also, did they replace the JIT with AOT?
No, OpenJDK 15 defaults to G1 (since JDK 9), but it is very different from G1 in JDK 8 and rarely requires tuning: https://archive.fosdem.org/2020/schedule/event/g1/
Plus, ZGC, the low-latency collector (which gives a ~1-2ms max pause times on heaps of up to 16TB in JDK 16) was introduced in 11 and made production-ready in 15.
> Edit: also, did they replace the JIT with AOT?
Replace? Why would anyone want to do that? But there is an AOT compiler available: https://www.graalvm.org/reference-manual/native-image/
They absolutely do. It’s called “managing memory.”
You're likely talking about work on custom memory allocators and impact on real time performance. In the hosted services domain this isn't so much an issue. Nobody's doing that in Java, and you likewise wouldn't care much if writing the same type of service in Rust.
Rust very much enables you to write high level, Java-style code. It's not bad code, nor is it difficult to write.
In my opinion it’s the worst of both worlds at that point—you’ve got to manually manage memory and tip toe around the runtime.
You really don't. Anything you could do it, say, Go, you can do in Java without doing any JVM flags. The only time you need to do JVM tuning is when you have performance requirements that are simply impossible in most languages.
Does't this argument cut both ways?
i can write my C programs without ever thinking about java. it is irrelevant to me. however, C is very important for java since the JVM it is running on top of is written in C.
i think, personally, the outcome this type of thinking is that “therefore every java program is in fact just cruft on top of C” which personally as someone who does 80% of their job in SQL i am ill-equipped to object on java’s behalf.
https://en.wikipedia.org/wiki/List_of_Java_virtual_machines
Most of them don't have a single line of C, rather C++.
Then there are a couple of them like JikesRVM and GraalVM that are meta-circular implementations.
I’ve deployed things written in many languages at extremely large scale. They’ve been written in Java, C, C++, python, go, sh, perl, and other languages I’ve forgotten. Java is, by far, the least operable of those languages.
I’m an expert Java developer, along with most of those other languages (where expert is defined by me as “over 10 years experience”).
In fairness to java, it’s not my least favorite language on the list.