Skip to content

Commit 9be6e77

Browse files
committed
8384381: Remove AppContext from java.awt.EventQueue implementation
Reviewed-by: kizune, azvegint, serb
1 parent aa29f79 commit 9be6e77

3 files changed

Lines changed: 28 additions & 109 deletions

File tree

src/java.desktop/share/classes/java/awt/EventQueue.java

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
4040

4141
import java.util.concurrent.locks.Condition;
4242
import java.util.concurrent.locks.Lock;
43+
import java.util.concurrent.locks.ReentrantLock;
4344
import java.util.concurrent.atomic.AtomicInteger;
4445

4546
/**
@@ -112,11 +113,11 @@ public class EventQueue {
112113

113114
/*
114115
* A single lock to synchronize the push()/pop() and related operations with
115-
* all the EventQueues from the AppContext. Synchronization on any particular
116+
* all the EventQueues. Synchronization on any particular
116117
* event queue(s) is not enough: we should lock the whole stack.
117118
*/
118-
private final Lock pushPopLock;
119-
private final Condition pushPopCond;
119+
private static final Lock pushPopLock = new ReentrantLock();
120+
private static final Condition pushPopCond = pushPopLock.newCondition();
120121

121122
/*
122123
* Dummy runnable to wake up EDT from getNextEvent() after
@@ -156,11 +157,6 @@ public void run() {
156157
*/
157158
private volatile int waitForID;
158159

159-
/*
160-
* AppContext corresponding to the queue.
161-
*/
162-
private final AppContext appContext;
163-
164160
private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
165161

166162
private FwDispatcher fwDispatcher;
@@ -222,18 +218,6 @@ public EventQueue() {
222218
for (int i = 0; i < NUM_PRIORITIES; i++) {
223219
queues[i] = new Queue();
224220
}
225-
/*
226-
* NOTE: if you ever have to start the associated event dispatch
227-
* thread at this point, be aware of the following problem:
228-
* If this EventQueue instance is created in
229-
* SunToolkit.createNewAppContext() the started dispatch thread
230-
* may call AppContext.getAppContext() before createNewAppContext()
231-
* completes thus causing mess in thread group to appcontext mapping.
232-
*/
233-
234-
appContext = AppContext.getAppContext();
235-
pushPopLock = (Lock)appContext.get(AppContext.EVENT_QUEUE_LOCK_KEY);
236-
pushPopCond = (Condition)appContext.get(AppContext.EVENT_QUEUE_COND_KEY);
237221
}
238222

239223
/**
@@ -247,7 +231,7 @@ public EventQueue() {
247231
* @throws NullPointerException if {@code theEvent} is {@code null}
248232
*/
249233
public void postEvent(AWTEvent theEvent) {
250-
SunToolkit.flushPendingEvents(appContext);
234+
SunToolkit.flushPendingEvents();
251235
postEventPrivate(theEvent);
252236
}
253237

@@ -532,7 +516,7 @@ public AWTEvent getNextEvent() throws InterruptedException {
532516
* of the synchronized block to avoid deadlock when
533517
* event queues are nested with push()/pop().
534518
*/
535-
SunToolkit.flushPendingEvents(appContext);
519+
SunToolkit.flushPendingEvents();
536520
pushPopLock.lock();
537521
try {
538522
AWTEvent event = getNextEventPrivate();
@@ -572,7 +556,7 @@ AWTEvent getNextEvent(int id) throws InterruptedException {
572556
* of the synchronized block to avoid deadlock when
573557
* event queues are nested with push()/pop().
574558
*/
575-
SunToolkit.flushPendingEvents(appContext);
559+
SunToolkit.flushPendingEvents();
576560
pushPopLock.lock();
577561
try {
578562
for (int i = 0; i < NUM_PRIORITIES; i++) {
@@ -869,8 +853,8 @@ public void push(EventQueue newEventQueue) {
869853
newEventQueue.previousQueue = topQueue;
870854
topQueue.nextQueue = newEventQueue;
871855

872-
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
873-
appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
856+
if (SunToolkit.currentEventQueue == topQueue) {
857+
SunToolkit.currentEventQueue = newEventQueue;
874858
}
875859

876860
pushPopCond.signalAll();
@@ -929,8 +913,8 @@ protected void pop() throws EmptyStackException {
929913
topQueue.dispatchThread.setEventQueue(prevQueue);
930914
}
931915

932-
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
933-
appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
916+
if (SunToolkit.currentEventQueue == this) {
917+
SunToolkit.currentEventQueue = prevQueue;
934918
}
935919

936920
// Wake up EDT waiting in getNextEvent(), so it can
@@ -1053,7 +1037,7 @@ final boolean isDispatchThreadImpl() {
10531037
final void initDispatchThread() {
10541038
pushPopLock.lock();
10551039
try {
1056-
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
1040+
if (dispatchThread == null && !threadGroup.isDestroyed()) {
10571041
EventDispatchThread t = new EventDispatchThread(threadGroup, name, EventQueue.this);
10581042
t.setContextClassLoader(classLoader);
10591043
t.setPriority(Thread.NORM_PRIORITY + 1);
@@ -1071,7 +1055,7 @@ final void detachDispatchThread(EventDispatchThread edt) {
10711055
/*
10721056
* Minimize discard possibility for non-posted events
10731057
*/
1074-
SunToolkit.flushPendingEvents(appContext);
1058+
SunToolkit.flushPendingEvents();
10751059
/*
10761060
* This synchronized block is to secure that the event dispatch
10771061
* thread won't die in the middle of posting a new event to the
@@ -1129,7 +1113,7 @@ final EventDispatchThread getDispatchThread() {
11291113
* {@code removeNotify} method.
11301114
*/
11311115
final void removeSourceEvents(Object source, boolean removeAllEvents) {
1132-
SunToolkit.flushPendingEvents(appContext);
1116+
SunToolkit.flushPendingEvents();
11331117
pushPopLock.lock();
11341118
try {
11351119
for (int i = 0; i < NUM_PRIORITIES; i++) {

src/java.desktop/share/classes/sun/awt/AppContext.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@
4343
import java.lang.ref.SoftReference;
4444

4545
import sun.util.logging.PlatformLogger;
46-
import java.util.concurrent.locks.Condition;
47-
import java.util.concurrent.locks.Lock;
48-
import java.util.concurrent.locks.ReentrantLock;
4946
import java.util.concurrent.atomic.AtomicInteger;
5047

5148
/**
@@ -121,17 +118,6 @@ public final class AppContext {
121118
/* Since the contents of an AppContext are unique to each Java
122119
* session, this class should never be serialized. */
123120

124-
/*
125-
* The key to put()/get() the Java EventQueue into/from the AppContext.
126-
*/
127-
public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");
128-
129-
/*
130-
* The keys to store EventQueue push/pop lock and condition.
131-
*/
132-
public static final Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
133-
public static final Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");
134-
135121
/* A map of AppContexts, referenced by ThreadGroup.
136122
*/
137123
private static final Map<ThreadGroup, AppContext> threadGroup2appContext =
@@ -225,12 +211,6 @@ public boolean isDisposed() {
225211
threadGroup2appContext.put(threadGroup, this);
226212

227213
this.contextClassLoader = Thread.currentThread().getContextClassLoader();
228-
// Initialize push/pop lock and its condition to be used by all the
229-
// EventQueues within this AppContext
230-
Lock eventQueuePushPopLock = new ReentrantLock();
231-
put(EVENT_QUEUE_LOCK_KEY, eventQueuePushPopLock);
232-
Condition eventQueuePushPopCond = eventQueuePushPopLock.newCondition();
233-
put(EVENT_QUEUE_COND_KEY, eventQueuePushPopCond);
234214
}
235215

236216
private static final ThreadLocal<AppContext> threadAppContext =

src/java.desktop/share/classes/sun/awt/SunToolkit.java

Lines changed: 13 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,6 @@ private static void initStatic() {
133133
*/
134134
public static final int GRAB_EVENT_MASK = 0x80000000;
135135

136-
/* The key to put()/get() the PostEventQueue into/from the AppContext.
137-
*/
138-
private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
139-
140136
/**
141137
* Number of buttons.
142138
* By default it's taken from the system. If system value does not
@@ -156,20 +152,17 @@ private static void initStatic() {
156152
*/
157153
public static final int MAX_BUTTONS_SUPPORTED = 20;
158154

155+
public static volatile EventQueue currentEventQueue;
156+
private static volatile PostEventQueue postEventQueue;
157+
159158
/**
160-
* Creates and initializes EventQueue instance for the specified
161-
* AppContext.
162-
* Note that event queue must be created from createNewAppContext()
163-
* only in order to ensure that EventQueue constructor obtains
164-
* the correct AppContext.
165-
* @param appContext AppContext to associate with the event queue
159+
* Creates and initializes EventQueue instance.
166160
*/
167-
private static void initEQ(AppContext appContext) {
168-
EventQueue eventQueue = new EventQueue();
169-
appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);
170-
171-
PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
172-
appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
161+
private static synchronized void initEQ() {
162+
if (currentEventQueue == null) {
163+
currentEventQueue = new EventQueue();
164+
postEventQueue = new PostEventQueue(currentEventQueue);
165+
}
173166
}
174167

175168
public SunToolkit() {
@@ -279,8 +272,7 @@ static final AppContext createNewAppContext(ThreadGroup threadGroup) {
279272
// the calls to AppContext.getAppContext() from EventQueue ctor
280273
// return correct values
281274
AppContext appContext = new AppContext(threadGroup);
282-
initEQ(appContext);
283-
275+
initEQ();
284276
return appContext;
285277
}
286278

@@ -468,12 +460,6 @@ public static void postEvent(AppContext appContext, AWTEvent event) {
468460
// otherwise have to be modified to precisely identify
469461
// system-generated events.
470462
setSystemGenerated(event);
471-
AppContext eventContext = targetToAppContext(event.getSource());
472-
if (eventContext != null && !eventContext.equals(appContext)) {
473-
throw new RuntimeException("Event posted on wrong app context : " + event);
474-
}
475-
PostEventQueue postEventQueue =
476-
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
477463
if (postEventQueue != null) {
478464
postEventQueue.postEvent(event);
479465
}
@@ -498,18 +484,6 @@ public void run() {
498484
* EventQueue yet.
499485
*/
500486
public static void flushPendingEvents() {
501-
AppContext appContext = AppContext.getAppContext();
502-
flushPendingEvents(appContext);
503-
}
504-
505-
/*
506-
* Flush the PostEventQueue for the right AppContext.
507-
* The default flushPendingEvents only flushes the thread-local context,
508-
* which is not always correct, c.f. 3746956
509-
*/
510-
public static void flushPendingEvents(AppContext appContext) {
511-
PostEventQueue postEventQueue =
512-
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
513487
if (postEventQueue != null) {
514488
postEventQueue.flush();
515489
}
@@ -600,20 +574,6 @@ class AWTInvocationLock {}
600574
}
601575
}
602576

603-
/*
604-
* Returns true if the calling thread is the event dispatch thread
605-
* contained within AppContext which associated with the given target.
606-
* Use this call to ensure that a given task is being executed
607-
* (or not being) on the event dispatch thread for the given target.
608-
*/
609-
public static boolean isDispatchThreadForAppContext(Object target) {
610-
AppContext appContext = targetToAppContext(target);
611-
EventQueue eq = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
612-
613-
AWTAccessor.EventQueueAccessor accessor = AWTAccessor.getEventQueueAccessor();
614-
return accessor.isDispatchThreadImpl(eq);
615-
}
616-
617577
@Override
618578
public Dimension getScreenSize() {
619579
return GraphicsEnvironment.getLocalGraphicsEnvironment()
@@ -1035,13 +995,8 @@ protected EventQueue getSystemEventQueueImpl() {
1035995
}
1036996

1037997
public static EventQueue getSystemEventQueueImplPP() {
1038-
return getSystemEventQueueImplPP(AppContext.getAppContext());
1039-
}
1040-
1041-
public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
1042-
EventQueue theEventQueue =
1043-
(EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
1044-
return theEventQueue;
998+
initEQ();
999+
return currentEventQueue;
10451000
}
10461001

10471002
/**
@@ -2021,7 +1976,7 @@ public static boolean isSystemGenerated(AWTEvent e) {
20211976

20221977

20231978
/*
2024-
* PostEventQueue is a Thread that runs in the same AppContext as the
1979+
* PostEventQueue is a Thread tied to the
20251980
* Java EventQueue. It is a queue of AWTEvents to be posted to the
20261981
* Java EventQueue. The toolkit Thread (AWT-Windows/AWT-Motif) posts
20271982
* events to this queue, which then calls EventQueue.postEvent().

0 commit comments

Comments
 (0)