Stricter checks on EDT violations in Substance
July 15th, 2008 | 8 Comments »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)
Related posts:
- New article on Swing EDT violations There’s a new article that has been published today on java.net titled Debugging Swing. It...
I for one welcome our EDT Violations checking overlords.
You can add Windows Forms, WPF, and Silverlight to that list of UI toolkits that are not thread-safe.
I think this is a good idea. I think that in general it is better to fail catastrophically up front, instead of failing in suttble ways later on. It should also help reduce the load on you as you will no longer need to help track down hard to diagnose bugs, that turn out to be a problem in others code.
That said, be sure to make sure the IllegalStateException contains plenty of information that allows developers to figure out what the problem is. It may even be better to subclass IllegalStateException – creating some kind of org.jvnet.substance.EdtThreadingViolationException.
That way people can look up the java doc for EdtThreadingViolationException, and get a detailed explanation of whats going wrong and why swing is single threaded.
+1 for EDT checks.
Wouldn’t it be nice if you were checking EDT violations in every UI methods like SWT does, but with the “assert” keyword? If my understanding is correct, this would have no impact on performance, and users could turn assertions on in case of a problem.
Luke – excellent suggestion. I will most probably do this in the next few days.
Christopher – remember that i am “in charge” of the UI delegates, not components themselves. So, if an application decides to call JTextField.setText off EDT, then i can potentially detect that by registering a document listener on every text field and see if the insertUpdate (in my own event handler) gets called off EDT. If it does, then *in the current implementation of JVM* the originating code was off EDT.
There are two problems with this. First, not everything is possible to catch in UI delegates. For example, you call button.isSelected off EDT – unless i install a custom button model on each button instance, i won’t be able to catch that. Second, even things that can be caught might require extensive wiring of listeners (much more than Substance currently does). This will result in a larger footprint *and* performance impact even with asserts.
I need to find the right balance between “educating” rogue Swing applications that decide to use Substance and not transgressing into the thread-checking library. This is very much work in progress.
Thanks
Kirill
You probably have to listen to many property change events in the UI delegates, in which I think such assert would make sense.
Should not there be an option to enable/disable this feature? One of my application does lots of things off EDT during startup process to give better user experience and now Substance 5 breaks that :-(
Vinod – there are clear UI threading rules in Swing, and it’s not Substance that breaks your UI experience. There are ways to use helper threads to perform non-UI tasks, and you are highly advised to use those to make sure that your application doesn’t suddenly freeze in a non-reproducible manner in a production environment. At the present moment i do not have plans to rollback this feature; furthermore i plan to identify additional low-overhead places to trace EDT violations.
Thanks
Kirill