AWT shutdown and daemon threads
About half a year ago Christopher Deckers had a guest spot post on this blog about a non-daemon WebStart thread that prevents JVM from exiting when you’re closing your last Swing window running under the DISPOSE_ON_CLOSE mode. To illustrate the problem with the current implementation of WebStart helper threads, he posted the following excerpt from the AWT threading documentation:
Prior to 1.4, the helper threads were never terminated. Starting with 1.4, the behavior has changed as a result of the fix for 4030718. With the current implementation, AWT terminates all its helper threads allowing the application to exit cleanly when the following three conditions are true:
- There are no displayable AWT or Swing components.
- There are no native events in the native event queue.
- There are no AWT events in java EventQueues.
There is an additional clarification to the last item in the same document:
Make sure that no method of AWT event listeners registered by the application with any AWT or Swing component can run into an infinite loop or hang indefinitely. For example, an AWT listener method triggered by some AWT event can post a new AWT event of the same type to the
EventQueue
. The argument is that methods of AWT event listeners are typically executed on helper threads.
So, as long as you don’t post another event from your event handler or hang indefinitely, you should be OK, right? That is not entirely correct, since the current implementation of the last item (at least in Sun’s VM) makes an additional restriction on shutting down the AWT queues in absence of events.
The relevant class in Sun’s VM is sun.awt.AWTAutoShutdown and it has additional logic on top of the official documentation (relevant part is highlighted by me):
The internal AWTAutoShutdown logic secures that the single non-daemon thread is running when AWT is not in ready-to-shutdown state. This blocker thread is to prevent AWT from exiting since the toolkit thread is now daemon and all the event dispatch threads are started only when needed. Once it is detected that AWT is in ready-to-shutdown state this blocker thread waits for a certain timeout and if AWT state doesn’t change during timeout this blocker thread terminates all the event dispatch threads and exits.
In the current implementation this timeout is 1000 ms (or one second). What this effectively means that AWT is not shutdown immediately after disposing the last window in your application and processing all pending events. Instead, it wakes every second, checks for any pending or processed events during the sleep and continues sleeping if there have been any such events.
How can this affect your application? In my case, i have a daemon thread that wakes up every 100ms and synchronizes the visual state of certain components. Since everything UI-related must run on the Event Dispatch Thread, i wrap each iteration loop inside the SwingUtilities.invokeLater (otherwise i run into sporadic deadlocks). As far as AWT is concerned, such an invocation is an event which effectively prevents AWT from shutting down.
Bottom line is that you should be careful with calling SwingUtilities.invokeLater from daemon threads in applications using DISPOSE_ON_CLOSE. Before calling that method you can check that the relevant component is visible and showing. If both are true it means that the window of that component is still not disposed.
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)
Swing links of the week: July 13, 2008
Here are some Swing links that you might have missed during this week:
- James Williams has a tongue-in-cheek list of five tips to tame Matisse layouts. This resonates with my earlier post on JBuilder and getting locked to an IDE that enforces any non-standard logic on the UI code that it creates.
- Luan O’Carroll writes about distributing a WebStart application via CD-ROM, expanding on such subjects as WebStart cache, not relying on existing JRE installations, working with no Internet connection and others.
- Build 27 of 6u10 is out and it addresses the issue that prevented applications from using the Synthetica look-and-feel. It also features performance improvements for Nimbus (about 8% as measured in the dynamic performance suite from the LightBeam project). Although not official, we can expect the release candidate of 6u10 this week.
- Ken Orr writes about a custom implementation of placard button commonly found in Mac applications.
- Alexander Potochkin introduces yet another useful feature of his JXLayer project – ability to lock (disable) the entire Swing container, including blocking any user interaction with its children.
- The “Ask the Experts” session on 6u10 is over, and (much like two years ago), i had a question that was not addressed. I will be polite and blame the intratubes, but the topic at hand will be a subject of a forthcoming entry.