AWT Threading Issues

According to The JavaTM Virtual Machine Specification, Second edition (see §2.17.9 and §2.19), the Java virtual machine (JVM) initially starts up with a single non-daemon thread, which typically calls the main method of some class. The virtual machine terminates all its activity and exits when one of two things happens:

This implies that if an application doesn't start any threads itself, the JVM will exit as soon as main terminates. This is not the case, however, for a simple application that creates and displays a java.awt.Frame:

        public static void main(String[] args) {
            Frame frame = new Frame();
            frame.setVisible(true);
         }
The reason is that AWT encapsulates asynchronous event dispatch machinery to process events AWT or Swing components can fire. The exact behavior of this machinery is implementation-dependent. In particular, it can start non-daemon helper threads for its internal purposes. In fact, these are the threads that prevent the example above from exiting. The only restrictions imposed on the behavior of this machinery are as follows: The implications of the third restriction are as follows: It depends on the implementation if and when the non-daemon helper threads are terminated once all components are made undisplayable. The implementation-specific details are given below.

Implementation-dependent behavior.

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:

Therefore, a stand-alone AWT application that wishes to exit cleanly without calling System.exit must: Note, that while an application following these recommendations will exit cleanly under normal conditions, it is not guaranteed that it will exit cleanly in all cases. Two examples: On the other hand, if you require the JVM to continue running even after the application has made all components undisplayable you should start a non-daemon thread that blocks forever.
	<...>
	Runnable r = new Runnable() {
	    public void run() {
	        Object o = new Object();
		try {
		    o.wait();
		} catch (InterruptedException ie) {
		}
            }
	};
	Thread t = new Thread(r);
	t.setDaemon(false);
	t.start();
	<...>
The Java Virtual Machine Specification guarantees that the JVM doesn't exit until this thread terminates.