JDK-8332131 : Remove the usage of ServiceLoader in j.u.r.RandomGeneratorFactory
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util
  • Priority: P4
  • Status: Closed
  • Resolution: Withdrawn
  • Fix Versions: 23
  • Submitted: 2024-05-13
  • Updated: 2024-05-31
  • Resolved: 2024-05-17
Related Reports
CSR :  
Description
Summary
-------

The methods `create(long)` and `create(byte[])` on `java.util.random.RandomGeneratorFactory` will now throw `java.lang.UnsupportedOperationException` if the underlying `java.util.RandomGenerator`, for the algorithm, does not support instantiation using a `long` seed or a `byte[]` seed respectively.


Problem
-------

`RandomGeneratorFactory` provides APIs to locate all or specific random number generators available in the Java runtime. Once located, the `RandomGeneratorFactory` provides the following 3 methods to construct instances of `java.util.random.RandomGenerator` for the corresponding algorithm:

    public T create();
    public T create(long seed);
    public T create(byte[ ] seed);


`create()` can be used to construct an instance of `RandomGenerator` without a seed value. The `create(long)` and `create(byte[])` methods allow applications to provide a seed value when constructing the `RandomGenerator`.

In their current form, the `create(long)` and `create(byte[])` methods are specified to construct a `RandomGenerator` instance with the specified seed and if the `RandomGenerator` for that algorithm doesn't support a seed of that type, then these 2 create(...) methods will fallback to constructing the `RandomGenerator` instance without any seed value. This is problematic because the returned `RandomGenerator` instance from these 2 create(...) methods can end up being an unseeded `RandomGenerator`, when the application actually wanted the instances to be seeded with a specific seed. Morever, the calling application will not have any indication whether or not a seed value was successfully used to construct the `RandomGenerator` instance returned from these 2 create(...) methods.


Solution
--------

The specification of `create(long)` and `create(byte[])` will be changed to specify that if the `RandomGenerator` corresponding to a random generator algorithm doesn't support constructing the `RandomGenerator` instance with the provided seed type, then these 2 methods will throw an `UnsupportedOperationException`. These 2 methods will no longer fallback to constructing unseeded instances of `RandomGenerator`.

Moreover, a line for the algorithm `SecureRandom`, which is missing from the table in the `java.util.random` package documentation, has been added there.



Specification
-------------


src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java

         /**
    -     * Create an instance of {@link RandomGenerator} based on
    +     * Create an instance of {@link RandomGenerator} based on the
          * <a href="package-summary.html#algorithms">algorithm</a> chosen.
          *
    -     * @return new in instance of {@link RandomGenerator}.
    -     *
    +     * @return new instance of {@link RandomGenerator}.
          */
         public T create() {

         /**
    -     * Create an instance of {@link RandomGenerator} based on
    -     * <a href="package-summary.html#algorithms">algorithm</a> 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
    +     * <a href="package-summary.html#algorithms">algorithm</a> 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) {

         /**
    -     * Create an instance of {@link RandomGenerator} based on
    -     * <a href="package-summary.html#algorithms">algorithm</a> chosen
    -     * providing a starting byte[] seed. If byte[] seed is not supported by an
    -     * <a href="package-summary.html#algorithms">algorithm</a> then the no
    -     * argument form of create is used.
    +     * Create an instance of {@link RandomGenerator} based on the
    +     * <a href="package-summary.html#algorithms">algorithm</a> 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) {


src/java.base/share/classes/java/util/random/package-info.java

      *      <td style="text-align:right">1</td>
      *  </tr>
      *  <tr>
    + *      <th scope="row" style="text-align:left">SecureRandom</th>
    + *      <td style="text-align:left">Legacy</td>
    + *      <td style="text-align:left">BigInteger.ZERO</td>
    + *      <td style="text-align:right">Integer.MAX_VALUE</td>
    + *      <td style="text-align:right">Integer.MAX_VALUE</td>
    + *  </tr>
    + *  <tr>
      *      <th scope="row" style="text-align:left">ThreadLocalRandom <sup>*</sup></th>
      *      <td style="text-align:left">Legacy</td>
      *      <td style="text-align:left">BigInteger.ONE.shiftLeft(64)</td>