--- 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;
}