Stricter checks on EDT violations in Substance
Most of the newcomers eventually find out that Swing is not thread-safe, but this is most certainly not Swing’s “fault”. Other UI toolkits, such as SWT, Win32 API, Motif, Xlib and GTK are not thread-safe as well (Chet Haase and Graham Hamilton have written on this topic a few years ago). It’s just that Swing is very lenient on the application code that violates the Event Dispatch Thread rules that state that every interaction with UI component must be done from the single UI thread (EDT). Unlike SWT that is much more rigorous in this aspect (checking access and throwing runtime exceptions), most Swing violations may go unnoticed for a long time, creeping to the production environment and making it very hard to debug / reproduce the scenarios on our development machines.
The automatic tracing of EDT violations has been a subject of extensive entries on Alex Potochkin’s blog about two years ago (part 1, part 2 and part 3) and his eventual conclusion was that it is highly unlikely that the EDT rules will be enforced by the core Swing runtime code.
As i already mentioned, these rules are very easy to break and quite tricky to track. I see a lot of “unorthodox” usage of Swing APIs from the users of Substance look-and-feel, and while most of it is correct, there are quite a few violations (quick search in the issue tracker came up with issues 156, 162, 163, 227, 283, 293 and 300). While most of these are manifested only under Substance due to a number of “behind-the-scenes” worker threads, nothing guarantees that these scenarios will not come up under other look-and-feels in the long term.
After thinking about this for a while i have decided to introduce a stricter EDT-related policy in the latest drops of the 5.0dev branch. A low-overhead check is done every time your application creates a Swing component that will have a UI delegate from Substance (in the “magic” static createUI method of all the UI delegates). In case an EDT violation is detected Substance will throw an IllegalStateException.
There are two issues to address here. The overall runtime performance should not be visibly affected. The check is only done when the component is created and not on every state change / paint / user interaction. While this does not go the whole way of more comprehensive techniques surveyed by Alex, it should detect quite a few rogue accesses. The second issue is that of potentially breaking the existing applications. This is an important issue for me as a library provider, but i do believe that it will result in better and more robust behavior of your applications in the long run.
The quicker you find a bug in your code, the easier it will be to fix. While this is not a compile-time check, the IllegalStateException will be thrown the very first time a component is created off EDT. Instead of postponing a possible application freeze / artifacts / data mangling / unpredictable behavior to your production environment, you will see the problem immediately on your development box. While this might be an annoyance in the short term, it should pay off greatly in the long term.
Going forward i do have plans to identify additional low-overhead candidates for checking EDT violations automatically inside Substance. This might involve accessing the models, views, listeners and other parts of the UI components.
The new policy is available in the latest drop of the core Substance library, as well as in the plugins for SwingX, Flamingo and JIDE components. As always, your feedback is highly appreciated.
Update: added a link to Graham Hamilton’s article (thanks to Javaposse for being better than Google)