By Java 5 the average cost of an allocation in Java was already lower than heap allocation in C++, but greater than the cost of stack allocation. With escape analysis in Java 8 that got even better.
The biggest problem Java had was that 90’s era thinking on GC algorithms (most GC languages in the 90’s were using 80’s era GC algorithms) ran out of steam sometime around 2005, when memory availability created situations where GC pause times were impossible to hide. Cliff Click created a JVM that actually ran as a VM, in order to create a cheaper mark phase via page faulting to implement mark on write. Now we have other options.