Java AWT-Shutdown Thread Refuses to Die
Developer's Cave, Potential RPG February 9th. 2010, 6:37pmThe cleanest way to close a Java GUI application is to dispose of all top-level resources (JFrame instances, for example) and allow the AWT/Swing thread to close itself. Calling System.exit(0) or Runtime.getRuntime().halt(0) is often prescribed, but not recommended, as it could preempt proper shutdown procedures in your application.
If your Java GUI application uses DISPOSE_ON_CLOSE mode, check that your process is exiting cleanly. If it is not, the most likely culprit is that the AWT Event Dispatch Thread is still active. This is well-known AWT/Swing behavior, but there is a scenario in which Java will refuse to shut down this thread, even with all resources closed and disposed.
Java’s Abstract Windowing Toolkit (AWT), upon which the Swing libraries are built, employs a kind of guardian thread, named “AWT-Shutdown.” If your application process is not closing as expected, consider inserting this snippet of debugging code, which will reveal which (non daemon) threads are hanging around:
for (Thread thread : Thread.getAllStackTraces().keySet()) { // daemon threads will not prevent shutdown if (!thread.isDaemon()) { System.err.println("Stalled thread: " + thread); } }
Look for threads named “AWT-Shutdown” and “AWT-EventQueue” in the output. What is happening is the Shutdown guardian thread refuses to shut down the EventQueue while it is busy. The details are explained on the Pushing Pixels blog, which is what inspired this approach.
In brief, even if all of your AWT/Swing resources have been disposed of, if any part of your code is actively queuing events to the EventQueue, the AWT-Shutdown thread will consider it to still be active. The EventQueue must remain inactive for some timeout before the Shutdown thread will stop it.
Begin with a search for calls to SwingUtilities.invoke*, which put tasks onto the EventQueue. If this does not reveal the offending events (or you do not have the source), consider using this snippet to catch the EventQueue in the act:
Object event = null; while (event == null) { event = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().peekEvent(); } System.err.println(event);
I used the above techniques to identify a periodic task being put onto the EventQueue, preventing its natural demise. The output from above gave me the class name of the associated event. To clean up my application’s termination, I now explicitly stop the process that was queuing these events upon application shutdown. Now, the application (the Potential RPG client) comes to a quicker, cleaner, natural halt when closed.












