-
Bug
-
Resolution: Fixed
-
P2
-
6, 6u21
-
b102
-
x86
-
windows_xp
java version "1.6.0-beta2"
Java(TM) SE Runtime Environment (build 1.6.0-beta2-b81)
Java HotSpot(TM) Client VM (build 1.6.0-beta2-b81, mixed mode, sharing)
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b02)
Java HotSpot(TM) Client VM (build 1.5.0_07-b02, mixed mode, sharing)
Does this problem occur on J2SE 1.4.x or 5.0.x ?
Yes, the issue is a general problem, which concers Tiger and Mustang.
Operating System Configuration Information (be specific):
Windows XP SP2 Professional / DE
Hardware Configuration Information (be specific):
Intel Pentium Mobile on VAIO VGN-FS 1.6 GHz
Bug Description:
java.awt.EventQueue push/pop might cause threading issues
Steps to Reproduce (be specific):
The issue rather concerns a general problem of the java.awt.EventQueue
class than a specific bug:
The following typical scenario might occur in a Swing application:
1. Assume the following EventQueue utility class:
public class EventPump extends java.awt.EventQueue {
private static final EventQueue EVENTQUEUE = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
public static EventPump push() {
EventPump pump = new EventPump();
EVENTQUEUE.push(pump);
return pump;
}
protected void pop() {
try {
super.pop();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
2. Assume that the application wants to execute some code on a separate
thread invoked from inside the awt thread. In addition, the current
awt thread should pause for the separate thread to terminate, i.e.
something like ...
// here we assume being on the awt thread
Thread worker = new Thread() {
public void run() {
// do something ...
}
}
worker.start();
worker.join();
// here the awt thread is waiting for the worker
3. In order NOT to freeze the gui, the code snippet 2. would be extended
using the utility 1. above:
Thread worker = new Thread() {
public void run() {
// do something ...
}
}
worker.start();
EventPump keepOnGoing = EventPump.push();
worker.join();
keepOnGoing.pop().
4. Now, looking at 3. and also having the source code of java.awt.EventQueue
and java.awt.EventDispatchThread in mind, we can make several observations.
Note that the implementation is in principle the same for Tiger and Mustang
concering the push, pop, initDispatchThread, stopDispatching,
stopDispatchingLater etc. methods relevant for the subsequent threading
dicussion. Hence, the following notes apply to both Java versions.
a. When executing push(), the following happens:
a.i. A new EventQueue Q2 is pushed on top of the EventQueue stack.
a.ii. All pending events are transferred from the current EventQueue Q1 to Q2.
a.iii. The thread T1 of the original EventQueue is stopped lazily, which is
implemented by setting the boolean doDispatch flag, which finally terminates
the thread's run() method when the thread the next time is trying to pump
an event.
a.iv. T1 is detached from Q1 by executing the theQueue.detachThread() method.
a.v. For instance, T1 is still running because it is currently dispatching
scenario 3. above and will execute the join() method first.
a.vi. Once, a new event is arriving on the currently active EventQueue Q2,
a new awt thread T2 is created for Q2, which starts pumping events on Q2.
b. Once, the worker thread of scenario 3. above has terminated, the pop()
method is executed by T1, which has the following effect:
b.i. All pending events are transferred from Q2 to Q1.
b.ii. The current dispatch Thread T2 is stopped by T1, i.e. b putting a
so-called StopEvent into Q2, which indirectly modifies the above-cited
doDispatch flag, when the StopEvent is dispatched by T2. Note, this
time T1 is waiting for this to happen.
Now, when Q1 resumes pumping events, it has no current dispatch thread due to
item a.iv above. Consequently, a new thread T1* is created for Q1, which gets
the new active awt thread.
Note, the javax.swing.SwingUtilities.isEventDispatchThread() method will
correctly supply "true" if and only if now called from T1*. Hence, the
method would correctly evaluate to "false" when called by T1 immeadiately
after the pop() method call of the avove-cited scenario.
Problem:
Immediately, before scenario 3. terminates, we have two active threads (with
the same name), i.e. T1*, the new awt thread, and T1 the original awt thread.
T1 is still dispatching its event, which might hence interfere with newly
arriving events dispatched by T1*.
Clearly, speaking there is room for potential threading issues for the period
between the start of T1* (after calling pop() above) and the dead of T1.
Imagine that T1 modifies variables before dying. Such changes would only be
visible to T1* when properly synchronized. By constrast, developers relying
on the "only one dispatch thread at the time" paradigm would probably not see
a reason for synchronization in this context.
Proposed Solution:
Instead of detaching T1 from its queue in a.iv above and stopping it, it might
be better (also for performance and resource aspects) , NOT to detach an awt
thread when pushing a new EventQueue. The awt thread should just be lazily
stopped and hence have a chance to resume dispatching on its original queue,
when pop() is called before lazy stopping really happens.
As a consequnce, the original queue would keep its original awt thread when
resuming work in the above-cited scenario, which seems to be a typical
EventQueue push/pop use case. The original awt thread could continue pumping
and there would be no need for synchronization. In addition, the
SwingUtilities.isEventDispatchThread() would continue to supply "true" for T1
in the above-cited scenario after pop(), which might be a more comprehensive
behavior from the user's point of view.
- relates to
-
JDK-8024034 The test is hung, we can't press "Pass" or "Fail" button
- Open
-
JDK-6982348 Deadlock with combined use of EDT and CountDownLatch
- Resolved
-
JDK-8081485 EDT auto shutdown is broken in case of new event queue usage
- Resolved
-
JDK-6553239 one more threading problem with EventQueue.pop()
- Closed
-
JDK-8144759 EventQueue.pop() does not stop dispatching thread
- Closed
-
JDK-6542185 Threading issues with java.awt.EventQueue.push/pop
- Closed
-
JDK-6949936 Provide API for running nested events loops, similar to what modal dialogs do
- Closed