The best choice of virtual machine is of course dependent both on the application and on the hardware the application is running on; here are the conclusions of a performance comparison with the latest batch of Java virtual machines for a web application that makes heavy use of BerkeleyDB and Lucene on an off-the-shelf Intel machine with 64-bit extensions.

The test consisted of running a set of a hundred requests several times. The first few runs were ignored (though it could also have been interesting to compare how fast a virtual machine warms up). I allocated 0.5GB of heap but didn’t bother fine tuning further as jconsole didn’t show any pathological garbage collector behavior in any case. JRockit was run with both -Xgcprio:throughput and -Xgcprio:pausetime. Former produces slightly better times but can have long pauses.

The following virtual machines were tested:

The first observation is that all of the current virtual machines are significantly (up to 50%) faster than any of the previous generation.

The second observation is that I could no longer find any significant differences between the different virtual machines.

…except when using 64-bit versions of the virtual machines. Having to manage 64-bit pointers seems to introduce some overhead (up to 20%), so unless you need to allocate >4GB of heap memory or memory-map large files (or run on a pure 64-bit machine, not tested), sticking with a 32-bit virtual machine seems like a good idea. JRockit uses pointer compression to avoid this problem (as long as you don’t need to allocate >4GB of memory).

All virtual machines were trivial to setup, I only had some trouble getting the web application to deploy (in Jetty) with the IBM VM (still in beta), fixed by copying Xerces to lib/ext/:

WEB-INF/lib/standard.jar!/META-INF/fmt-1_0.tld line:1 col:5 :
  org.xml.sax.SAXParseException: White space is required between the processing instruction target and data.