The JVM engineers have been free to do whatever they want in terms of optimizations at runtime, like code inlining or escape analysis. They may even add trace compilation or whatever they feel like it's necessary. The JVM's GC is precise and generational. The CMS garbage collection rarely blocks the whole process and you've got options for GCs that are totally non-blocking. In fact, the JVM's GC is so efficient that allocating and deallocating short-lived objects is almost as efficient as doing that on the stack.
Russ Cox speaks about the boxing that Java does, but Java makes boxing almost a non-issue. Personally I've learned to appreciate the JVM and what it can do in the context of servers receiving tens of thousands of requests per second.
And here in lies the problem - Go is too low level to achieve the same level of optimizations that Java is able of. But on the other hand it's totally dependent on a per-process GC and personally I don't think we'll ever see a precise, generational GC for it precisely because Go is too low level. The Rust engineers at the very least redefined the problem by making individual threads in a process have their own heap and their own garbage collector.
Go on the other hand feels like a hack on multiple accounts. And to me it's not a beautiful hack either, plus once a language achieves inertia, you cannot change its fundamentals without redefining the language to be something else entirely. If Go will indeed get popular, it will join a long line of languages that people hate, because they have to maintain code-bases written in it, with no easy way out.
Its authors say they don't want Go to be like C++. In many ways, it already is.