8004584: Augment applet contextualization
Summary: Do not create the main AppContext for applets
Reviewed-by: art, ahgross
--- a/jdk/src/share/classes/java/util/logging/LogManager.java Wed Mar 20 11:50:11 2013 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Thu Mar 21 02:13:49 2013 +0400
@@ -394,27 +394,23 @@
// from the execution stack.
Object ecx = javaAwtAccess.getExecutionContext();
if (ecx == null) {
- // fall back to AppContext.getAppContext()
+ // fall back to thread group seach of AppContext
ecx = javaAwtAccess.getContext();
}
- context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class);
- if (context == null) {
- if (javaAwtAccess.isMainAppContext()) {
- context = userContext;
- } else {
- context = new LoggerContext();
- // during initialization, rootLogger is null when
- // instantiating itself RootLogger
- if (manager.rootLogger != null)
- context.addLocalLogger(manager.rootLogger);
+ if (ecx != null) {
+ context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class);
+ if (context == null) {
+ if (javaAwtAccess.isMainAppContext()) {
+ context = userContext;
+ } else {
+ context = new LoggerContext();
+ }
+ javaAwtAccess.put(ecx, LoggerContext.class, context);
}
- javaAwtAccess.put(ecx, LoggerContext.class, context);
}
}
- } else {
- context = userContext;
}
- return context;
+ return context != null ? context : userContext;
}
private List<LoggerContext> contexts() {
@@ -539,9 +535,22 @@
return logger;
}
+ synchronized void ensureRootLogger(Logger logger) {
+ if (logger == manager.rootLogger)
+ return;
+
+ // during initialization, rootLogger is null when
+ // instantiating itself RootLogger
+ if (findLogger("") == null && manager.rootLogger != null) {
+ addLocalLogger(manager.rootLogger);
+ }
+ }
+
// Add a logger to this context. This method will only set its level
// and process parent loggers. It doesn't set its handlers.
synchronized boolean addLocalLogger(Logger logger) {
+ ensureRootLogger(logger);
+
final String name = logger.getName();
if (name == null) {
throw new NullPointerException();
--- a/jdk/src/share/classes/sun/applet/AppletSecurity.java Wed Mar 20 11:50:11 2013 -0700
+++ b/jdk/src/share/classes/sun/applet/AppletSecurity.java Thu Mar 21 02:13:49 2013 +0400
@@ -52,7 +52,6 @@
*/
public
class AppletSecurity extends AWTSecurityManager {
- private AppContext mainAppContext;
//URLClassLoader.acc
private static Field facc = null;
@@ -77,7 +76,6 @@
*/
public AppletSecurity() {
reset();
- mainAppContext = AppContext.getAppContext();
}
// Cache to store known restricted packages
@@ -312,7 +310,7 @@
AppContext appContext = AppContext.getAppContext();
AppletClassLoader appletClassLoader = currentAppletClassLoader();
- if ((appContext == mainAppContext) && (appletClassLoader != null)) {
+ if (AppContext.isMainContext(appContext) && (appletClassLoader != null)) {
// If we're about to allow access to the main EventQueue,
// and anything untrusted is on the class context stack,
// disallow access.
--- a/jdk/src/share/classes/sun/awt/AppContext.java Wed Mar 20 11:50:11 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/AppContext.java Thu Mar 21 02:13:49 2013 +0400
@@ -162,7 +162,8 @@
}
/* The main "system" AppContext, used by everything not otherwise
- contained in another AppContext.
+ contained in another AppContext. It is implicitly created for
+ standalone apps only (i.e. not applets)
*/
private static volatile AppContext mainAppContext = null;
@@ -204,25 +205,6 @@
*/
private static final AtomicInteger numAppContexts = new AtomicInteger(0);
- static {
- // On the main Thread, we get the ThreadGroup, make a corresponding
- // AppContext, and instantiate the Java EventQueue. This way, legacy
- // code is unaffected by the move to multiple AppContext ability.
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- ThreadGroup currentThreadGroup =
- Thread.currentThread().getThreadGroup();
- ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
- while (parentThreadGroup != null) {
- // Find the root ThreadGroup to construct our main AppContext
- currentThreadGroup = parentThreadGroup;
- parentThreadGroup = currentThreadGroup.getParent();
- }
- mainAppContext = new AppContext(currentThreadGroup);
- return null;
- }
- });
- }
/*
* The context ClassLoader that was used to create this AppContext.
@@ -266,6 +248,27 @@
private static final ThreadLocal<AppContext> threadAppContext =
new ThreadLocal<AppContext>();
+ private final static void initMainAppContext() {
+ // On the main Thread, we get the ThreadGroup, make a corresponding
+ // AppContext, and instantiate the Java EventQueue. This way, legacy
+ // code is unaffected by the move to multiple AppContext ability.
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ ThreadGroup currentThreadGroup =
+ Thread.currentThread().getThreadGroup();
+ ThreadGroup parentThreadGroup = currentThreadGroup.getParent();
+ while (parentThreadGroup != null) {
+ // Find the root ThreadGroup to construct our main AppContext
+ currentThreadGroup = parentThreadGroup;
+ parentThreadGroup = currentThreadGroup.getParent();
+ }
+
+ mainAppContext = SunToolkit.createNewAppContext(currentThreadGroup);
+ return null;
+ }
+ });
+ }
+
/**
* Returns the appropriate AppContext for the caller,
* as determined by its ThreadGroup. If the main "system" AppContext
@@ -278,8 +281,10 @@
* @since 1.2
*/
public final static AppContext getAppContext() {
- if (numAppContexts.get() == 1) // If there's only one system-wide,
- return mainAppContext; // return the main system AppContext.
+ // we are standalone app, return the main app context
+ if (numAppContexts.get() == 1 && mainAppContext != null) {
+ return mainAppContext;
+ }
AppContext appContext = threadAppContext.get();
@@ -293,29 +298,37 @@
// when new AppContext objects are created.
ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();
ThreadGroup threadGroup = currentThreadGroup;
+
+ // Special case: we implicitly create the main app context
+ // if no contexts have been created yet. This covers standalone apps
+ // and excludes applets because by the time applet starts
+ // a number of contexts have already been created by the plugin.
+ if (numAppContexts.get() == 0) {
+ // This check is not necessary, its purpose is to help
+ // Plugin devs to catch all the cases of main AC creation.
+ if (System.getProperty("javaplugin.version") == null &&
+ System.getProperty("javawebstart.version") == null) {
+ initMainAppContext();
+ }
+ }
+
AppContext context = threadGroup2appContext.get(threadGroup);
while (context == null) {
threadGroup = threadGroup.getParent();
if (threadGroup == null) {
- // If we get here, we're running under a ThreadGroup that
- // has no AppContext associated with it. This should never
- // happen, because createNewContext() should be used by the
- // toolkit to create the ThreadGroup that everything runs
- // under.
- throw new RuntimeException("Invalid ThreadGroup");
+ return null;
}
context = threadGroup2appContext.get(threadGroup);
}
+
// In case we did anything in the above while loop, we add
// all the intermediate ThreadGroups to threadGroup2appContext
// so we won't spin again.
for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {
threadGroup2appContext.put(tg, context);
}
+
// Now we're done, so we cache the latest key/value pair.
- // (we do this before checking with any AWTSecurityManager, so if
- // this Thread equates with the main AppContext in the cache, it
- // still will)
threadAppContext.set(context);
return context;
@@ -323,17 +336,18 @@
});
}
- if (appContext == mainAppContext) {
- // Before we return the main "system" AppContext, check to
- // see if there's an AWTSecurityManager installed. If so,
- // allow it to choose the AppContext to return.
- AppContext secAppContext = getExecutionAppContext();
- if (secAppContext != null) {
- appContext = secAppContext; // Return what we're told
- }
- }
+ return appContext;
+ }
- return appContext;
+ /**
+ * Returns true if the specified AppContext is the main AppContext.
+ *
+ * @param ctx the context to compare with the main context
+ * @return true if the specified AppContext is the main AppContext.
+ * @since 1.8
+ */
+ public final static boolean isMainContext(AppContext ctx) {
+ return (ctx != null && ctx == mainAppContext);
}
private final static AppContext getExecutionAppContext() {
@@ -348,16 +362,6 @@
return null;
}
- /**
- * Returns the main ("system") AppContext.
- *
- * @return the main AppContext
- * @since 1.8
- */
- final static AppContext getMainAppContext() {
- return mainAppContext;
- }
-
private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout
// for disposal of all Frames
// (we wait for this time twice,
@@ -810,7 +814,7 @@
return getAppContext().isDisposed();
}
public boolean isMainAppContext() {
- return (numAppContexts.get() == 1);
+ return (numAppContexts.get() == 1 && mainAppContext != null);
}
public Object getContext() {
return getAppContext();
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Mar 20 11:50:11 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Thu Mar 21 02:13:49 2013 +0400
@@ -117,8 +117,6 @@
}
public SunToolkit() {
- // 7122796: Always create an EQ for the main AppContext
- initEQ(AppContext.getMainAppContext());
}
public boolean useBufferPerWindow() {
@@ -281,11 +279,14 @@
*/
public static AppContext createNewAppContext() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ return createNewAppContext(threadGroup);
+ }
+
+ static final AppContext createNewAppContext(ThreadGroup threadGroup) {
// Create appContext before initialization of EventQueue, so all
// the calls to AppContext.getAppContext() from EventQueue ctor
// return correct values
AppContext appContext = new AppContext(threadGroup);
-
initEQ(appContext);
return appContext;