FACTORY_MAP = createFactoryMap();
/**
- * Returns the factory map, lazily constructing map on first use.
+ * Returns the factory map, lazily constructing it on first use.
+ * Although {@link ThreadLocalRandom} can only be accessed via
+ * {@link ThreadLocalRandom#current()}, a map entry is added nevertheless
+ * to record its properties that are otherwise not documented
+ * anywhere else.
+ *
Currently, no algorithm is deprecated.
*
- * @return Map of RandomGeneratorFactory classes.
+ * @return Map of RandomGeneratorProperties.
*/
- private static Map> createFactoryMap() {
- FactoryMapHolder.class.getModule().addUses(RandomGenerator.class);
- return ServiceLoader
- .load(RandomGenerator.class, ClassLoader.getPlatformClassLoader())
- .stream()
- .filter(p -> !p.type().isInterface())
- .collect(Collectors.toMap(p -> p.type().getSimpleName(), Function.identity()));
+ private static Map createFactoryMap() {
+ return Map.ofEntries(
+ entry(SecureRandom.class, "SecureRandom", "Legacy",
+ 0, 0, 0, Integer.MAX_VALUE,
+ INSTANTIABLE | BYTE_ARRAY_SEED | STOCHASTIC | deprecationBit(SecureRandom.class)),
+ entry(Random.class, "Random", "Legacy",
+ 48, 0, 0, 0,
+ INSTANTIABLE | LONG_SEED | deprecationBit(Random.class)),
+ entry(SplittableRandom.class, "SplittableRandom", "Legacy",
+ 64, 0, 0, 1,
+ INSTANTIABLE | LONG_SEED | deprecationBit(SplittableRandom.class)),
+ entry(L32X64MixRandom.class, "L32X64MixRandom", "LXM",
+ 64, 1, 32, 1,
+ ALL_CONSTRUCTORS),
+ entry(L64X128MixRandom.class, "L64X128MixRandom", "LXM",
+ 128, 1, 64, 2,
+ ALL_CONSTRUCTORS),
+ entry(L64X128StarStarRandom.class, "L64X128StarStarRandom", "LXM",
+ 128, 1, 64, 2,
+ ALL_CONSTRUCTORS),
+ entry(L64X256MixRandom.class, "L64X256MixRandom", "LXM",
+ 256, 1, 64, 4,
+ ALL_CONSTRUCTORS),
+ entry(L64X1024MixRandom.class, "L64X1024MixRandom", "LXM",
+ 1024, 1, 64, 16,
+ ALL_CONSTRUCTORS),
+ entry(L128X128MixRandom.class, "L128X128MixRandom", "LXM",
+ 128, 1, 128, 1,
+ ALL_CONSTRUCTORS),
+ entry(L128X256MixRandom.class, "L128X256MixRandom", "LXM",
+ 256, 1, 128, 1,
+ ALL_CONSTRUCTORS),
+ entry(L128X1024MixRandom.class, "L128X1024MixRandom", "LXM",
+ 1024, 1, 128, 1,
+ ALL_CONSTRUCTORS),
+ entry(Xoroshiro128PlusPlus.class, "Xoroshiro128PlusPlus", "Xoroshiro",
+ 128, 1, 0, 1,
+ ALL_CONSTRUCTORS),
+ entry(Xoshiro256PlusPlus.class, "Xoshiro256PlusPlus", "Xoshiro",
+ 256, 1, 0, 3,
+ ALL_CONSTRUCTORS),
+ entry(ThreadLocalRandom.class, "ThreadLocalRandom", "Legacy",
+ 64, 0, 0, 1,
+ deprecationBit(ThreadLocalRandom.class))
+ );
+ }
+
+ private static Map.Entry entry(
+ Class extends RandomGenerator> rgClass, String name, String group,
+ int i, int j, int k, int equidistribution,
+ int flags) {
+ return Map.entry(name,
+ new RandomGeneratorProperties(rgClass, name, group,
+ i, j, k, equidistribution,
+ flags));
+ }
+
+ private static int deprecationBit(Class extends RandomGenerator> rgClass) {
+ return rgClass.isAnnotationPresent(Deprecated.class) ? DEPRECATED : 0;
+ }
+
+ private RandomGenerator create() {
+ return switch (name) {
+ case "Random" -> new Random();
+ case "SecureRandom" -> new SecureRandom();
+ case "SplittableRandom" -> new SplittableRandom();
+ case "L32X64MixRandom" -> new L32X64MixRandom();
+ case "L64X128MixRandom" -> new L64X128MixRandom();
+ case "L64X128StarStarRandom" -> new L64X128StarStarRandom();
+ case "L64X256MixRandom" -> new L64X256MixRandom();
+ case "L64X1024MixRandom" -> new L64X1024MixRandom();
+ case "L128X128MixRandom" -> new L128X128MixRandom();
+ case "L128X256MixRandom" -> new L128X256MixRandom();
+ case "L128X1024MixRandom" -> new L128X1024MixRandom();
+ case "Xoroshiro128PlusPlus" -> new Xoroshiro128PlusPlus();
+ case "Xoshiro256PlusPlus" -> new Xoshiro256PlusPlus();
+ default -> throw new InternalError("should not happen");
+ };
+ }
+
+ private RandomGenerator create(long seed) {
+ if (isInstantiable() && (flags & LONG_SEED) == 0) {
+ throw new UnsupportedOperationException("Random algorithm "
+ + name + " does not support a long seed");
+ }
+ return switch (name) {
+ case "Random" -> new Random(seed);
+ case "SplittableRandom" -> new SplittableRandom(seed);
+ case "L32X64MixRandom" -> new L32X64MixRandom(seed);
+ case "L64X128MixRandom" -> new L64X128MixRandom(seed);
+ case "L64X128StarStarRandom" -> new L64X128StarStarRandom(seed);
+ case "L64X256MixRandom" -> new L64X256MixRandom(seed);
+ case "L64X1024MixRandom" -> new L64X1024MixRandom(seed);
+ case "L128X128MixRandom" -> new L128X128MixRandom(seed);
+ case "L128X256MixRandom" -> new L128X256MixRandom(seed);
+ case "L128X1024MixRandom" -> new L128X1024MixRandom(seed);
+ case "Xoroshiro128PlusPlus" -> new Xoroshiro128PlusPlus(seed);
+ case "Xoshiro256PlusPlus" -> new Xoshiro256PlusPlus(seed);
+ default -> throw new InternalError("should not happen");
+ };
+ }
+
+ private RandomGenerator create(byte[] seed) {
+ if (isInstantiable() && (flags & BYTE_ARRAY_SEED) == 0) {
+ throw new UnsupportedOperationException("Random algorithm "
+ + name + " does not support a byte[] seed");
+ }
+ return switch (name) {
+ case "SecureRandom" -> new SecureRandom(seed);
+ case "L32X64MixRandom" -> new L32X64MixRandom(seed);
+ case "L64X128MixRandom" -> new L64X128MixRandom(seed);
+ case "L64X128StarStarRandom" -> new L64X128StarStarRandom(seed);
+ case "L64X256MixRandom" -> new L64X256MixRandom(seed);
+ case "L64X1024MixRandom" -> new L64X1024MixRandom(seed);
+ case "L128X128MixRandom" -> new L128X128MixRandom(seed);
+ case "L128X256MixRandom" -> new L128X256MixRandom(seed);
+ case "L128X1024MixRandom" -> new L128X1024MixRandom(seed);
+ case "Xoroshiro128PlusPlus" -> new Xoroshiro128PlusPlus(seed);
+ case "Xoshiro256PlusPlus" -> new Xoshiro256PlusPlus(seed);
+ default -> throw new InternalError("should not happen");
+ };
+ }
+
+ private boolean isStochastic() {
+ return (flags & STOCHASTIC) != 0;
+ }
+
+ private boolean isHardware() {
+ return (flags & HARDWARE) != 0;
+ }
+
+ private boolean isInstantiable() {
+ return (flags & INSTANTIABLE) != 0;
+ }
+
+ private boolean isDeprecated() {
+ return (flags & DEPRECATED) != 0;
+ }
+
+ private BigInteger period() {
+ /*
+ * 0 if i = j = k = 0
+ * (2^i - j) 2^k otherwise
+ */
+ return i == 0 && j == 0 && k == 0
+ ? BigInteger.ZERO
+ : BigInteger.ONE.shiftLeft(i).subtract(BigInteger.valueOf(j)).shiftLeft(k);
+ }
+
+ private int stateBits() {
+ return i == 0 && k == 0 ? Integer.MAX_VALUE : i + k;
}
}
+ /**
+ * Random generator properties.
+ */
+ private final RandomGeneratorProperties properties;
+
/**
* Private constructor.
*
- * @param provider Provider class to wrap.
+ * @param properties Random generator properties.
*/
- private RandomGeneratorFactory(Provider extends RandomGenerator> provider) {
- this.provider = provider;
+ private RandomGeneratorFactory(RandomGeneratorProperties properties) {
+ this.properties = properties;
}
/**
- * Returns the factory map, lazily constructing map on first call.
+ * Returns the factory map, lazily constructing the map on first call.
*
- * @return Map of RandomGeneratorFactory classes.
+ * @return Map of random generator classes.
*/
- private static Map> getFactoryMap() {
- return FactoryMapHolder.FACTORY_MAP;
+ private static Map getFactoryMap() {
+ return RandomGeneratorProperties.FACTORY_MAP;
}
/**
- * Return the annotation for the specified provider.
- *
- * @return RandomGeneratorProperties annotation for the specified provider.
- */
- private RandomGeneratorProperties getProperties() {
- if (properties == null) {
- synchronized (provider) {
- if (properties == null) {
- properties = provider.type().getDeclaredAnnotation(RandomGeneratorProperties.class);
- Objects.requireNonNull(properties, provider.type() + " missing annotation");
- }
- }
- }
-
- return properties;
- }
-
- /**
- * Return true if the provider is a subclass of the category.
+ * Return true if the random generator class is a subclass of the category.
*
* @param category Interface category, sub-interface of {@link RandomGenerator}.
*
- * @return true if the provider is a subclass of the category.
+ * @return true if the random generator class is a subclass of the category.
*/
private boolean isSubclass(Class extends RandomGenerator> category) {
- return isSubclass(category, provider);
+ return isSubclass(category, properties.rgClass());
}
/**
- * Return true if the provider is a subclass of the category.
+ * Return true if rgClass is a subclass of the category.
*
* @param category Interface category, sub-interface of {@link RandomGenerator}.
- * @param provider Provider that is being filtered.
+ * @param rgClass Class that is being filtered.
*
- * @return true if the provider is a subclass of the category.
+ * @return true if rgClass is a subclass of the category.
*/
private static boolean isSubclass(Class extends RandomGenerator> category,
- Provider extends RandomGenerator> provider) {
- return provider != null && category.isAssignableFrom(provider.type());
+ Class extends RandomGenerator> rgClass) {
+ return rgClass != null && category.isAssignableFrom(rgClass);
}
/**
- * Returns the provider matching name and category.
+ * Returns a RandomGeneratorProperties instance matching name and category.
*
- * @param name Name of RandomGenerator
- * @param category Interface category, sub-interface of {@link RandomGenerator}.
- *
- * @return A provider matching name and category.
- *
- * @throws IllegalArgumentException if provider is not a subclass of category.
+ * @param name Name of RandomGenerator
+ * @param category Interface category, sub-interface of {@link RandomGenerator}.
+ * @return A RandomGeneratorProperties instance matching name and category.
+ * @throws IllegalArgumentException if the resulting type is not a subclass of category.
*/
- private static Provider extends RandomGenerator> findProvider(String name,
- Class extends RandomGenerator> category)
- throws IllegalArgumentException {
- Map> fm = getFactoryMap();
- Provider extends RandomGenerator> provider = fm.get(name);
- if (provider == null) {
+ private static RandomGeneratorProperties findClass(String name,
+ Class extends RandomGenerator> category) throws IllegalArgumentException {
+ RandomGeneratorProperties properties = name != null
+ ? getFactoryMap().get(name)
+ : null;
+ if (properties == null || !properties.isInstantiable()) {
throw new IllegalArgumentException("No implementation of the random number generator algorithm \"" +
- name +
- "\" is available");
- } else if (!isSubclass(category, provider)) {
- throw new IllegalArgumentException("The random number generator algorithm \"" +
- name +
- "\" is not implemented with the interface \"" +
- category.getSimpleName() +
- "\"");
+ name +
+ "\" is available");
}
- return provider;
+ if (!isSubclass(category, properties.rgClass())) {
+ throw new IllegalArgumentException("The random number generator algorithm \"" +
+ name +
+ "\" is not implemented with the interface \"" +
+ category.getSimpleName() +
+ "\"");
+ }
+ return properties;
}
/**
@@ -255,8 +392,8 @@ public final class RandomGeneratorFactory {
static T of(String name, Class category)
throws IllegalArgumentException {
@SuppressWarnings("unchecked")
- T uncheckedRandomGenerator = (T)findProvider(name, category).get();
- return uncheckedRandomGenerator;
+ T instance = (T) findClass(name, category).create();
+ return instance;
}
/**
@@ -273,68 +410,7 @@ public final class RandomGeneratorFactory {
*/
static RandomGeneratorFactory factoryOf(String name, Class category)
throws IllegalArgumentException {
- Provider extends RandomGenerator> uncheckedProvider = findProvider(name, category);
- return new RandomGeneratorFactory<>(uncheckedProvider);
- }
-
- /**
- * Fetch the required constructors for class of random number algorithm.
- *
- * @param randomGeneratorClass class of random number algorithm (provider)
- */
- private void getConstructors(Class extends RandomGenerator> randomGeneratorClass) {
- if (ctor == null) {
- synchronized (provider) {
- if (ctor == null) {
- PrivilegedExceptionAction[]> ctorAction = randomGeneratorClass::getConstructors;
- try {
- @SuppressWarnings("removal")
- Constructor>[] ctors = AccessController.doPrivileged(ctorAction);
-
- Constructor tmpCtor = null;
- Constructor tmpCtorLong = null;
- Constructor tmpCtorBytes = null;
-
-
- for (Constructor> ctorGeneric : ctors) {
- @SuppressWarnings("unchecked")
- Constructor ctorSpecific = (Constructor) ctorGeneric;
- final Class>[] parameterTypes = ctorSpecific.getParameterTypes();
-
- if (parameterTypes.length == 0) {
- tmpCtor = ctorSpecific;
- } else if (parameterTypes.length == 1) {
- Class> argType = parameterTypes[0];
-
- if (argType == long.class) {
- tmpCtorLong = ctorSpecific;
- } else if (argType == byte[].class) {
- tmpCtorBytes = ctorSpecific;
- }
- }
- }
-
- if (tmpCtor == null) {
- throw new IllegalStateException("Random algorithm " + name() + " is missing a default constructor");
- }
-
- // Store specialized constructors first, guarded by ctor
- ctorBytes = tmpCtorBytes;
- ctorLong = tmpCtorLong;
- ctor = tmpCtor;
- } catch (PrivilegedActionException ex) {
- // Do nothing
- }
- }
- }
- }
- }
-
- /**
- * Ensure all the required constructors are fetched.
- */
- private void ensureConstructors() {
- getConstructors(provider.type());
+ return new RandomGeneratorFactory<>(findClass(name, category));
}
/**
@@ -355,7 +431,7 @@ public final class RandomGeneratorFactory {
Objects.requireNonNull(name);
@SuppressWarnings("unchecked")
RandomGeneratorFactory factory =
- (RandomGeneratorFactory)factoryOf(name, RandomGenerator.class);
+ (RandomGeneratorFactory) factoryOf(name, RandomGenerator.class);
return factory;
}
@@ -369,23 +445,21 @@ public final class RandomGeneratorFactory {
* @return a {@link RandomGeneratorFactory}
*/
public static RandomGeneratorFactory getDefault() {
- return factoryOf("L32X64MixRandom", RandomGenerator.class);
+ return factoryOf(DEFAULT_ALGORITHM, RandomGenerator.class);
}
/**
* Returns a non-empty stream of available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}.
- *
+ *
* RandomGenerators that are marked as deprecated are not included in the result.
*
* @return a non-empty stream of all available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}.
*/
public static Stream> all() {
- Map> fm = getFactoryMap();
- return fm.values()
- .stream()
- .filter(p -> !p.type().isAnnotationPresent(Deprecated.class) &&
- p.type().isAnnotationPresent(RandomGeneratorProperties.class))
- .map(RandomGeneratorFactory::new);
+ return getFactoryMap().values()
+ .stream()
+ .filter(p -> p.isInstantiable() && !p.isDeprecated())
+ .map(RandomGeneratorFactory::new);
}
/**
@@ -395,7 +469,7 @@ public final class RandomGeneratorFactory {
* @return Name of the algorithm.
*/
public String name() {
- return provider.type().getSimpleName();
+ return properties.name();
}
/**
@@ -405,7 +479,7 @@ public final class RandomGeneratorFactory {
* @return Group name of the algorithm.
*/
public String group() {
- return getProperties().group();
+ return properties.group();
}
/**
@@ -416,11 +490,7 @@ public final class RandomGeneratorFactory {
* to maintain state of seed.
*/
public int stateBits() {
- RandomGeneratorProperties properties = getProperties();
- int i = properties.i();
- int k = properties.k();
-
- return i == 0 && k == 0 ? Integer.MAX_VALUE : i + k;
+ return properties.stateBits();
}
/**
@@ -429,7 +499,7 @@ public final class RandomGeneratorFactory {
* @return the equidistribution of the algorithm.
*/
public int equidistribution() {
- return getProperties().equidistribution();
+ return properties.equidistribution();
}
/**
@@ -440,16 +510,7 @@ public final class RandomGeneratorFactory {
* @return BigInteger period.
*/
public BigInteger period() {
- RandomGeneratorProperties properties = getProperties();
- int i = properties.i();
- int j = properties.j();
- int k = properties.k();
-
- if (i == 0 && j == 0 && k == 0) {
- return BigInteger.ZERO;
- } else {
- return BigInteger.ONE.shiftLeft(i).subtract(BigInteger.valueOf(j)).shiftLeft(k);
- }
+ return properties.period();
}
/**
@@ -460,7 +521,7 @@ public final class RandomGeneratorFactory {
* @return true if random generator is statistical.
*/
public boolean isStatistical() {
- return !getProperties().isStochastic();
+ return !properties.isStochastic();
}
/**
@@ -470,7 +531,7 @@ public final class RandomGeneratorFactory {
* @return true if random generator is stochastic.
*/
public boolean isStochastic() {
- return getProperties().isStochastic();
+ return properties.isStochastic();
}
/**
@@ -480,7 +541,7 @@ public final class RandomGeneratorFactory {
* @return true if random generator is generated by hardware.
*/
public boolean isHardware() {
- return getProperties().isHardware();
+ return properties.isHardware();
}
/**
@@ -547,66 +608,64 @@ public final class RandomGeneratorFactory {
* marked for deprecation
*/
public boolean isDeprecated() {
- return provider.type().isAnnotationPresent(Deprecated.class);
+ return properties.isDeprecated();
}
/**
- * Create an instance of {@link RandomGenerator} based on
+ * Create an instance of {@link RandomGenerator} based on the
* algorithm chosen.
*
- * @return new in instance of {@link RandomGenerator}.
- *
+ * @return new instance of {@link RandomGenerator}.
*/
public T create() {
- try {
- ensureConstructors();
- return ctor.newInstance();
- } catch (Exception ex) {
- // Should never happen.
- throw new IllegalStateException("Random algorithm " + name() + " is missing a default constructor", ex);
- }
+ @SuppressWarnings("unchecked")
+ T instance = (T) properties.create();
+ return instance;
}
/**
- * Create an instance of {@link RandomGenerator} based on
- * algorithm chosen
- * providing a starting long seed. If long seed is not supported by an
- * algorithm then the no argument form of create is used.
+ * Create an instance of {@link RandomGenerator} based on the
+ * algorithm chosen,
+ * and the provided {@code seed}.
+ * If the {@link RandomGenerator} doesn't support instantiation through
+ * a {@code seed} of type {@code long} then this method throws
+ * an {@link UnsupportedOperationException}.
*
* @param seed long random seed value.
*
- * @return new in instance of {@link RandomGenerator}.
+ * @return new instance of {@link RandomGenerator}.
+ *
+ * @throws UnsupportedOperationException
+ * if a {@code seed} of type {@code long} in not supported.
*/
public T create(long seed) {
- try {
- ensureConstructors();
- return ctorLong.newInstance(seed);
- } catch (Exception ex) {
- return create();
- }
+ @SuppressWarnings("unchecked")
+ T instance = (T) properties.create(seed);
+ return instance;
}
/**
- * Create an instance of {@link RandomGenerator} based on
- * algorithm chosen
- * providing a starting byte[] seed. If byte[] seed is not supported by an
- * algorithm then the no
- * argument form of create is used.
+ * Create an instance of {@link RandomGenerator} based on the
+ * algorithm chosen,
+ * and the provided {@code seed}.
+ * If the {@link RandomGenerator} doesn't support instantiation through
+ * a {@code seed} of type {@code byte[]} then this method throws
+ * an {@link UnsupportedOperationException}.
*
* @param seed byte array random seed value.
*
- * @return new in instance of {@link RandomGenerator}.
+ * @return new instance of {@link RandomGenerator}.
+ *
+ * @throws UnsupportedOperationException
+ * if a {@code seed} of type {@code byte[]} in not supported.
*
* @throws NullPointerException if seed is null.
*/
public T create(byte[] seed) {
Objects.requireNonNull(seed, "seed must not be null");
- try {
- ensureConstructors();
- return ctorBytes.newInstance(seed);
- } catch (Exception ex) {
- return create();
- }
+ @SuppressWarnings("unchecked")
+ T instance = (T) properties.create(seed);
+ return instance;
}
}
diff --git a/src/java.base/share/classes/java/util/random/package-info.java b/src/java.base/share/classes/java/util/random/package-info.java
index 2e16b319f44..9f9df0ff395 100644
--- a/src/java.base/share/classes/java/util/random/package-info.java
+++ b/src/java.base/share/classes/java/util/random/package-info.java
@@ -81,8 +81,8 @@
* {@code import java.util.random.*;}
*
* Then one can choose a specific implementation by giving the name of a generator
- * algorithm to the static method {@link RandomGenerator#of}, in which case the
- * no-arguments constructor for that implementation is used:
+ * algorithm to the static method {@link RandomGenerator#of}, in which case
+ * a {@link RandomGenerator} is constructed without any seed value:
*
* {@code RandomGenerator g = RandomGenerator.of("L64X128MixRandom");}
*
@@ -125,8 +125,8 @@
*
* Choosing a Random Number Generator Algorithm
*
- * There are three groups of random number generator algorithm provided
- * in Java: the Legacy group, the LXM group, and the Xoroshiro/Xoshiro group.
+ *
Random number generator algorithms are organized in groups,
+ * as described {@linkplain java.util.random##algorithms below}.
*
*
The legacy group includes random number generators that existed
* before JDK 17: Random, ThreadLocalRandom, SplittableRandom, and
@@ -304,6 +304,13 @@
*
1 |
*
*
+ * SecureRandom |
+ * Legacy |
+ * BigInteger.ZERO |
+ * Integer.MAX_VALUE |
+ * Integer.MAX_VALUE |
+ *
+ *
* ThreadLocalRandom * |
* Legacy |
* BigInteger.ONE.shiftLeft(64) |
diff --git a/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java
index e6f4f896dc0..4af9ecc3dd4 100644
--- a/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L128X1024MixRandom",
- group = "LXM",
- i = 1024, j = 1, k = 128,
- equidistribution = 1
-)
public final class L128X1024MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java
index d03fcfc0864..1323139ea59 100644
--- a/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L128X128MixRandom",
- group = "LXM",
- i = 128, j = 1, k = 128,
- equidistribution = 1
-)
public final class L128X128MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java
index 81440d7316a..19fd31b069a 100644
--- a/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L128X256MixRandom",
- group = "LXM",
- i = 256, j = 1, k = 128,
- equidistribution = 1
-)
public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java
index 0f6beea7bc7..a9442bd0ef2 100644
--- a/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L32X64MixRandom",
- group = "LXM",
- i = 64, j = 1, k = 32,
- equidistribution = 1
-)
public final class L32X64MixRandom extends AbstractSplittableWithBrineGenerator {
/*
* Implementation Overview.
diff --git a/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java
index e4eb82d450e..074aac0c70e 100644
--- a/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L64X1024MixRandom",
- group = "LXM",
- i = 1024, j = 1, k = 64,
- equidistribution = 16
-)
public final class L64X1024MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java
index 7dd757f312b..37e10237c39 100644
--- a/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L64X128MixRandom",
- group = "LXM",
- i = 128, j = 1, k = 64,
- equidistribution = 2
-)
public final class L64X128MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java
index 15b9bc312da..1d1a00ca006 100644
--- a/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L64X128StarStarRandom",
- group = "LXM",
- i = 128, j = 1, k = 64,
- equidistribution = 2
-)
public final class L64X128StarStarRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java
index bb605df5fdc..109148e3f01 100644
--- a/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java
+++ b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "splittable" pseudorandom number generator (PRNG) whose period
@@ -75,12 +74,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "L64X256MixRandom",
- group = "LXM",
- i = 256, j = 1, k = 64,
- equidistribution = 4
-)
public final class L64X256MixRandom extends AbstractSplittableWithBrineGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java
index d20b3cf9e6a..3dc90fff4d0 100644
--- a/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java
+++ b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import java.util.random.RandomGenerator.LeapableGenerator;
import jdk.internal.util.random.RandomSupport;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "jumpable and leapable" pseudorandom number generator (PRNG) whose period
@@ -72,12 +71,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "Xoroshiro128PlusPlus",
- group = "Xoroshiro",
- i = 128, j = 1, k = 0,
- equidistribution = 1
-)
public final class Xoroshiro128PlusPlus implements LeapableGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java
index fdefe02dd03..1ae4aeaac02 100644
--- a/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java
+++ b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java
@@ -29,7 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.random.RandomGenerator;
import java.util.random.RandomGenerator.LeapableGenerator;
import jdk.internal.util.random.RandomSupport;
-import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
/**
* A "jumpable and leapable" pseudorandom number generator (PRNG) whose period
@@ -87,12 +86,6 @@ import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
* @since 17
*
*/
-@RandomGeneratorProperties(
- name = "Xoshiro256PlusPlus",
- group = "Xoshiro",
- i = 256, j = 1, k = 0,
- equidistribution = 3
-)
public final class Xoshiro256PlusPlus implements LeapableGenerator {
/*
diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java
index c80d67005ae..402be6b5dfe 100644
--- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java
+++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,7 @@
package jdk.internal.util.random;
-import java.lang.annotation.*;
-import java.math.BigInteger;
import java.util.Objects;
-import java.util.Random;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
@@ -53,49 +50,6 @@ import java.util.stream.StreamSupport;
* @since 17
*/
public class RandomSupport {
- /**
- * Annotation providing RandomGenerator properties.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface RandomGeneratorProperties {
- /**
- * Name of algorithm.
- */
- String name();
-
- /**
- * Category of algorithm.
- */
- String group() default "Legacy";
-
- /**
- * Algorithm period defined as:
- *
- * BigInteger.ONE.shiftLeft(i)
- * .subtract(j)
- * .shiftLeft(k)
- */
- int i() default 0;
- int j() default 0;
- int k() default 0;
-
- /**
- * The equidistribution of the algorithm.
- */
- int equidistribution() default Integer.MAX_VALUE;
-
- /**
- * Is the algorithm based on entropy (true random.)
- */
- boolean isStochastic() default false;
-
- /**
- * Is the algorithm assisted by hardware (fast true random.)
- */
- boolean isHardware() default false;
- }
-
/*
* Implementation Overview.
*
diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
index edbbad78c9d..a8b0a0c992c 100644
--- a/src/java.base/share/classes/module-info.java
+++ b/src/java.base/share/classes/module-info.java
@@ -419,19 +419,4 @@ module java.base {
provides java.nio.file.spi.FileSystemProvider with
jdk.internal.jrtfs.JrtFileSystemProvider;
- provides java.util.random.RandomGenerator with
- java.security.SecureRandom,
- java.util.Random,
- java.util.SplittableRandom,
- jdk.internal.random.L32X64MixRandom,
- jdk.internal.random.L64X128MixRandom,
- jdk.internal.random.L64X128StarStarRandom,
- jdk.internal.random.L64X256MixRandom,
- jdk.internal.random.L64X1024MixRandom,
- jdk.internal.random.L128X128MixRandom,
- jdk.internal.random.L128X256MixRandom,
- jdk.internal.random.L128X1024MixRandom,
- jdk.internal.random.Xoroshiro128PlusPlus,
- jdk.internal.random.Xoshiro256PlusPlus;
-
}
diff --git a/test/jdk/java/util/Random/RandomTestCoverage.java b/test/jdk/java/util/Random/RandomTestCoverage.java
index be12d188198..a0e906fbbe2 100644
--- a/test/jdk/java/util/Random/RandomTestCoverage.java
+++ b/test/jdk/java/util/Random/RandomTestCoverage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,7 +87,7 @@ public class RandomTestCoverage {
DoubleStream doubleStream4 = rng.doubles(5, 0.5, 1.0);
}
- static void checkPredicates(RandomGeneratorFactory factory) {
+ static void checkPredicates(RandomGeneratorFactory factory) {
RandomGenerator rng = factory.create();
if (rng instanceof ArbitrarilyJumpableGenerator != factory.isArbitrarilyJumpable()) {
throw new RuntimeException("isArbitrarilyJumpable failing");
@@ -156,7 +156,7 @@ public class RandomTestCoverage {
coverFactory(RandomGeneratorFactory.of(name));
}
- static void coverFactory(RandomGeneratorFactory factory) {
+ static void coverFactory(RandomGeneratorFactory factory) {
String name = factory.name();
String group = factory.group();
int stateBits = factory.stateBits();
@@ -171,8 +171,34 @@ public class RandomTestCoverage {
boolean isSplittable = factory.isSplittable();
coverRandomGenerator(factory.create());
- coverRandomGenerator(factory.create(12345L));
- coverRandomGenerator(factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}));
+ // test create(long)
+ switch (factory.name()) {
+ // SecureRandom doesn't have long constructors so we expect
+ // UnsupportedOperationException
+ case "SecureRandom" -> {
+ try {
+ factory.create(12345L);
+ throw new AssertionError("RandomGeneratorFactory.create(long) was expected" +
+ "to throw UnsupportedOperationException for " + factory.name() + " but didn't");
+ } catch (UnsupportedOperationException ignored) {
+ }
+ }
+ default -> coverRandomGenerator(factory.create(12345L));
+ }
+ // test create(byte[])
+ switch (factory.name()) {
+ // these don't have byte[] constructors so we expect UnsupportedOperationException
+ case "Random",
+ "SplittableRandom" -> {
+ try {
+ factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
+ throw new AssertionError("RandomGeneratorFactory.create(byte[]) was expected" +
+ "to throw UnsupportedOperationException for " + factory.name() + " but didn't");
+ } catch (UnsupportedOperationException ignored) {
+ }
+ }
+ default -> coverRandomGenerator(factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}));
+ }
}
static void coverDefaults() {
@@ -188,32 +214,35 @@ public class RandomTestCoverage {
coverOf(factory.name());
});
RandomGeneratorFactory.all()
- .filter(f -> f.isStreamable())
+ .filter(RandomGeneratorFactory::isStreamable)
.forEach(factory -> {
coverStreamable((StreamableGenerator)factory.create());
});
RandomGeneratorFactory.all()
- .filter(f -> f.isSplittable())
+ .filter(RandomGeneratorFactory::isSplittable)
.forEach(factory -> {
coverSplittable((SplittableGenerator)factory.create());
});
RandomGeneratorFactory.all()
- .filter(f -> f.isJumpable())
+ .filter(RandomGeneratorFactory::isJumpable)
.forEach(factory -> {
coverJumpable((JumpableGenerator)factory.create());
});
RandomGeneratorFactory.all()
- .filter(f -> f.isLeapable())
+ .filter(RandomGeneratorFactory::isLeapable)
.forEach(factory -> {
coverLeapable((LeapableGenerator)factory.create());
});
RandomGeneratorFactory.all()
- .filter(f -> f.isArbitrarilyJumpable())
+ .filter(RandomGeneratorFactory::isArbitrarilyJumpable)
.forEach(factory -> {
coverArbitrarilyJumpable((ArbitrarilyJumpableGenerator)factory.create());
});
+ RandomGeneratorFactory.all()
+ .forEach(RandomTestCoverage::checkPredicates);
coverRandomGenerator(new SecureRandom());
coverRandomGenerator(ThreadLocalRandom.current());
+ coverDefaults();
}
}