0N/A<!--
2362N/A Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A
0N/A This code is free software; you can redistribute it and/or modify it
0N/A under the terms of the GNU General Public License version 2 only, as
2362N/A published by the Free Software Foundation. Oracle designates this
0N/A particular file as subject to the "Classpath" exception as provided
2362N/A by Oracle in the LICENSE file that accompanied this code.
0N/A
0N/A This code is distributed in the hope that it will be useful, but WITHOUT
0N/A ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A version 2 for more details (a copy is included in the LICENSE file that
0N/A accompanied this code).
0N/A
0N/A You should have received a copy of the GNU General Public License version
0N/A 2 along with this work; if not, write to the Free Software Foundation,
0N/A Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A
2362N/A Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A or visit www.oracle.com if you need additional information or have any
2362N/A questions.
0N/A-->
0N/A
0N/A<html>
0N/A<body bgcolor=white>
0N/A
0N/A<h1 align=center>AWT Threading Issues</h1>
0N/A
0N/A<a name="ListenersThreads"></a>
0N/A<h2>Listeners and threads</h2>
0N/A
0N/AUnless otherwise noted all AWT listeners are notified on the event
0N/Adispatch thread. It is safe to remove/add listeners from any thread
0N/Aduring dispatching, but the changes only effect subsequent notification.
0N/A<br>For example, if a key listeners is added from another key listener, the
0N/Anewly added listener is only notified on subsequent key events.
0N/A
0N/A<a name="Autoshutdown"></a>
0N/A<h2>Auto-shutdown</h2>
0N/A
4008N/AAccording to
4008N/A<cite>The Java&trade; Virtual Machine Specification</cite>,
4008N/Asections 2.17.9 and 2.19,
0N/Athe Java virtual machine (JVM) initially starts up with a single non-daemon
0N/Athread, which typically calls the <code>main</code> method of some class.
0N/AThe virtual machine terminates all its activity and exits when
0N/Aone of two things happens:
0N/A<ul>
0N/A <li> All the threads that are not daemon threads terminate.
0N/A <li> Some thread invokes the <code>exit</code> method of class
0N/A <code>Runtime</code> or class <code>System</code>, and the exit
0N/A operation is permitted by the security manager.
0N/A</ul>
0N/A<p>
0N/AThis implies that if an application doesn't start any threads itself,
0N/Athe JVM will exit as soon as <code>main</code> terminates.
0N/AThis is not the case, however, for a simple application
0N/Athat creates and displays a <code>java.awt.Frame</code>:
0N/A<pre>
0N/A public static void main(String[] args) {
0N/A Frame frame = new Frame();
0N/A frame.setVisible(true);
0N/A }
0N/A</pre>
0N/AThe reason is that AWT encapsulates asynchronous event dispatch
0N/Amachinery to process events AWT or Swing components can fire. The
0N/Aexact behavior of this machinery is implementation-dependent. In
0N/Aparticular, it can start non-daemon helper threads for its internal
0N/Apurposes. In fact, these are the threads that prevent the example
0N/Aabove from exiting. The only restrictions imposed on the behavior of
0N/Athis machinery are as follows:
0N/A<ul>
0N/A <li> <a href="/EventQueue.html#isDispatchThread()"><code>EventQueue.isDispatchThread</code></a>
0N/A returns <code>true</code> if and only if the calling thread is the
0N/A event dispatch thread started by the machinery;
0N/A <li> <code>AWTEvents</code> which were actually enqueued to a
0N/A particular <code>EventQueue</code> (note that events being
0N/A posted to the <code>EventQueue</code> can be coalesced) are
0N/A dispatched:
0N/A <ul>
0N/A <li> Sequentially.
0N/A <dd> That is, it is not permitted that several events from
0N/A this queue are dispatched simultaneously.
0N/A <li> In the same order as they are enqueued.
0N/A <dd> That is, if <code>AWTEvent</code>&nbsp;A is enqueued
0N/A to the <code>EventQueue</code> before
0N/A <code>AWTEvent</code>&nbsp;B then event B will not be
0N/A dispatched before event A.
0N/A </ul>
0N/A <li> There is at least one alive non-daemon thread while there is at
0N/A least one displayable AWT or Swing component within the
0N/A application (see
0N/A <a href="/Component.html#isDisplayable()"><code>Component.isDisplayable</code></a>).
0N/A</ul>
0N/AThe implications of the third restriction are as follows:
0N/A<ul>
0N/A <li> The JVM will exit if some thread invokes the <code>exit</code>
0N/A method of class <code>Runtime</code> or class <code>System</code>
0N/A regardless of the presence of displayable components;
0N/A <li> Even if the application terminates all non-daemon threads it
0N/A started, the JVM will not exit while there is at least one
0N/A displayable component.
0N/A</ul>
0N/AIt depends on the implementation if and when the non-daemon helper
0N/Athreads are terminated once all components are made undisplayable.
0N/AThe implementation-specific details are given below.
0N/A
0N/A<h3>
0N/AImplementation-dependent behavior.
0N/A</h3>
0N/A
0N/APrior to 1.4, the helper threads were never terminated.
0N/A<p>
0N/AStarting with 1.4, the behavior has changed as a result of the fix for
3910N/A<a href="http://bugs.sun.com/view_bug.do?bug_id=4030718">
0N/A4030718</a>. With the current implementation, AWT terminates all its
0N/Ahelper threads allowing the application to exit cleanly when the
0N/Afollowing three conditions are true:
0N/A<ul>
0N/A <li> There are no displayable AWT or Swing components.
0N/A <li> There are no native events in the native event queue.
0N/A <li> There are no AWT events in java EventQueues.
0N/A</ul>
0N/ATherefore, a stand-alone AWT application that wishes to exit
0N/Acleanly without calling <code>System.exit</code> must:
0N/A<ul>
0N/A <li> Make sure that all AWT or Swing components are made
0N/A undisplayable when the application finishes. This can be done
0N/A by calling
0N/A<a href="/Window.html#dispose()"><code>Window.dispose</code></a>
0N/A on all top-level <code>Windows</code>. See
0N/A<a href="/Frame.html#getFrames()"><code>Frame.getFrames</code></a>.
0N/A <li> Make sure that no method of AWT event listeners registered by
0N/A the application with any AWT or Swing component can run into an
0N/A infinite loop or hang indefinitely. For example, an AWT listener
0N/A method triggered by some AWT event can post a new AWT event of
0N/A the same type to the <code>EventQueue</code>.
0N/A The argument is that methods
0N/A of AWT event listeners are typically executed on helper
0N/A threads.
0N/A</ul>
0N/ANote, that while an application following these recommendations will
0N/Aexit cleanly under normal conditions, it is not guaranteed that it
0N/Awill exit cleanly in all cases. Two examples:
0N/A<ul>
0N/A <li> Other packages can create displayable components for internal
0N/A needs and never make them undisplayable. See
3910N/A<a href="http://bugs.sun.com/view_bug.do?bug_id=4515058">
0N/A4515058</a>,
3910N/A<a href="http://bugs.sun.com/view_bug.do?bug_id=4671025">
0N/A4671025</a>, and
3910N/A<a href="http://bugs.sun.com/view_bug.do?bug_id=4465537">
0N/A4465537</a>.
0N/A <li> Both Microsoft Windows and X11 allow an application to send native
0N/A events to windows that belong to another application. With this
0N/A feature it is possible to write a malicious program that will
0N/A continuously send events to all available windows preventing
0N/A any AWT application from exiting cleanly.
0N/A</ul>
0N/AOn the other hand, if you require the JVM to continue running even after
0N/Athe application has made all components undisplayable you should start a
0N/Anon-daemon thread that blocks forever.
0N/A
0N/A<pre>
0N/A <...>
0N/A Runnable r = new Runnable() {
0N/A public void run() {
0N/A Object o = new Object();
0N/A try {
0N/A synchronized (o) {
0N/A o.wait();
0N/A }
0N/A } catch (InterruptedException ie) {
0N/A }
0N/A }
0N/A };
0N/A Thread t = new Thread(r);
0N/A t.setDaemon(false);
0N/A t.start();
0N/A <...>
0N/A</pre>
0N/A
4008N/A<cite>The Java&trade; Virtual Machine Specification</cite>
4008N/A guarantees
0N/Athat the JVM doesn't exit until this thread terminates.
0N/A</body>
0N/A</html>