My understanding is that GCC has a more diverse arsenal of optimizations that it can apply to code while hotspot has the advantage that it can profile at runtime and apply speculative optimizations based on those profiles and bail out later if things change. In principle it can even optimize code that never reaches steady state as long as the transient states last long enough.
What costs java performance these days is not the quality of the JIT compilers or even the garbage collectors. It's the object layout that is not very cache-friendly. There is lots of pointer-chasing going on since there are no arrays-of-structs.
Valhalla[0] promises to improve the data layout issue at some point in the future while graal may allow compiler writers to cram some more optimizations into the jits.
Indeed. Another issue is that java semantics is too rigidly defined. Compilers of many other languages have a lot more room in deciding order of evaluation, vectorization etc
Java tries to provide semi-sane behavior even in the presence of data races. Carefully constructed code can give you benign behavior even under racy data accesses.
If you relaxed some compiler constraints, e.g. allowed it to re-read local variables because they were discarded due to register pressure then those benign races would suddenly turn into non-benign ones.
What costs java performance these days is not the quality of the JIT compilers or even the garbage collectors. It's the object layout that is not very cache-friendly. There is lots of pointer-chasing going on since there are no arrays-of-structs.
Valhalla[0] promises to improve the data layout issue at some point in the future while graal may allow compiler writers to cram some more optimizations into the jits.
[0] http://openjdk.java.net/projects/valhalla/