RFR [9] 8031050: [macosx] Crash while awt starting

Chris Hegarty chris.hegarty at oracle.com
Mon Feb 3 13:18:26 UTC 2014


An old issue has resurfaced because of a change in AWT. AWT, now, on Mac 
OS X, attaches a system graphics thread to the running VM, using 
JNI_AttachCurrentThread. This change can result in a NPE, if a security 
manager is installed, and the security manager tries to print the name 
of the current thread.

In this case, attaching a thread to the VM, the j.l.Thread instance/oop 
is created by the VM in allocate_threadObj(), and then its constructor 
is run. At this point almost everything has been created for the thread, 
jni env, etc, so it can query currentThread() to retrieve itself. (Note: 
this is unusual. Typically the thread running the j.l.Thread constructor 
is not itself.) Since the j.l.Thread oop was allocated directly by the 
VM, its fields, other than those directly set by allocate_threadObj(), 
are not initialized.

The call out from Thread.init to the security manager is problematic as 
the partially constructed thread can be retrieved through 
Thread.currentThread. Some of our internal tests run into a problem when 
the security manager tries to print the name of the thread, i.e. NPE.

Clearly there are other concerns of accessing a partially constructed
thread, not just the thread name, but it seems reasonable to simply move 
the setting of the name to the beginning of the init() method.

I propose the following change for JDK 9, with the intention of backport
exactly to JDK 8. Long term this should be revisited in JDK 9.

diff --git a/src/share/classes/java/lang/Thread.java
--- a/src/share/classes/java/lang/Thread.java
+++ b/src/share/classes/java/lang/Thread.java
@@ -366,6 +366,8 @@
               throw new NullPointerException("name cannot be null");

+         this.name = name.toCharArray();
           Thread parent = currentThread();
           SecurityManager security = System.getSecurityManager();
           if (g == null) {
@@ -402,7 +404,6 @@
           this.group = g;
           this.daemon = parent.isDaemon();
           this.priority = parent.getPriority();
-         this.name = name.toCharArray();
           if (security == null || isCCLOverridden(parent.getClass()))
               this.contextClassLoader = parent.getContextClassLoader();


More information about the core-libs-dev mailing list