jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java
changeset 29903 b21ed6c8bc3f
parent 25859 3317bb8137f4
child 29904 d5f909aa26bc
equal deleted inserted replaced
29901:7288f904fbe8 29903:b21ed6c8bc3f
    24  */
    24  */
    25 
    25 
    26 package sun.misc;
    26 package sun.misc;
    27 
    27 
    28 import java.security.AccessControlContext;
    28 import java.security.AccessControlContext;
       
    29 import java.security.AccessController;
    29 import java.security.ProtectionDomain;
    30 import java.security.ProtectionDomain;
       
    31 import java.security.PrivilegedAction;
       
    32 import java.util.concurrent.atomic.AtomicInteger;
    30 
    33 
    31 /**
    34 /**
    32  * A thread that has no permissions, is not a member of any user-defined
    35  * A thread that has no permissions, is not a member of any user-defined
    33  * ThreadGroup and supports the ability to erase ThreadLocals.
    36  * ThreadGroup and supports the ability to erase ThreadLocals.
    34  *
    37  *
    35  * @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
    38  * @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
    36  */
    39  */
    37 public final class InnocuousThread extends Thread {
    40 public final class InnocuousThread extends Thread {
    38     private static final Unsafe UNSAFE;
    41     private static final Unsafe UNSAFE;
    39     private static final ThreadGroup THREADGROUP;
    42     private static final ThreadGroup INNOCUOUSTHREADGROUP;
    40     private static final AccessControlContext ACC;
    43     private static final AccessControlContext ACC;
    41     private static final long THREADLOCALS;
    44     private static final long THREADLOCALS;
    42     private static final long INHERITABLETHREADLOCALS;
    45     private static final long INHERITABLETHREADLOCALS;
    43     private static final long INHERITEDACCESSCONTROLCONTEXT;
    46     private static final long INHERITEDACCESSCONTROLCONTEXT;
    44 
    47 
       
    48     private static final AtomicInteger threadNumber = new AtomicInteger(1);
       
    49 
    45     public InnocuousThread(Runnable target) {
    50     public InnocuousThread(Runnable target) {
    46         super(THREADGROUP, target, "anInnocuousThread");
    51         this(INNOCUOUSTHREADGROUP, target,
       
    52              "InnocuousThread-" + threadNumber.getAndIncrement());
       
    53     }
       
    54 
       
    55     public InnocuousThread(Runnable target, String name) {
       
    56         this(INNOCUOUSTHREADGROUP, target, name);
       
    57     }
       
    58 
       
    59     private InnocuousThread(ThreadGroup group, Runnable target, String name) {
       
    60         super(group, target, name);
    47         UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
    61         UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
    48         eraseThreadLocals();
    62         eraseThreadLocals();
    49     }
    63     }
    50 
    64 
       
    65     // always report system class loader, or null
       
    66     private ClassLoader contextClassLoader = ClassLoader.getSystemClassLoader();
       
    67 
    51     @Override
    68     @Override
    52     public ClassLoader getContextClassLoader() {
    69     public ClassLoader getContextClassLoader() {
    53         // always report system class loader
    70         return contextClassLoader;
    54         return ClassLoader.getSystemClassLoader();
       
    55     }
    71     }
    56 
    72 
    57     @Override
    73     @Override
    58     public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
    74     public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
    59         // silently fail
    75         // silently fail
    60     }
    76     }
    61 
    77 
    62     @Override
    78     @Override
    63     public void setContextClassLoader(ClassLoader cl) {
    79     public void setContextClassLoader(ClassLoader cl) {
    64         throw new SecurityException("setContextClassLoader");
    80         if (cl == null)
       
    81             contextClassLoader = null;
       
    82         else
       
    83             throw new SecurityException("setContextClassLoader");
    65     }
    84     }
    66 
    85 
    67     // ensure run method is run only once
    86     // ensure run method is run only once
    68     private volatile boolean hasRun;
    87     private volatile boolean hasRun;
    69 
    88 
   111                 ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);
   130                 ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);
   112                 if (parent == null)
   131                 if (parent == null)
   113                     break;
   132                     break;
   114                 group = parent;
   133                 group = parent;
   115             }
   134             }
   116             THREADGROUP = new ThreadGroup(group, "InnocuousThreadGroup");
   135             final ThreadGroup root = group;
       
   136             INNOCUOUSTHREADGROUP = AccessController.doPrivileged(
       
   137                 (PrivilegedAction<ThreadGroup>) () ->
       
   138                     { return new ThreadGroup(root, "InnocuousThreadGroup"); });
   117         } catch (Exception e) {
   139         } catch (Exception e) {
   118             throw new Error(e);
   140             throw new Error(e);
   119         }
   141         }
   120     }
   142     }
   121 }
   143 }