BEAM's observability is very good, but JFR is unmatched. We're not talking about debugging, but about low-overhead deep telemetry (or "always on, in-production profiling"). eBPF helps, but it doesn't come close (e.g. dynamic allocations are much expensive in low-level languages than in Java, but even if you probe malloc, it doesn't tell you the type of the object allocated).
> The AI can just write in rust if you need to optimise a hot loop
Why would it when it could just write it in Java? The JVM was invented not because we couldn't write code in C++ but, among other things, to optimise things (especially around memory management and inlining) that low-level languages have trouble optimising in a large class of applications. If you're after the best performance, then you'll ask AI to use a low-level language when a low-level language offers better performance, and to use Java for applications when Java offers better performance.
Java isn't a performance compromise. It offers different tradeoffs that could make some programs significantly slower than low-level languages in some cases and significantly faster than low-level languages in others. That's the point of the approach taken by the JVM: to offer optimisation opportunities that aren't available in low-level languages. People who think low-level languages always offer better performance are people who have not had much experience with low-level languages. I originally came to Java from C++ because Java has optimisation opportunities that low-level languages don't (they have to compromise on performance in some situations for the sake of low-level control) that matter in certain but very common kinds of programs.
> zgc is a lot better for pauses
It has no real GC pauses. It does have minuscule pauses for synchronisations, but those are an optimisation, and they're no worse than OS jitter. In other words, if ZGC's pauses are a problem for you, then you won't use a non-realtime kernel, as you'll get similar pauses even in a C program on the same OS.
> I'd still say that it pulls along a fair bit of incidental complexity - it encourages you to allocate a fair amount of memory to your heap, which isn't ideal in this world of kubernetes and microservices.
It really doesn't. All of our GCs are optimised for a natural rate of allocation. They do discourage pooling objects to artificially reduce allocation rates, though, but it's easier to not pool than to pool.
> If you leave on uncommit (returning memory to he OS periodically) you get extra latency penalties which are just as painful as garbage collection stalls IMHO.
You get such stalls and worse with C++ or any other low-level language.