I remember a debate with a colleague five years ago about the merits of dynamic compilation versus static compilation. He was arguing that .NET was ‘better’ than Java because .NET had an
ngen utility for AOT native code generation. Of course, he favoured straight C++ even more because it was unmanaged; he felt that the management in managed systems just slowed things down.
I disagreed strongly with him at the time, citing the capabilities of the JIT compiler in Java at the time (it was at 1.4 back in those days, if I remember right; right about the time when there was that big fight between log4j versus
java.util.logging). Well, of course, it's improved a lot since then, and I'm especially happy with the capabilities of Java 6 in the performance department!
John Rose (the mastermind behind the Da Vinci Machine project) has a page detailing all the various optimisations currently in place in Hotspot; there are sure to be even more optimisations for dynamic code invocation to come up.
On a related topic, I was perusing the OpenJDK 6 code today, and I learnt about a really cool technique they use in reflection (yes, I'm aware that the technique was implemented even in the 1.4 days, but OpenJDK code is easier to obtain, so that's what I'm looking at). Now, assuming that you, the reader, are not an expert in Java's core library implementation, how would you go about implementing reflection? Have a think about it, then read on (if you want to).
If you've played with JNI at all, I would presume you'd probably be thinking of that. Just write a native method that simply calls the JNI's builtin reflection functionality (or some shortcut thereto in the JVM). This, indeed, does work, and is one way that OpenJDK 6 does it.
It has a much cooler technique, though, called “inflation”. Inflation means that for the first few runs (default 15) of a reflected method/constructor (from now on, any reference to methods applies to constructors too), it does so via JNI; the next time after that, it assembles a class file on the fly, and loads it. At that point, full JITting applies, and further calls to that reflected method has the same performance as directly calling that method.
You can even disable inflation completely (set the
sun.reflect.noInflation property to true), in which case the JNI approach is skipped completely, and all reflected method calls are assembled to class files straight away. Alternatively, you can tune the number of runs before the assembly occurs (use the
If that's not cool, I don't know what is!