I remember the days when the JVM only had mark and sweep GC and it interpreted bytecodes. I remember when the JIT kept on crashing, and Java apps were catching up to Smalltalk VMs on benchmarks, but wheezing on real apps because of poor GC. Then there was generational GC, but lots of real apps were still wheezing because no one knew how to tune the GC settings. It took a decade for the JVM to cover the same ground the Smalltalk VMs had covered 4 or 5 before it.
Now the JVM is mature, and it fricken kicks ass! Really, for a high-level OO language supporting VM, the thing just screams. It's still unwieldy and much better suited to server stuff, but as a Smalltalker and therefore a former longtime Java detractor, I have to say, I am really impressed.
"Java is COBOL of nineties. Future generations of programers will fly here from the Moon to piss on our graves for inflicting it upon them."