--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Jul 15 13:51:43 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Jul 15 13:55:51 2016 -0700
@@ -36,6 +36,7 @@
package java.util.concurrent;
import java.io.ObjectStreamField;
+import java.security.AccessControlContext;
import java.util.Random;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
@@ -47,6 +48,7 @@
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.StreamSupport;
+import jdk.internal.misc.Unsafe;
/**
* A random number generator isolated to the current thread. Like the
@@ -95,7 +97,9 @@
* ThreadLocalRandom sequence. The dual use is a marriage of
* convenience, but is a simple and efficient way of reducing
* application-level overhead and footprint of most concurrent
- * programs.
+ * programs. Even more opportunistically, we also define here
+ * other package-private utilities that access Thread class
+ * fields.
*
* Even though this class subclasses java.util.Random, it uses the
* same basic algorithm as java.util.SplittableRandom. (See its
@@ -958,6 +962,49 @@
return r;
}
+ // Support for other package-private ThreadLocal access
+
+ /**
+ * Erases ThreadLocals by nulling out Thread maps.
+ */
+ static final void eraseThreadLocals(Thread thread) {
+ U.putObject(thread, THREADLOCALS, null);
+ U.putObject(thread, INHERITABLETHREADLOCALS, null);
+ }
+
+ static final void setInheritedAccessControlContext(Thread thread,
+ AccessControlContext acc) {
+ U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
+ }
+
+ /**
+ * Returns a new group with the system ThreadGroup (the
+ * topmost, parent-less group) as parent. Uses Unsafe to
+ * traverse Thread.group and ThreadGroup.parent fields.
+ */
+ static final ThreadGroup createThreadGroup(String name) {
+ if (name == null)
+ throw new NullPointerException();
+ try {
+ long tg = U.objectFieldOffset
+ (Thread.class.getDeclaredField("group"));
+ long gp = U.objectFieldOffset
+ (ThreadGroup.class.getDeclaredField("parent"));
+ ThreadGroup group = (ThreadGroup)
+ U.getObject(Thread.currentThread(), tg);
+ while (group != null) {
+ ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
+ if (parent == null)
+ return new ThreadGroup(group, name);
+ group = parent;
+ }
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ // fall through if null as cannot-happen safeguard
+ throw new Error("Cannot create ThreadGroup");
+ }
+
// Serialization support
private static final long serialVersionUID = -5851777807851030925L;
@@ -1022,10 +1069,13 @@
static final String BAD_SIZE = "size must be non-negative";
// Unsafe mechanics
- private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+ private static final Unsafe U = Unsafe.getUnsafe();
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
+ private static final long THREADLOCALS;
+ private static final long INHERITABLETHREADLOCALS;
+ private static final long INHERITEDACCESSCONTROLCONTEXT;
static {
try {
SEED = U.objectFieldOffset
@@ -1034,6 +1084,12 @@
(Thread.class.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = U.objectFieldOffset
(Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ THREADLOCALS = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocals"));
+ INHERITABLETHREADLOCALS = U.objectFieldOffset
+ (Thread.class.getDeclaredField("inheritableThreadLocals"));
+ INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
+ (Thread.class.getDeclaredField("inheritedAccessControlContext"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}