37 |
|
* owning thread. |
38 |
|
* |
39 |
|
* Support for (non-public) subclass InnocuousForkJoinWorkerThread |
40 |
< |
* requires that we break quite a lot of encapsulation (via Unsafe) |
41 |
< |
* both here and in the subclass to access and set Thread fields. |
40 |
> |
* requires that we break quite a lot of encapsulation (via helper |
41 |
> |
* methods in Threadlocalrandom) both here and in the subclass to |
42 |
> |
* access and set Thread fields. |
43 |
|
*/ |
44 |
|
|
45 |
|
final ForkJoinPool pool; // the pool this thread works in |
64 |
|
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup, |
65 |
|
AccessControlContext acc) { |
66 |
|
super(threadGroup, null, "aForkJoinWorkerThread"); |
67 |
< |
U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc); |
68 |
< |
eraseThreadLocals(); // clear before registering |
67 |
> |
ThreadLocalRandom.setInheritedAccessControlContext(this,acc); |
68 |
> |
ThreadLocalRandom.eraseThreadLocals(this); // clear before registering |
69 |
|
this.pool = pool; |
70 |
|
this.workQueue = pool.registerWorker(this); |
71 |
|
} |
143 |
|
} |
144 |
|
|
145 |
|
/** |
145 |
– |
* Erases ThreadLocals by nulling out Thread maps. |
146 |
– |
*/ |
147 |
– |
final void eraseThreadLocals() { |
148 |
– |
U.putObject(this, THREADLOCALS, null); |
149 |
– |
U.putObject(this, INHERITABLETHREADLOCALS, null); |
150 |
– |
} |
151 |
– |
|
152 |
– |
/** |
146 |
|
* Non-public hook method for InnocuousForkJoinWorkerThread. |
147 |
|
*/ |
148 |
|
void afterTopLevelExec() { |
149 |
|
} |
150 |
|
|
158 |
– |
// Set up to allow setting thread fields in constructor |
159 |
– |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
160 |
– |
private static final long THREADLOCALS; |
161 |
– |
private static final long INHERITABLETHREADLOCALS; |
162 |
– |
private static final long INHERITEDACCESSCONTROLCONTEXT; |
163 |
– |
static { |
164 |
– |
try { |
165 |
– |
THREADLOCALS = U.objectFieldOffset |
166 |
– |
(Thread.class.getDeclaredField("threadLocals")); |
167 |
– |
INHERITABLETHREADLOCALS = U.objectFieldOffset |
168 |
– |
(Thread.class.getDeclaredField("inheritableThreadLocals")); |
169 |
– |
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset |
170 |
– |
(Thread.class.getDeclaredField("inheritedAccessControlContext")); |
171 |
– |
} catch (ReflectiveOperationException e) { |
172 |
– |
throw new Error(e); |
173 |
– |
} |
174 |
– |
} |
175 |
– |
|
151 |
|
/** |
152 |
|
* A worker thread that has no permissions, is not a member of any |
153 |
|
* user-defined ThreadGroup, and erases all ThreadLocals after |
156 |
|
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread { |
157 |
|
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */ |
158 |
|
private static final ThreadGroup innocuousThreadGroup = |
159 |
< |
createThreadGroup(); |
159 |
> |
ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup"); |
160 |
|
|
161 |
|
/** An AccessControlContext supporting no privileges */ |
162 |
|
private static final AccessControlContext INNOCUOUS_ACC = |
171 |
|
|
172 |
|
@Override // to erase ThreadLocals |
173 |
|
void afterTopLevelExec() { |
174 |
< |
eraseThreadLocals(); |
174 |
> |
ThreadLocalRandom.eraseThreadLocals(this); |
175 |
|
} |
176 |
|
|
177 |
|
@Override // to always report system loader |
187 |
|
throw new SecurityException("setContextClassLoader"); |
188 |
|
} |
189 |
|
|
215 |
– |
/** |
216 |
– |
* Returns a new group with the system ThreadGroup (the |
217 |
– |
* topmost, parent-less group) as parent. Uses Unsafe to |
218 |
– |
* traverse Thread.group and ThreadGroup.parent fields. |
219 |
– |
*/ |
220 |
– |
private static ThreadGroup createThreadGroup() { |
221 |
– |
try { |
222 |
– |
jdk.internal.misc.Unsafe u = jdk.internal.misc.Unsafe.getUnsafe(); |
223 |
– |
long tg = u.objectFieldOffset |
224 |
– |
(Thread.class.getDeclaredField("group")); |
225 |
– |
long gp = u.objectFieldOffset |
226 |
– |
(ThreadGroup.class.getDeclaredField("parent")); |
227 |
– |
ThreadGroup group = (ThreadGroup) |
228 |
– |
u.getObject(Thread.currentThread(), tg); |
229 |
– |
while (group != null) { |
230 |
– |
ThreadGroup parent = (ThreadGroup)u.getObject(group, gp); |
231 |
– |
if (parent == null) |
232 |
– |
return new ThreadGroup(group, |
233 |
– |
"InnocuousForkJoinWorkerThreadGroup"); |
234 |
– |
group = parent; |
235 |
– |
} |
236 |
– |
} catch (ReflectiveOperationException e) { |
237 |
– |
throw new Error(e); |
238 |
– |
} |
239 |
– |
// fall through if null as cannot-happen safeguard |
240 |
– |
throw new Error("Cannot create ThreadGroup"); |
241 |
– |
} |
190 |
|
} |
243 |
– |
|
191 |
|
} |