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 |