blob: 6b918188fdc762ec70ba8cfc8b3ea41eec83e264 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001<!--
2 Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 This code is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License version 2 only, as
7 published by the Free Software Foundation. Sun designates this
8 particular file as subject to the "Classpath" exception as provided
9 by Sun in the LICENSE file that accompanied this code.
10
11 This code is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 version 2 for more details (a copy is included in the LICENSE file that
15 accompanied this code).
16
17 You should have received a copy of the GNU General Public License version
18 2 along with this work; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 CA 95054 USA or visit www.sun.com if you need additional information or
23 have any questions.
24-->
25
26<html>
27<body bgcolor=white>
28
29<h1 align=center>AWT Threading Issues</h1>
30
31<a name="ListenersThreads"></a>
32<h2>Listeners and threads</h2>
33
34Unless otherwise noted all AWT listeners are notified on the event
35dispatch thread. It is safe to remove/add listeners from any thread
36during dispatching, but the changes only effect subsequent notification.
37<br>For example, if a key listeners is added from another key listener, the
38newly added listener is only notified on subsequent key events.
39
40<a name="Autoshutdown"></a>
41<h2>Auto-shutdown</h2>
42
43According to <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html"><i>The
44Java</i><sup><small>TM</small></sup> <i>Virtual Machine Specification,
45Second edition</i></a> (see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#19152">§2.17.9</a>
46and <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#33308">§2.19</a>),
47the Java virtual machine (JVM) initially starts up with a single non-daemon
48thread, which typically calls the <code>main</code> method of some class.
49The virtual machine terminates all its activity and exits when
50one of two things happens:
51<ul>
52 <li> All the threads that are not daemon threads terminate.
53 <li> Some thread invokes the <code>exit</code> method of class
54 <code>Runtime</code> or class <code>System</code>, and the exit
55 operation is permitted by the security manager.
56</ul>
57<p>
58This implies that if an application doesn't start any threads itself,
59the JVM will exit as soon as <code>main</code> terminates.
60This is not the case, however, for a simple application
61that creates and displays a <code>java.awt.Frame</code>:
62<pre>
63 public static void main(String[] args) {
64 Frame frame = new Frame();
65 frame.setVisible(true);
66 }
67</pre>
68The reason is that AWT encapsulates asynchronous event dispatch
69machinery to process events AWT or Swing components can fire. The
70exact behavior of this machinery is implementation-dependent. In
71particular, it can start non-daemon helper threads for its internal
72purposes. In fact, these are the threads that prevent the example
73above from exiting. The only restrictions imposed on the behavior of
74this machinery are as follows:
75<ul>
76 <li> <a href="../EventQueue.html#isDispatchThread()"><code>EventQueue.isDispatchThread</code></a>
77 returns <code>true</code> if and only if the calling thread is the
78 event dispatch thread started by the machinery;
79 <li> <code>AWTEvents</code> which were actually enqueued to a
80 particular <code>EventQueue</code> (note that events being
81 posted to the <code>EventQueue</code> can be coalesced) are
82 dispatched:
83 <ul>
84 <li> Sequentially.
85 <dd> That is, it is not permitted that several events from
86 this queue are dispatched simultaneously.
87 <li> In the same order as they are enqueued.
88 <dd> That is, if <code>AWTEvent</code>&nbsp;A is enqueued
89 to the <code>EventQueue</code> before
90 <code>AWTEvent</code>&nbsp;B then event B will not be
91 dispatched before event A.
92 </ul>
93 <li> There is at least one alive non-daemon thread while there is at
94 least one displayable AWT or Swing component within the
95 application (see
96 <a href="../Component.html#isDisplayable()"><code>Component.isDisplayable</code></a>).
97</ul>
98The implications of the third restriction are as follows:
99<ul>
100 <li> The JVM will exit if some thread invokes the <code>exit</code>
101 method of class <code>Runtime</code> or class <code>System</code>
102 regardless of the presence of displayable components;
103 <li> Even if the application terminates all non-daemon threads it
104 started, the JVM will not exit while there is at least one
105 displayable component.
106</ul>
107It depends on the implementation if and when the non-daemon helper
108threads are terminated once all components are made undisplayable.
109The implementation-specific details are given below.
110
111<h3>
112Implementation-dependent behavior.
113</h3>
114
115Prior to 1.4, the helper threads were never terminated.
116<p>
117Starting with 1.4, the behavior has changed as a result of the fix for
118<a href="http://developer.java.sun.com/developer/bugParade/bugs/4030718.html">
1194030718</a>. With the current implementation, AWT terminates all its
120helper threads allowing the application to exit cleanly when the
121following three conditions are true:
122<ul>
123 <li> There are no displayable AWT or Swing components.
124 <li> There are no native events in the native event queue.
125 <li> There are no AWT events in java EventQueues.
126</ul>
127Therefore, a stand-alone AWT application that wishes to exit
128cleanly without calling <code>System.exit</code> must:
129<ul>
130 <li> Make sure that all AWT or Swing components are made
131 undisplayable when the application finishes. This can be done
132 by calling
133<a href="../Window.html#dispose()"><code>Window.dispose</code></a>
134 on all top-level <code>Windows</code>. See
135<a href="../Frame.html#getFrames()"><code>Frame.getFrames</code></a>.
136 <li> Make sure that no method of AWT event listeners registered by
137 the application with any AWT or Swing component can run into an
138 infinite loop or hang indefinitely. For example, an AWT listener
139 method triggered by some AWT event can post a new AWT event of
140 the same type to the <code>EventQueue</code>.
141 The argument is that methods
142 of AWT event listeners are typically executed on helper
143 threads.
144</ul>
145Note, that while an application following these recommendations will
146exit cleanly under normal conditions, it is not guaranteed that it
147will exit cleanly in all cases. Two examples:
148<ul>
149 <li> Other packages can create displayable components for internal
150 needs and never make them undisplayable. See
151<a href="http://developer.java.sun.com/developer/bugParade/bugs/4515058.html">
1524515058</a>,
153<a href="http://developer.java.sun.com/developer/bugParade/bugs/4671025.html">
1544671025</a>, and
155<a href="http://developer.java.sun.com/developer/bugParade/bugs/4465537.html">
1564465537</a>.
157 <li> Both Microsoft Windows and X11 allow an application to send native
158 events to windows that belong to another application. With this
159 feature it is possible to write a malicious program that will
160 continuously send events to all available windows preventing
161 any AWT application from exiting cleanly.
162</ul>
163On the other hand, if you require the JVM to continue running even after
164the application has made all components undisplayable you should start a
165non-daemon thread that blocks forever.
166
167<pre>
168 <...>
169 Runnable r = new Runnable() {
170 public void run() {
171 Object o = new Object();
172 try {
173 synchronized (o) {
174 o.wait();
175 }
176 } catch (InterruptedException ie) {
177 }
178 }
179 };
180 Thread t = new Thread(r);
181 t.setDaemon(false);
182 t.start();
183 <...>
184</pre>
185
186The Java Virtual Machine Specification guarantees
187that the JVM doesn't exit until this thread terminates.
188</body>
189</html>