Three things:
* 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.