| <!-- | |
| Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. | |
| DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| This code is free software; you can redistribute it and/or modify it | |
| under the terms of the GNU General Public License version 2 only, as | |
| published by the Free Software Foundation. Oracle designates this | |
| particular file as subject to the "Classpath" exception as provided | |
| by Oracle in the LICENSE file that accompanied this code. | |
| This code is distributed in the hope that it will be useful, but WITHOUT | |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| version 2 for more details (a copy is included in the LICENSE file that | |
| accompanied this code). | |
| You should have received a copy of the GNU General Public License version | |
| 2 along with this work; if not, write to the Free Software Foundation, | |
| Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| or visit www.oracle.com if you need additional information or have any | |
| questions. | |
| --> | |
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
| <html> | |
| <head> | |
| <title></title> | |
| </head> | |
| <body bgcolor=white> | |
| <h1 align=center>AWT Threading Issues</h1> | |
| <a name="ListenersThreads"></a> | |
| <h2>Listeners and threads</h2> | |
| Unless otherwise noted all AWT listeners are notified on the event | |
| dispatch thread. It is safe to remove/add listeners from any thread | |
| during dispatching, but the changes only effect subsequent notification. | |
| <br>For example, if a key listeners is added from another key listener, the | |
| newly added listener is only notified on subsequent key events. | |
| <a name="Autoshutdown"></a> | |
| <h2>Auto-shutdown</h2> | |
| According to | |
| <cite>The Java™ Virtual Machine Specification</cite>, | |
| sections 2.17.9 and 2.19, | |
| the Java virtual machine (JVM) initially starts up with a single non-daemon | |
| thread, which typically calls the <code>main</code> method of some class. | |
| The virtual machine terminates all its activity and exits when | |
| one of two things happens: | |
| <ul> | |
| <li> All the threads that are not daemon threads terminate. | |
| <li> Some thread invokes the <code>exit</code> method of class | |
| <code>Runtime</code> or class <code>System</code>, and the exit | |
| operation is permitted by the security manager. | |
| </ul> | |
| <p> | |
| This implies that if an application doesn't start any threads itself, | |
| the JVM will exit as soon as <code>main</code> terminates. | |
| This is not the case, however, for a simple application | |
| that creates and displays a <code>java.awt.Frame</code>: | |
| <pre> | |
| public static void main(String[] args) { | |
| Frame frame = new Frame(); | |
| frame.setVisible(true); | |
| } | |
| </pre> | |
| 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: | |
| <ul> | |
| <li> <a href="../EventQueue.html#isDispatchThread()"><code>EventQueue.isDispatchThread</code></a> | |
| returns <code>true</code> if and only if the calling thread is the | |
| event dispatch thread started by the machinery; | |
| <li> <code>AWTEvents</code> which were actually enqueued to a | |
| particular <code>EventQueue</code> (note that events being | |
| posted to the <code>EventQueue</code> can be coalesced) are | |
| dispatched: | |
| <ul> | |
| <li> Sequentially. | |
| <dl><dd> That is, it is not permitted that several events from | |
| this queue are dispatched simultaneously. </dd></dl> | |
| <li> In the same order as they are enqueued. | |
| <dl><dd> That is, if <code>AWTEvent</code> A is enqueued | |
| to the <code>EventQueue</code> before | |
| <code>AWTEvent</code> B then event B will not be | |
| dispatched before event A.</dd></dl> | |
| </ul> | |
| <li> There is at least one alive non-daemon thread while there is at | |
| least one displayable AWT or Swing component within the | |
| application (see | |
| <a href="../Component.html#isDisplayable()"><code>Component.isDisplayable</code></a>). | |
| </ul> | |
| The implications of the third restriction are as follows: | |
| <ul> | |
| <li> The JVM will exit if some thread invokes the <code>exit</code> | |
| method of class <code>Runtime</code> or class <code>System</code> | |
| regardless of the presence of displayable components; | |
| <li> Even if the application terminates all non-daemon threads it | |
| started, the JVM will not exit while there is at least one | |
| displayable component. | |
| </ul> | |
| 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. | |
| <h3> | |
| Implementation-dependent behavior. | |
| </h3> | |
| Prior to 1.4, the helper threads were never terminated. | |
| <p> | |
| Starting with 1.4, the behavior has changed as a result of the fix for | |
| <a href="http://bugs.sun.com/view_bug.do?bug_id=4030718"> | |
| 4030718</a>. With the current implementation, AWT terminates all its | |
| helper threads allowing the application to exit cleanly when the | |
| following three conditions are true: | |
| <ul> | |
| <li> There are no displayable AWT or Swing components. | |
| <li> There are no native events in the native event queue. | |
| <li> There are no AWT events in java EventQueues. | |
| </ul> | |
| Therefore, a stand-alone AWT application that wishes to exit | |
| cleanly without calling <code>System.exit</code> must: | |
| <ul> | |
| <li> Make sure that all AWT or Swing components are made | |
| undisplayable when the application finishes. This can be done | |
| by calling | |
| <a href="../Window.html#dispose()"><code>Window.dispose</code></a> | |
| on all top-level <code>Windows</code>. See | |
| <a href="../Frame.html#getFrames()"><code>Frame.getFrames</code></a>. | |
| <li> 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 <code>EventQueue</code>. | |
| The argument is that methods | |
| of AWT event listeners are typically executed on helper | |
| threads. | |
| </ul> | |
| 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: | |
| <ul> | |
| <li> Other packages can create displayable components for internal | |
| needs and never make them undisplayable. See | |
| <a href="http://bugs.sun.com/view_bug.do?bug_id=4515058"> | |
| 4515058</a>, | |
| <a href="http://bugs.sun.com/view_bug.do?bug_id=4671025"> | |
| 4671025</a>, and | |
| <a href="http://bugs.sun.com/view_bug.do?bug_id=4465537"> | |
| 4465537</a>. | |
| <li> Both Microsoft Windows and X11 allow an application to send native | |
| events to windows that belong to another application. With this | |
| feature it is possible to write a malicious program that will | |
| continuously send events to all available windows preventing | |
| any AWT application from exiting cleanly. | |
| </ul> | |
| 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. | |
| <pre> | |
| <...> | |
| Runnable r = new Runnable() { | |
| public void run() { | |
| Object o = new Object(); | |
| try { | |
| synchronized (o) { | |
| o.wait(); | |
| } | |
| } catch (InterruptedException ie) { | |
| } | |
| } | |
| }; | |
| Thread t = new Thread(r); | |
| t.setDaemon(false); | |
| t.start(); | |
| <...> | |
| </pre> | |
| <cite>The Java™ Virtual Machine Specification</cite> | |
| guarantees | |
| that the JVM doesn't exit until this thread terminates. | |
| </body> | |
| </html> |