8025010: Enhance AWT contexts
authorpchelko
Fri, 20 Dec 2013 15:43:41 +0400
changeset 23893 1a92335b55bb
parent 23892 9959956918be
child 23894 7500e0f62a4a
8025010: Enhance AWT contexts Reviewed-by: art, serb, hawtin
jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
jdk/src/macosx/native/sun/awt/LWCToolkit.m
jdk/src/macosx/native/sun/awt/awt.m
jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h
jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m
jdk/src/share/classes/sun/awt/AWTAutoShutdown.java
jdk/src/share/classes/sun/awt/SunToolkit.java
jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
jdk/src/windows/classes/sun/awt/windows/WToolkit.java
jdk/src/windows/native/sun/windows/awt_Toolkit.cpp
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Dec 20 15:43:41 2013 +0400
@@ -478,8 +478,12 @@
     private static final String APPKIT_THREAD_NAME = "AppKit Thread";
 
     // Intended to be called from the LWCToolkit.m only.
-    private static void installToolkitThreadNameInJava() {
+    private static void installToolkitThreadInJava() {
         Thread.currentThread().setName(APPKIT_THREAD_NAME);
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            Thread.currentThread().setContextClassLoader(null);
+            return null;
+        });
     }
 
     @Override
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Fri Dec 20 15:43:41 2013 +0400
@@ -226,10 +226,10 @@
 
         JNIEnv *env = [ThreadUtilities getJNIEnv];
         static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
-        static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadNameInJava, jc_LWCToolkit, "installToolkitThreadNameInJava", "()V");
-        JNFCallStaticVoidMethod(env, jsm_installToolkitThreadNameInJava);
+        static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
+        JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava);
     });
-
+    
     gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS;
 
     jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent");
--- a/jdk/src/macosx/native/sun/awt/awt.m	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/macosx/native/sun/awt/awt.m	Fri Dec 20 15:43:41 2013 +0400
@@ -434,6 +434,15 @@
         forceEmbeddedMode = YES;
     }
 
+    JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
+    jclass jc_SunToolkit = (*env)->FindClass(env, "sun/awt/SunToolkit");
+    jmethodID sjm_getRootThreadGroup = (*env)->GetStaticMethodID(env, jc_SunToolkit, "getRootThreadGroup", "()Ljava/lang/ThreadGroup;");
+    jobject rootThreadGroup = (*env)->CallStaticObjectMethod(env, jc_SunToolkit, sjm_getRootThreadGroup);
+    appkitThreadGroup = (*env)->NewGlobalRef(env, rootThreadGroup);
+    // The current thread was attached in getJNIEnvUnchached.
+    // Detach it back. It will be reattached later if needed with a proper TG
+    [ThreadUtilities detachCurrentThread];
+
     BOOL headless = isHeadless(env);
 
     // We need to let Foundation know that this is a multithreaded application, if it isn't already.
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h	Fri Dec 20 15:43:41 2013 +0400
@@ -122,11 +122,15 @@
 #endif /* AWT_THREAD_ASSERTS */
 // --------------------------------------------------------------------------
 
+// Set from JNI_Onload
+extern jobject appkitThreadGroup;
+
 __attribute__((visibility("default")))
 @interface ThreadUtilities { }
 
 + (JNIEnv*)getJNIEnv;
 + (JNIEnv*)getJNIEnvUncached;
++ (void)detachCurrentThread;
 
 //Wrappers for the corresponding JNFRunLoop methods with a check for main thread
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block;
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m	Fri Dec 20 15:43:41 2013 +0400
@@ -33,23 +33,40 @@
 // The following must be named "jvm", as there are extern references to it in AWT
 JavaVM *jvm = NULL;
 static JNIEnv *appKitEnv = NULL;
+jobject appkitThreadGroup = NULL;
+
+inline void attachCurrentThread(void** env) {
+    JavaVMAttachArgs args;
+    args.version = JNI_VERSION_1_2;
+    args.name = NULL; // Set from LWCToolkit
+    if ([NSThread isMainThread]) {
+        args.group = appkitThreadGroup;
+    } else {
+        args.group = NULL;
+    }
+    (*jvm)->AttachCurrentThreadAsDaemon(jvm, env, &args);
+}
 
 @implementation ThreadUtilities
 
 + (JNIEnv*)getJNIEnv {
 AWT_ASSERT_APPKIT_THREAD;
     if (appKitEnv == NULL) {
-        (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&appKitEnv, NULL);
+        attachCurrentThread((void **)&appKitEnv);
     }
     return appKitEnv;
 }
 
 + (JNIEnv*)getJNIEnvUncached {
     JNIEnv *env = NULL;
-    (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&env, nil);
+    attachCurrentThread((void **)&env);
     return env;
 }
 
++ (void)detachCurrentThread {
+    (*jvm)->DetachCurrentThread(jvm);
+}
+
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block {
     if ([NSThread isMainThread] && wait == YES) {
         block(); 
--- a/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java	Fri Dec 20 15:43:41 2013 +0400
@@ -27,6 +27,8 @@
 
 import java.awt.AWTEvent;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
@@ -333,7 +335,11 @@
      * the new blocker thread starts.
      */
     private void activateBlockerThread() {
-        Thread thread = new Thread(this, "AWT-Shutdown");
+        Thread thread = new Thread(SunToolkit.getRootThreadGroup(), this, "AWT-Shutdown");
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            thread.setContextClassLoader(null);
+            return null;
+        });
         thread.setDaemon(false);
         blockerThread = thread;
         thread.start();
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java	Fri Dec 20 15:43:41 2013 +0400
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
@@ -1185,6 +1186,17 @@
         return startupLocale;
     }
 
+    protected static ThreadGroup getRootThreadGroup() {
+        return AccessController.doPrivileged((PrivilegedAction<ThreadGroup>) () -> {
+            ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
+            ThreadGroup parentTG = currentTG.getParent();
+            while (parentTG != null) {
+                currentTG = parentTG;
+                parentTG = currentTG.getParent();
+            }
+            return currentTG;
+        });
+    }
     /**
      * Returns the default keyboard locale of the underlying operating system
      */
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Fri Dec 20 15:43:41 2013 +0400
@@ -256,13 +256,7 @@
         }
         PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
             public Void run() {
-                ThreadGroup mainTG = Thread.currentThread().getThreadGroup();
-                ThreadGroup parentTG = mainTG.getParent();
-                while (parentTG != null) {
-                    mainTG = parentTG;
-                    parentTG = mainTG.getParent();
-                }
-                Thread shutdownThread = new Thread(mainTG, "XToolkt-Shutdown-Thread") {
+                Thread shutdownThread = new Thread(getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
                         public void run() {
                             XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
                             if (peer != null) {
@@ -324,13 +318,8 @@
 
             PrivilegedAction<Thread> action = new PrivilegedAction() {
                 public Thread run() {
-                    ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parentTG = currentTG.getParent();
-                    while (parentTG != null) {
-                        currentTG = parentTG;
-                        parentTG = currentTG.getParent();
-                    }
-                    Thread thread = new Thread(currentTG, XToolkit.this, "AWT-XAWT");
+                    Thread thread = new Thread(getRootThreadGroup(), XToolkit.this, "AWT-XAWT");
+                    thread.setContextClassLoader(null);
                     thread.setPriority(Thread.NORM_PRIORITY + 1);
                     thread.setDaemon(true);
                     return thread;
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Fri Dec 20 15:43:41 2013 +0400
@@ -224,7 +224,7 @@
 
     private static native void postDispose();
 
-    private static native boolean startToolkitThread(Runnable thread);
+    private static native boolean startToolkitThread(Runnable thread, ThreadGroup rootThreadGroup);
 
     public WToolkit() {
         // Startup toolkit threads
@@ -241,8 +241,10 @@
          */
         AWTAutoShutdown.notifyToolkitThreadBusy();
 
-        if (!startToolkitThread(this)) {
-            Thread toolkitThread = new Thread(this, "AWT-Windows");
+        // Find a root TG and attach Appkit thread to it
+        ThreadGroup rootTG = getRootThreadGroup();
+        if (!startToolkitThread(this, rootTG)) {
+            Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows");
             toolkitThread.setDaemon(true);
             toolkitThread.start();
         }
@@ -271,14 +273,7 @@
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             @Override
             public Void run() {
-                ThreadGroup currentTG =
-                    Thread.currentThread().getThreadGroup();
-                ThreadGroup parentTG = currentTG.getParent();
-                while (parentTG != null) {
-                    currentTG = parentTG;
-                    parentTG = currentTG.getParent();
-                }
-                Thread shutdown = new Thread(currentTG, new Runnable() {
+                Thread shutdown = new Thread(getRootThreadGroup(), new Runnable() {
                     @Override
                     public void run() {
                         shutdown();
@@ -293,7 +288,11 @@
 
     @Override
     public void run() {
-        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            Thread.currentThread().setContextClassLoader(null);
+            return null;
+        });
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
         boolean startPump = init();
 
         if (startPump) {
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Fri Dec 20 09:58:29 2013 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Fri Dec 20 15:43:41 2013 +0400
@@ -351,6 +351,7 @@
     HANDLE hCompleted;
 
     jobject thread;
+    jobject threadGroup;
 };
 
 void ToolkitThreadProc(void *param)
@@ -363,7 +364,7 @@
     JavaVMAttachArgs attachArgs;
     attachArgs.version  = JNI_VERSION_1_2;
     attachArgs.name     = "AWT-Windows";
-    attachArgs.group    = NULL;
+    attachArgs.group    = data->threadGroup;
 
     jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
     if (res < 0) {
@@ -402,17 +403,18 @@
 /*
  * Class:     sun_awt_windows_WToolkit
  * Method:    startToolkitThread
- * Signature: (Ljava/lang/Runnable;)Z
+ * Signature: (Ljava/lang/Runnable;Ljava/lang/ThreadGroup)Z
  */
 JNIEXPORT jboolean JNICALL
-Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread)
+Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread, jobject threadGroup)
 {
     AwtToolkit& tk = AwtToolkit::GetInstance();
 
     ToolkitThreadProc_Data data;
     data.result = false;
     data.thread = env->NewGlobalRef(thread);
-    if (data.thread == NULL) {
+    data.threadGroup = env->NewGlobalRef(threadGroup);
+    if (data.thread == NULL || data.threadGroup == NULL) {
         return JNI_FALSE;
     }
     data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -430,6 +432,7 @@
     ::CloseHandle(data.hCompleted);
 
     env->DeleteGlobalRef(data.thread);
+    env->DeleteGlobalRef(data.threadGroup);
 
     return result ? JNI_TRUE : JNI_FALSE;
 }