8048210: More Enhancements to InnocuousThread and friends
authorchegar
Thu, 26 Jun 2014 14:49:23 +0100
changeset 29904 d5f909aa26bc
parent 29903 b21ed6c8bc3f
child 29905 f976927bb286
8048210: More Enhancements to InnocuousThread and friends Reviewed-by: alanb, pchelko, jbachorik
jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java
jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java
--- a/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java	Wed Jun 18 10:44:24 2014 +0100
+++ b/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java	Thu Jun 26 14:49:23 2014 +0100
@@ -34,16 +34,13 @@
 /**
  * A thread that has no permissions, is not a member of any user-defined
  * ThreadGroup and supports the ability to erase ThreadLocals.
- *
- * @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
  */
-public final class InnocuousThread extends Thread {
+public final class InnocuousThread extends ManagedLocalsThread {
     private static final Unsafe UNSAFE;
     private static final ThreadGroup INNOCUOUSTHREADGROUP;
     private static final AccessControlContext ACC;
-    private static final long THREADLOCALS;
-    private static final long INHERITABLETHREADLOCALS;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
+    private static final long CONTEXTCLASSLOADER;
 
     private static final AtomicInteger threadNumber = new AtomicInteger(1);
 
@@ -56,18 +53,10 @@
         this(INNOCUOUSTHREADGROUP, target, name);
     }
 
-    private InnocuousThread(ThreadGroup group, Runnable target, String name) {
+    public InnocuousThread(ThreadGroup group, Runnable target, String name) {
         super(group, target, name);
         UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
-        eraseThreadLocals();
-    }
-
-    // always report system class loader, or null
-    private ClassLoader contextClassLoader = ClassLoader.getSystemClassLoader();
-
-    @Override
-    public ClassLoader getContextClassLoader() {
-        return contextClassLoader;
+        UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
     }
 
     @Override
@@ -77,8 +66,9 @@
 
     @Override
     public void setContextClassLoader(ClassLoader cl) {
+        // Allow clearing of the TCCL to remove the reference to the system classloader.
         if (cl == null)
-            contextClassLoader = null;
+            super.setContextClassLoader(null);
         else
             throw new SecurityException("setContextClassLoader");
     }
@@ -94,14 +84,6 @@
         }
     }
 
-    /**
-     * Drops all thread locals (and inherited thread locals).
-     */
-    public void eraseThreadLocals() {
-        UNSAFE.putObject(this, THREADLOCALS, null);
-        UNSAFE.putObject(this, INHERITABLETHREADLOCALS, null);
-    }
-
     // Use Unsafe to access Thread group and ThreadGroup parent fields
     static {
         try {
@@ -114,12 +96,10 @@
             Class<?> tk = Thread.class;
             Class<?> gk = ThreadGroup.class;
 
-            THREADLOCALS = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocals"));
-            INHERITABLETHREADLOCALS = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("inheritableThreadLocals"));
             INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
                 (tk.getDeclaredField("inheritedAccessControlContext"));
+            CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
+                (tk.getDeclaredField("contextClassLoader"));
 
             long tg = UNSAFE.objectFieldOffset(tk.getDeclaredField("group"));
             long gp = UNSAFE.objectFieldOffset(gk.getDeclaredField("parent"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java	Thu Jun 26 14:49:23 2014 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+/**
+ * A thread that has it's thread locals, and inheritable thread
+ * locals erased on construction.
+ */
+public class ManagedLocalsThread extends Thread {
+    private static final Unsafe UNSAFE;
+    private static final long THREAD_LOCALS;
+    private static final long INHERITABLE_THREAD_LOCALS;
+
+    public ManagedLocalsThread(Runnable target) {
+        super(target);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(Runnable target, String name) {
+        super(target, name);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) {
+        super(group, target, name);
+        eraseThreadLocals();
+    }
+
+    /**
+     * Drops all thread locals (and inherited thread locals).
+     */
+    public final void eraseThreadLocals() {
+        UNSAFE.putObject(this, THREAD_LOCALS, null);
+        UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+    }
+
+    static {
+        UNSAFE = Unsafe.getUnsafe();
+        Class<?> t = Thread.class;
+        try {
+            THREAD_LOCALS = UNSAFE.objectFieldOffset
+                (t.getDeclaredField("threadLocals"));
+            INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
+                (t.getDeclaredField("inheritableThreadLocals"));
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+}
+