changeset 7263:23a8ee1e7ed9

8025010: Enhance AWT contexts Reviewed-by: art, serb, hawtin
author pchelko
date Fri, 20 Dec 2013 13:37:06 +0400
parents 56161b644cbc
children 813b5f3ebc22
files src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java src/macosx/native/sun/awt/LWCToolkit.m src/macosx/native/sun/awt/awt.m src/macosx/native/sun/osxapp/ThreadUtilities.h src/macosx/native/sun/osxapp/ThreadUtilities.m src/share/classes/sun/awt/AWTAutoShutdown.java src/share/classes/sun/awt/SunToolkit.java src/solaris/classes/sun/awt/X11/XToolkit.java src/windows/classes/sun/awt/windows/WToolkit.java src/windows/native/sun/windows/awt_Toolkit.cpp
diffstat 10 files changed, 91 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Dec 20 13:37:06 2013 +0400
@@ -414,8 +414,15 @@
     }
 
     // Intended to be called from the LWCToolkit.m only.
-    private static void installToolkitThreadNameInJava() {
+    private static void installToolkitThreadInJava() {
         Thread.currentThread().setName(CThreading.APPKIT_THREAD_NAME);
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                Thread.currentThread().setContextClassLoader(null);
+                return null;
+            }
+        });
     }
 
     @Override
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Fri Dec 20 13:37:06 2013 +0400
@@ -193,8 +193,8 @@
 
         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;
--- a/src/macosx/native/sun/awt/awt.m	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/macosx/native/sun/awt/awt.m	Fri Dec 20 13:37:06 2013 +0400
@@ -432,6 +432,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 getJNIEnvUncached.
+    // 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/src/macosx/native/sun/osxapp/ThreadUtilities.h	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/macosx/native/sun/osxapp/ThreadUtilities.h	Fri Dec 20 13:37:06 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/src/macosx/native/sun/osxapp/ThreadUtilities.m	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/macosx/native/sun/osxapp/ThreadUtilities.m	Fri Dec 20 13:37:06 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/src/share/classes/sun/awt/AWTAutoShutdown.java	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/share/classes/sun/awt/AWTAutoShutdown.java	Fri Dec 20 13:37:06 2013 +0400
@@ -26,6 +26,8 @@
 package sun.awt;
 
 import java.awt.AWTEvent;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
@@ -328,7 +330,14 @@
      * the new blocker thread starts.
      */
     private void activateBlockerThread() {
-        Thread thread = new Thread(this, "AWT-Shutdown");
+        final Thread thread = new Thread(SunToolkit.getRootThreadGroup(), this, "AWT-Shutdown");
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                thread.setContextClassLoader(null);
+                return null;
+            }
+        });
         thread.setDaemon(false);
         blockerThread = thread;
         thread.start();
--- a/src/share/classes/sun/awt/SunToolkit.java	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/share/classes/sun/awt/SunToolkit.java	Fri Dec 20 13:37:06 2013 +0400
@@ -37,6 +37,7 @@
 import java.awt.SystemTray;
 import java.awt.event.InputEvent;
 import java.net.URL;
+import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
@@ -1126,6 +1127,20 @@
         return startupLocale;
     }
 
+    protected static ThreadGroup getRootThreadGroup() {
+        return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
+            @Override
+            public ThreadGroup run() {
+                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/src/solaris/classes/sun/awt/X11/XToolkit.java	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/solaris/classes/sun/awt/X11/XToolkit.java	Fri Dec 20 13:37:06 2013 +0400
@@ -311,13 +311,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) {
@@ -382,13 +376,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/src/windows/classes/sun/awt/windows/WToolkit.java	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/windows/classes/sun/awt/windows/WToolkit.java	Fri Dec 20 13:37:06 2013 +0400
@@ -215,7 +215,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
@@ -232,8 +232,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();
         }
@@ -263,14 +265,7 @@
     private final void registerShutdownHook() {
         AccessController.doPrivileged(new PrivilegedAction() {
             public Object 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() {
                     public void run() {
                         shutdown();
                     }
@@ -283,7 +278,14 @@
      }
 
     public void run() {
-        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                Thread.currentThread().setContextClassLoader(null);
+                return null;
+            }
+        });
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
         boolean startPump = init();
 
         if (startPump) {
--- a/src/windows/native/sun/windows/awt_Toolkit.cpp	Thu Dec 19 22:00:54 2013 +0400
+++ b/src/windows/native/sun/windows/awt_Toolkit.cpp	Fri Dec 20 13:37:06 2013 +0400
@@ -365,6 +365,7 @@
     HANDLE hCompleted;
 
     jobject thread;
+    jobject threadGroup;
 };
 
 void ToolkitThreadProc(void *param)
@@ -377,7 +378,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) {
@@ -416,17 +417,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);
@@ -444,6 +446,7 @@
     ::CloseHandle(data.hCompleted);
 
     env->DeleteGlobalRef(data.thread);
+    env->DeleteGlobalRef(data.threadGroup);
 
     return result ? JNI_TRUE : JNI_FALSE;
 }