After the introduction of Java Memory Model, the Swing guidelines were changed to state that any Swing components need to be instantiated on the EDT in order to avoid non-published instance state.
What I could not find anywhere is whether the classloading is also mandated to be on the EDT or can we pre-load key Swing classes in a background thread? Is there any official statement from Sun/Oracle on this? Are there any classes that are known to hold non-threadsafe static state, hence need to be loaded on EDT?
Clarification to address Nemi's question: this is a practical issue. A sizable portion of our application's startup time, is spent classloading, and font/image-loading on the EDT. Most of this can be attributed to Swing and related libraries.
Here is som background: As many other Swing apps, on startup we are pre-constructing many forms, in order to make the UI more responsive. After profiling, we found that the actual time for form construction is relatively fast - what's slow is loading of all classes and fonts (disk reads are slow in corporate setup with on-access virus scanner, surveilance scanner, audit tracker and god knows what else tacked on the HDD driver).
We tried to construct the same forms in a background thread (violating Swing's rules) and then throw them away. Once we are done we construct the same forms on the EDT, which is much faster as all classes are loaded and any other files are in the disk cache. It works for us, and we'll probably keep doing it unless something really bad happens.
What I'm asking is whether this is a safe practice, a good practice or a hack?
The evidence seems to suggest it is safe - but then again, as ddimitrov says in the comments - the odds are in favor of not finding subtle thread bugs due to non-published changes because typical machines have only a few cores, and L2/L3 caches are shared. (L1 caches are per core, but usally very small.)
If you want to guarantee no problem arises because of the background classloading, then it's probably safest to stick to loading classes on the ETD. To maintain a live UI, create a custom class loader that also pumps events in-between loading each class. (Dependencies are loaded re-entrantly so the delay would only be for the duration of loading just one class.) Assuming this class loader is packaged with your application, then it can simply defer all class loading to it's classloader.
Alternatively, Secondary event queues can be spanwed that run on separate threads (e.g. modal dialogs, and the spin library). This implies Swing can run on any thread, as long as it runs on just one, and means that it must be update-consistent (or that we've all just been very lucky so far!) On the basis of this, you could load your classes on the primary EDT, and start a secondary EDT to pump the UI events, keeping the UI responsive - in the same way a modal dialog functions. The Spin utility will pump EDT events for you, or you can spawn a new EDT by hand.
It is safe. See: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html (the single thread rule)
If you are afraid or want some feedback / debug, have a look at this FEST/Swing tool: http://fest.easytesting.org/swing/wiki/pmwiki.php?n=FEST-Swing.EDT ("Testing that access to GUI components is done in the EDT") -- it is a custom RepaintManager
that fails when you violate the EDT access policy.
You may find this helpful as well: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html
They don't mention class loading explicitly, but they do explain what the EDT access policy is about.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With