New Class: UIDefaults.UIDefaultProxy, Related Performance Changes
One of the main reasons that Swing's startup performance
was slower than desired was that as soon as any component
requires a UI delegate, the UIManager loads a look and feel,
which results in loading a defaults table which includes
defaults for UIs for all component classes.
In previous releases, we mistakenly believed that instance
creation should be avoided, and so we delayed instance
creation by creating anonymous implementations of
LazyValue, an interface which acts as a lightweight proxy
that only creates its instance the first time it is retrieved
from the defaults table.
Performance analysis for Kestrel indicates that we were wrong
in believing that instance creation was the determining factor.
In fact, the overwhelming factor contributing to delay and
increased footprint in this area was classloading, which was
ironically not helped by our creation of lots of anonymous
interface implementations!
The general approach taken to fix this was to define a concrete
LazyValue implementation in UIDefaults.java which uses reflection
to create its proxied instance when asked to do so. This class
is called UIDefaultProxy. As a result only one class is loaded,
and about 90 other classloads could be avoided in a Hello World
example.
See: UIDefaults.UIDefaultProxy
In the course of replacing the existing anonymous LazyValue
implementations and identifying other classloads that could
be avoided, we came across several classes and accessor methods
which were incorrectly package private. Since the UIDefaultProxy
is in the javax.swing package, and most of the uses are in
javax.swing.plaf.* packages, these signatures needed to be changed
so that they could be used by the proxy.