mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-11 07:28:36 +00:00
8150417: Make ThreadLocalRandom more robust against static initialization cycles
Reviewed-by: martin, psandoz, dholmes, mhaupt
This commit is contained in:
parent
90771aabae
commit
a9c908bcb3
@ -219,12 +219,20 @@ public final class SplittableRandom {
|
||||
return seed += gamma;
|
||||
}
|
||||
|
||||
// IllegalArgumentException messages
|
||||
static final String BAD_BOUND = "bound must be positive";
|
||||
static final String BAD_RANGE = "bound must be greater than origin";
|
||||
static final String BAD_SIZE = "size must be non-negative";
|
||||
|
||||
/**
|
||||
* The seed generator for default constructors.
|
||||
*/
|
||||
private static final AtomicLong defaultGen = new AtomicLong(initialSeed());
|
||||
private static final AtomicLong defaultGen
|
||||
= new AtomicLong(mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
|
||||
private static long initialSeed() {
|
||||
// at end of <clinit> to survive static initialization circularity
|
||||
static {
|
||||
if (java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
@ -234,17 +242,10 @@ public final class SplittableRandom {
|
||||
long s = (long)seedBytes[0] & 0xffL;
|
||||
for (int i = 1; i < 8; ++i)
|
||||
s = (s << 8) | ((long)seedBytes[i] & 0xffL);
|
||||
return s;
|
||||
defaultGen.set(s);
|
||||
}
|
||||
return (mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
}
|
||||
|
||||
// IllegalArgumentException messages
|
||||
static final String BAD_BOUND = "bound must be positive";
|
||||
static final String BAD_RANGE = "bound must be greater than origin";
|
||||
static final String BAD_SIZE = "size must be non-negative";
|
||||
|
||||
/*
|
||||
* Internal versions of nextX methods used by streams, as well as
|
||||
* the public nextX(origin, bound) methods. These exist mainly to
|
||||
|
||||
@ -125,53 +125,6 @@ public class ThreadLocalRandom extends Random {
|
||||
* but we provide identical statistical properties.
|
||||
*/
|
||||
|
||||
/** Generates per-thread initialization/probe field */
|
||||
private static final AtomicInteger probeGenerator = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* The next seed for default constructors.
|
||||
*/
|
||||
private static final AtomicLong seeder = new AtomicLong(initialSeed());
|
||||
|
||||
private static long initialSeed() {
|
||||
if (java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
return Boolean.getBoolean("java.util.secureRandomSeed");
|
||||
}})) {
|
||||
byte[] seedBytes = java.security.SecureRandom.getSeed(8);
|
||||
long s = (long)seedBytes[0] & 0xffL;
|
||||
for (int i = 1; i < 8; ++i)
|
||||
s = (s << 8) | ((long)seedBytes[i] & 0xffL);
|
||||
return s;
|
||||
}
|
||||
return (mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The seed increment.
|
||||
*/
|
||||
private static final long GAMMA = 0x9e3779b97f4a7c15L;
|
||||
|
||||
/**
|
||||
* The increment for generating probe values.
|
||||
*/
|
||||
private static final int PROBE_INCREMENT = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The increment of seeder per new instance.
|
||||
*/
|
||||
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
|
||||
|
||||
// Constants from SplittableRandom
|
||||
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
|
||||
private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
|
||||
|
||||
/** Rarely-used holder for the second of a pair of Gaussians */
|
||||
private static final ThreadLocal<Double> nextLocalGaussian =
|
||||
new ThreadLocal<>();
|
||||
|
||||
private static long mix64(long z) {
|
||||
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
|
||||
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
|
||||
@ -194,9 +147,6 @@ public class ThreadLocalRandom extends Random {
|
||||
initialized = true; // false during super() call
|
||||
}
|
||||
|
||||
/** The common ThreadLocalRandom */
|
||||
static final ThreadLocalRandom instance = new ThreadLocalRandom();
|
||||
|
||||
/**
|
||||
* Initialize Thread fields for the current thread. Called only
|
||||
* when Thread.threadLocalRandomProbe is zero, indicating that a
|
||||
@ -248,11 +198,6 @@ public class ThreadLocalRandom extends Random {
|
||||
return (int)(mix64(nextSeed()) >>> (64 - bits));
|
||||
}
|
||||
|
||||
// IllegalArgumentException messages
|
||||
static final String BAD_BOUND = "bound must be positive";
|
||||
static final String BAD_RANGE = "bound must be greater than origin";
|
||||
static final String BAD_SIZE = "size must be non-negative";
|
||||
|
||||
/**
|
||||
* The form of nextLong used by LongStream Spliterators. If
|
||||
* origin is greater than bound, acts as unbounded form of
|
||||
@ -1050,6 +995,32 @@ public class ThreadLocalRandom extends Random {
|
||||
return current();
|
||||
}
|
||||
|
||||
// Static initialization
|
||||
|
||||
/**
|
||||
* The seed increment.
|
||||
*/
|
||||
private static final long GAMMA = 0x9e3779b97f4a7c15L;
|
||||
|
||||
/**
|
||||
* The increment for generating probe values.
|
||||
*/
|
||||
private static final int PROBE_INCREMENT = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The increment of seeder per new instance.
|
||||
*/
|
||||
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
|
||||
|
||||
// Constants from SplittableRandom
|
||||
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
|
||||
private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
|
||||
|
||||
// IllegalArgumentException messages
|
||||
static final String BAD_BOUND = "bound must be positive";
|
||||
static final String BAD_RANGE = "bound must be greater than origin";
|
||||
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 long SEED;
|
||||
@ -1067,4 +1038,36 @@ public class ThreadLocalRandom extends Random {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Rarely-used holder for the second of a pair of Gaussians */
|
||||
private static final ThreadLocal<Double> nextLocalGaussian =
|
||||
new ThreadLocal<>();
|
||||
|
||||
/** Generates per-thread initialization/probe field */
|
||||
private static final AtomicInteger probeGenerator = new AtomicInteger();
|
||||
|
||||
/** The common ThreadLocalRandom */
|
||||
static final ThreadLocalRandom instance = new ThreadLocalRandom();
|
||||
|
||||
/**
|
||||
* The next seed for default constructors.
|
||||
*/
|
||||
private static final AtomicLong seeder
|
||||
= new AtomicLong(mix64(System.currentTimeMillis()) ^
|
||||
mix64(System.nanoTime()));
|
||||
|
||||
// at end of <clinit> to survive static initialization circularity
|
||||
static {
|
||||
if (java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
return Boolean.getBoolean("java.util.secureRandomSeed");
|
||||
}})) {
|
||||
byte[] seedBytes = java.security.SecureRandom.getSeed(8);
|
||||
long s = (long)seedBytes[0] & 0xffL;
|
||||
for (int i = 1; i < 8; ++i)
|
||||
s = (s << 8) | ((long)seedBytes[i] & 0xffL);
|
||||
seeder.set(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user