The garbage collector was a problem and as usually it required us to profile and pay attention to memory access patterns, plus a lot of tuning of that garbage collector. But truth be told, we were also much sloppier than what people do in the financial industry. For example we did use Scala, functional programming and immutable data-structures, which ca bring with it significant overhead, since the profile of persistent collections does not match the assumptions of current generational garbage collectors. But on the JVM you also have options not available on other platforms. The G1 GC is pretty advanced and at scale the commercial Azul Zing promises a pauseless GC and has been used successfully in the financial industry.
I also used Erlang and in my experience the JVM can achieve much lower latency and better throughput. Where Erlang systems tend to shine is in being more resilient and adaptable.