Your fourth point is the primary reason.
The GC in the JVM is set to try to waste as much RAM as possible. If you tune the GC you can get a big improvement and the standard Java Frameworks are bloated and slow as hell.
In my opinion it's a platform that is bad by default and simply isn't worth using but companies don't care and just buy more RAM.
Just a small nit but the term you're looking for here is "value types". Rust does heap allocations(with the pointer overhead) via Box<T>, you just get explicit control over the overhead and cost.
With Java 9 modularity and lightweight libraries like Guice you can get much nimbler apps.
Of course there have been some advanced in GC technology since 2005 (and that paper was deliberately measuring a relatively standard generational approach). But I don’t think I’d call the 5x figure a serious exaggeration.
So like I said, maybe in 2005 a 3x memory overhead only incurred 17% slowdown, but 3x overhead is at least at par, and possibly even a little ahead, of manual memory management.
* Java tends to allocate things separately and manipulate pointers, while Rust allocates things inline. This introduces allocation overhead and eats up the space needed by the pointers themselves.
* Java uses a JIT, which consumes of memory for profiling state and for storing the resulting compiled code.
* A tracing garbage collector needs about five times as much memory as explicit freeing to reach the same performance. https://en.wikipedia.org/wiki/Garbage_collection_(computer_s...
* Like vegetarians, Rustaceans pay more attention to efficiency as a whole. This may give the appearance of Rust being more efficient, even if it's actually not.