J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | <!-- |
| 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 | |
| 34 | Unless otherwise noted all AWT listeners are notified on the event |
| 35 | dispatch thread. It is safe to remove/add listeners from any thread |
| 36 | during dispatching, but the changes only effect subsequent notification. |
| 37 | <br>For example, if a key listeners is added from another key listener, the |
| 38 | newly added listener is only notified on subsequent key events. |
| 39 | |
| 40 | <a name="Autoshutdown"></a> |
| 41 | <h2>Auto-shutdown</h2> |
| 42 | |
| 43 | According to <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html"><i>The |
| 44 | Java</i><sup><small>TM</small></sup> <i>Virtual Machine Specification, |
| 45 | Second edition</i></a> (see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#19152">§2.17.9</a> |
| 46 | and <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#33308">§2.19</a>), |
| 47 | the Java virtual machine (JVM) initially starts up with a single non-daemon |
| 48 | thread, which typically calls the <code>main</code> method of some class. |
| 49 | The virtual machine terminates all its activity and exits when |
| 50 | one 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> |
| 58 | This implies that if an application doesn't start any threads itself, |
| 59 | the JVM will exit as soon as <code>main</code> terminates. |
| 60 | This is not the case, however, for a simple application |
| 61 | that 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> |
| 68 | The reason is that AWT encapsulates asynchronous event dispatch |
| 69 | machinery to process events AWT or Swing components can fire. The |
| 70 | exact behavior of this machinery is implementation-dependent. In |
| 71 | particular, it can start non-daemon helper threads for its internal |
| 72 | purposes. In fact, these are the threads that prevent the example |
| 73 | above from exiting. The only restrictions imposed on the behavior of |
| 74 | this 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> A is enqueued |
| 89 | to the <code>EventQueue</code> before |
| 90 | <code>AWTEvent</code> 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> |
| 98 | The 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> |
| 107 | It depends on the implementation if and when the non-daemon helper |
| 108 | threads are terminated once all components are made undisplayable. |
| 109 | The implementation-specific details are given below. |
| 110 | |
| 111 | <h3> |
| 112 | Implementation-dependent behavior. |
| 113 | </h3> |
| 114 | |
| 115 | Prior to 1.4, the helper threads were never terminated. |
| 116 | <p> |
| 117 | Starting 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"> |
| 119 | 4030718</a>. With the current implementation, AWT terminates all its |
| 120 | helper threads allowing the application to exit cleanly when the |
| 121 | following 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> |
| 127 | Therefore, a stand-alone AWT application that wishes to exit |
| 128 | cleanly 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> |
| 145 | Note, that while an application following these recommendations will |
| 146 | exit cleanly under normal conditions, it is not guaranteed that it |
| 147 | will 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"> |
| 152 | 4515058</a>, |
| 153 | <a href="http://developer.java.sun.com/developer/bugParade/bugs/4671025.html"> |
| 154 | 4671025</a>, and |
| 155 | <a href="http://developer.java.sun.com/developer/bugParade/bugs/4465537.html"> |
| 156 | 4465537</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> |
| 163 | On the other hand, if you require the JVM to continue running even after |
| 164 | the application has made all components undisplayable you should start a |
| 165 | non-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 | |
| 186 | The Java Virtual Machine Specification guarantees |
| 187 | that the JVM doesn't exit until this thread terminates. |
| 188 | </body> |
| 189 | </html> |