Skip to main content

JDK 6u14 almost ready at b05; Making Java load faster and lighter

Posted by opinali on April 24, 2009 at 8:52 AM PDT

I previously reported the highlights of b01 and b02. Following that, b03 was another round of stabilization and small features: fixed some critical compiler2 (HotSpot Server) bugs; closed an important Java2D perf bug (XOR rendering); allowed JavaFX (and other advanced gfx runtimes) to do custom font hinting; allowed users to customize java.lang.Integer's valueOf() cache (smells like a benchmark-oriented feature); optimized Nimbus's initialization for JavaFX (perhaps also for Swing apps?); optimized StAX's memory management (apparently big impact on XML messaging); and closed another round of minor plugin2/JAWS bugs. This build also introduced (in experimental stage) some important enhancements to the Treemap, HashMap and BigDecimal classes - apparently a joint Apache/Sun effort that was discussed for example in David Dagastine's blog (and yes, Sun has finally released their improvements back to Harmony).

Then b04 was a less exciting build with an important backport of G1 fixes, a critical Vista detection fix, and the final round of plugin2/JAWS bugs.

Now b05 is even less interesting (great news: converging to FCS) with a bunch of Lazy Loading optimizations and nothing very important.

I am very interested in anything that makes Java load faster and consume less resources, it's perhaps the biggest challenge for Java in the desktop (with either JavaFX, Swing or whatever toolkit that's dear to you). I compared the latest stable JRE (6u13) to 6u14b05 with my JavaFX Balls 2 benchmark. The test is very simple: launch the program as an application from the command line (javafx -verbose:class -classpath JavaFXBalls.jar javafxballs.MainDesktop), collect the classloading logs, sort and diff them. Result:

  • JRE 6u13 loads 3159 classes; 6u14b05 loads 3024 (135 classes or 4,3% less).
  • JRE 6u14b05 avoids 149 classes that 6u13 loads, but it loads 14 classes that 6u13 doesn't.
  • A tally of the saved classes: 55 from com.sun.java.swing.plaf.nimbus; 26 from java.awt and sun.awt; 15 from java.io, sun.misc.JavaIO* and sun.nio.ch; 25 from java.util.regex; 15 from sun.text.normalizer (Unicode stuff). Overall, a pretty good cleanup of useless dependencies.
  • Room for improvement? From the 3024 classes that my program still loads, I see: 64 from com.sun.crypto.provider and javafx.crypto (loading triggered by JarVerifier); 80 from com.sun.net.ssl.internal.ssl and javax.net.ssl (triggered apparently by the networking/HTTP APIs); 28 from java.util.regex (apparently triggered by Nimbus style support); and... horror!! 183 from javax.swing (including such things as JColorChooser, JMenu - apparently all this stuff triggered also by the Nimbus style support).

I understand why the JRE uses the security and SSL APIs, so I added -Xverify:none and voilá ! Only 2922 classes loaded, another cut of 102 classes or 3,3% of the normal 6u14b05 number. But we can't possibly get rid of this overhead for apps deployed over the net.

But JavaFX apps can still get rid of further Swing dependencies. JavaFX needs some Swing classes, remarkably the core of Nimbus, I guess for such needs as desktop preferences (colors etc.), sharing low-level support to create a window, handling events etc. But Swing (or Nimbus) appears to have a styling framework that loads virtually all Swing component classes - I guess it's building some kind of Map<component class, configuration data>. This could perhaps be done lazily. If JavaFX needs the same config data, I guess that repository could be refactored to not be hardwired to Swing classes. Just some wild guesses, I'm not familiar with the source code form either Swing or the JavaFX runtime, or even with the styling/theming facilities of either. Fixing this dependency could save almost 200 classes, another significant reduction of 6,6% of all classes loaded by the latest 6u14 build. Remember that these classes not only need to be loaded from the rt.jar, they must be linked, verified, some code executed in interpreted mode (static initializers), lots of metadata created to hang around in the heap forever..., even if they never get a single object instantiated or a single method invoked.

And if you allow me to repeat my own comment from a previous blog, I would love the opinion of the Sun JDK developers and other JVM hackers who really understand this issue:

A quasi-instant loading time (as well as better resource usage) is possible for JavaFX (and even for Swing), but I'm afraid if it depends on more radical JRE changes than Sun seems committed to do now. Some personal ideas:

- Much better CDS;
- Ahead-of-time compilation of the core APIs (at least for HotSpot Client);
- Improvements to the classfile specification to allow compile-time construction and fast loading of complex ConstantPool literals (so classloading time is not increased by the execution of a ton of bytecode to initialize static vars).

The reason why Flash initializes instantly is that its runtime is a big blob of plain old C/C++ code, compiled to a efficient, monolithic piece of native code that the OS is able do load/link/relocate/init with light speed.

Sun is right now optimizing in a higher level (like several lazy loading refactorings). They also promise that Jigsaw (in JDK 7) will further improve loading time, but I'm not holding my breath to see a sub-second startup (even warm start) of any nontrivial JavaFX applet (or Swing, for that matter) only with those improvements. Let's hope I'm proven wrong.

Related Topics >>