It usually makes sense to talk about the memory overhead of the JVM itself, rather than talking about one of the languages specifically, like Java or Kotlin (but maybe Scala and Clojure are a bit different).
The tradeoffs for GC systems are complicated and not easy to understand. Go supports only one GC system, as far as I know, which does not move memory and attempts to minimize GC pauses. It sacrifices throughput and CPU utilization to achieve this.
The JVM can be tuned in many ways and there are a number of different options, from choosing different GC algorithms to different memory models. Most JVM algorithms will compact memory. Some are optimized for throughput and others are optimized for shorter pauses.
In practice, my observation is that Go’s GC pauses are, out of the box, shorter than what most people will get by tuning the JVM. This is probably the most critical property for writing backend services with high fanout, which is very common at places like Google.
However, the throughput penalty is very real and e.g. compiling a large codebase I’d much rather have throughput tuning.
The drawback of both Go and Rust for our group was that Java developers were so much more abundant in our market(not major technology hub city in the South).
I think cities with smaller amounts of talent have the same problem when trying to find Go and Rust developers of all skill levels.