The other issue with bedrock is it is far from feature parity with java. If these two things were hit then java could be reasonably retired. However we are decades too late in it being acceptable to introduce a breaking change to mod loading. So it's java forever.
Games with robust modding will almost always feature a garbage collected language which is what's primarily used for the modding.
Consider this, if the mod interface was C/C++, do you think those poorly optimized mods could be trusted to also not leak memory?
Of course. Because they would fail loudly and would have to be fixed in order to run. Garbage collection is a crutch which lets broken things appear not broken.
A lot of the memory problems that you can see without a GC are hard to find and diagnose. Use after free, for example, is very often safe. It only crashes or causes problems sometimes. Same for double free. And they are hard to diagnose because the problems they do create are often observed at a distance. Use after free will silently corrupt some bit of memory somewhere else, what trips up on it might be completely unrelated.
It's the opposite of failing loudly.
The nastiest leak I've ever seen in a C++ production system happened inside the allocator. We had a really hostile allocation pattern that forced the book-keeping structures inside the allocator to grow over time.
It's since gotten a lot better with JVM updates, so much so that it's not a problem in Java 21 and 25.
Garbage collection does not solve memory leak problems. For example
- keeping a reference too long,
- much more subtle: having a reference to some object inside some closure
will also cause memory leaks in a garbage-collected language.
The proper solution is to consider what you name "poorly optimized mods" to be highly experimental (only those who are of very high quality can be treated differently).
It solves a class of memory leak problems which are much harder to address without the GC. Memory lifetimes.
It's true that you can still create an object that legitimately lives for the duration of the application, nothing solves that.
But what you can't do is allocate something on the heap and forget to free it. Or double free it. Or free it before the actual lifetime has finished.
Those are much trickier problems to solve which experienced C/C++ programmers trip over all the time. It's hard enough to have been the genesis of languages like Java and Rust.