8384381: Remove AppContext from java.awt.EventQueue implementation

Reviewed-by: kizune, azvegint, serb
This commit is contained in:
Phil Race 2026-05-13 16:41:09 +00:00
parent aa29f79564
commit 9be6e77d73
3 changed files with 29 additions and 110 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, 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
@ -40,6 +40,7 @@ import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -112,11 +113,11 @@ public class EventQueue {
/*
* A single lock to synchronize the push()/pop() and related operations with
* all the EventQueues from the AppContext. Synchronization on any particular
* all the EventQueues. Synchronization on any particular
* event queue(s) is not enough: we should lock the whole stack.
*/
private final Lock pushPopLock;
private final Condition pushPopCond;
private static final Lock pushPopLock = new ReentrantLock();
private static final Condition pushPopCond = pushPopLock.newCondition();
/*
* Dummy runnable to wake up EDT from getNextEvent() after
@ -156,11 +157,6 @@ public class EventQueue {
*/
private volatile int waitForID;
/*
* AppContext corresponding to the queue.
*/
private final AppContext appContext;
private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
private FwDispatcher fwDispatcher;
@ -222,18 +218,6 @@ public class EventQueue {
for (int i = 0; i < NUM_PRIORITIES; i++) {
queues[i] = new Queue();
}
/*
* NOTE: if you ever have to start the associated event dispatch
* thread at this point, be aware of the following problem:
* If this EventQueue instance is created in
* SunToolkit.createNewAppContext() the started dispatch thread
* may call AppContext.getAppContext() before createNewAppContext()
* completes thus causing mess in thread group to appcontext mapping.
*/
appContext = AppContext.getAppContext();
pushPopLock = (Lock)appContext.get(AppContext.EVENT_QUEUE_LOCK_KEY);
pushPopCond = (Condition)appContext.get(AppContext.EVENT_QUEUE_COND_KEY);
}
/**
@ -247,7 +231,7 @@ public class EventQueue {
* @throws NullPointerException if {@code theEvent} is {@code null}
*/
public void postEvent(AWTEvent theEvent) {
SunToolkit.flushPendingEvents(appContext);
SunToolkit.flushPendingEvents();
postEventPrivate(theEvent);
}
@ -532,7 +516,7 @@ public class EventQueue {
* of the synchronized block to avoid deadlock when
* event queues are nested with push()/pop().
*/
SunToolkit.flushPendingEvents(appContext);
SunToolkit.flushPendingEvents();
pushPopLock.lock();
try {
AWTEvent event = getNextEventPrivate();
@ -572,7 +556,7 @@ public class EventQueue {
* of the synchronized block to avoid deadlock when
* event queues are nested with push()/pop().
*/
SunToolkit.flushPendingEvents(appContext);
SunToolkit.flushPendingEvents();
pushPopLock.lock();
try {
for (int i = 0; i < NUM_PRIORITIES; i++) {
@ -869,8 +853,8 @@ public class EventQueue {
newEventQueue.previousQueue = topQueue;
topQueue.nextQueue = newEventQueue;
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
if (SunToolkit.currentEventQueue == topQueue) {
SunToolkit.currentEventQueue = newEventQueue;
}
pushPopCond.signalAll();
@ -929,8 +913,8 @@ public class EventQueue {
topQueue.dispatchThread.setEventQueue(prevQueue);
}
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
if (SunToolkit.currentEventQueue == this) {
SunToolkit.currentEventQueue = prevQueue;
}
// Wake up EDT waiting in getNextEvent(), so it can
@ -1053,7 +1037,7 @@ public class EventQueue {
final void initDispatchThread() {
pushPopLock.lock();
try {
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
if (dispatchThread == null && !threadGroup.isDestroyed()) {
EventDispatchThread t = new EventDispatchThread(threadGroup, name, EventQueue.this);
t.setContextClassLoader(classLoader);
t.setPriority(Thread.NORM_PRIORITY + 1);
@ -1071,7 +1055,7 @@ public class EventQueue {
/*
* Minimize discard possibility for non-posted events
*/
SunToolkit.flushPendingEvents(appContext);
SunToolkit.flushPendingEvents();
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
@ -1129,7 +1113,7 @@ public class EventQueue {
* {@code removeNotify} method.
*/
final void removeSourceEvents(Object source, boolean removeAllEvents) {
SunToolkit.flushPendingEvents(appContext);
SunToolkit.flushPendingEvents();
pushPopLock.lock();
try {
for (int i = 0; i < NUM_PRIORITIES; i++) {

View File

@ -43,9 +43,6 @@ import java.beans.PropertyChangeListener;
import java.lang.ref.SoftReference;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -121,17 +118,6 @@ public final class AppContext {
/* Since the contents of an AppContext are unique to each Java
* session, this class should never be serialized. */
/*
* The key to put()/get() the Java EventQueue into/from the AppContext.
*/
public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");
/*
* The keys to store EventQueue push/pop lock and condition.
*/
public static final Object EVENT_QUEUE_LOCK_KEY = new StringBuilder("EventQueue.Lock");
public static final Object EVENT_QUEUE_COND_KEY = new StringBuilder("EventQueue.Condition");
/* A map of AppContexts, referenced by ThreadGroup.
*/
private static final Map<ThreadGroup, AppContext> threadGroup2appContext =
@ -225,12 +211,6 @@ public final class AppContext {
threadGroup2appContext.put(threadGroup, this);
this.contextClassLoader = Thread.currentThread().getContextClassLoader();
// Initialize push/pop lock and its condition to be used by all the
// EventQueues within this AppContext
Lock eventQueuePushPopLock = new ReentrantLock();
put(EVENT_QUEUE_LOCK_KEY, eventQueuePushPopLock);
Condition eventQueuePushPopCond = eventQueuePushPopLock.newCondition();
put(EVENT_QUEUE_COND_KEY, eventQueuePushPopCond);
}
private static final ThreadLocal<AppContext> threadAppContext =

View File

@ -133,10 +133,6 @@ public abstract class SunToolkit extends Toolkit
*/
public static final int GRAB_EVENT_MASK = 0x80000000;
/* The key to put()/get() the PostEventQueue into/from the AppContext.
*/
private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
/**
* Number of buttons.
* By default it's taken from the system. If system value does not
@ -156,20 +152,17 @@ public abstract class SunToolkit extends Toolkit
*/
public static final int MAX_BUTTONS_SUPPORTED = 20;
/**
* Creates and initializes EventQueue instance for the specified
* AppContext.
* Note that event queue must be created from createNewAppContext()
* only in order to ensure that EventQueue constructor obtains
* the correct AppContext.
* @param appContext AppContext to associate with the event queue
*/
private static void initEQ(AppContext appContext) {
EventQueue eventQueue = new EventQueue();
appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);
public static volatile EventQueue currentEventQueue;
private static volatile PostEventQueue postEventQueue;
PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
/**
* Creates and initializes EventQueue instance.
*/
private static synchronized void initEQ() {
if (currentEventQueue == null) {
currentEventQueue = new EventQueue();
postEventQueue = new PostEventQueue(currentEventQueue);
}
}
public SunToolkit() {
@ -279,8 +272,7 @@ public abstract class SunToolkit extends Toolkit
// the calls to AppContext.getAppContext() from EventQueue ctor
// return correct values
AppContext appContext = new AppContext(threadGroup);
initEQ(appContext);
initEQ();
return appContext;
}
@ -468,12 +460,6 @@ public abstract class SunToolkit extends Toolkit
// otherwise have to be modified to precisely identify
// system-generated events.
setSystemGenerated(event);
AppContext eventContext = targetToAppContext(event.getSource());
if (eventContext != null && !eventContext.equals(appContext)) {
throw new RuntimeException("Event posted on wrong app context : " + event);
}
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if (postEventQueue != null) {
postEventQueue.postEvent(event);
}
@ -498,18 +484,6 @@ public abstract class SunToolkit extends Toolkit
* EventQueue yet.
*/
public static void flushPendingEvents() {
AppContext appContext = AppContext.getAppContext();
flushPendingEvents(appContext);
}
/*
* Flush the PostEventQueue for the right AppContext.
* The default flushPendingEvents only flushes the thread-local context,
* which is not always correct, c.f. 3746956
*/
public static void flushPendingEvents(AppContext appContext) {
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if (postEventQueue != null) {
postEventQueue.flush();
}
@ -600,20 +574,6 @@ public abstract class SunToolkit extends Toolkit
}
}
/*
* Returns true if the calling thread is the event dispatch thread
* contained within AppContext which associated with the given target.
* Use this call to ensure that a given task is being executed
* (or not being) on the event dispatch thread for the given target.
*/
public static boolean isDispatchThreadForAppContext(Object target) {
AppContext appContext = targetToAppContext(target);
EventQueue eq = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
AWTAccessor.EventQueueAccessor accessor = AWTAccessor.getEventQueueAccessor();
return accessor.isDispatchThreadImpl(eq);
}
@Override
public Dimension getScreenSize() {
return GraphicsEnvironment.getLocalGraphicsEnvironment()
@ -1035,13 +995,8 @@ public abstract class SunToolkit extends Toolkit
}
public static EventQueue getSystemEventQueueImplPP() {
return getSystemEventQueueImplPP(AppContext.getAppContext());
}
public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
EventQueue theEventQueue =
(EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
return theEventQueue;
initEQ();
return currentEventQueue;
}
/**
@ -2021,7 +1976,7 @@ public abstract class SunToolkit extends Toolkit
/*
* PostEventQueue is a Thread that runs in the same AppContext as the
* PostEventQueue is a Thread tied to the
* Java EventQueue. It is a queue of AWTEvents to be posted to the
* Java EventQueue. The toolkit Thread (AWT-Windows/AWT-Motif) posts
* events to this queue, which then calls EventQueue.postEvent().