<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body style="background-color: rgb(255, 255, 255); color: rgb(0, 0,
    0);" bgcolor="#FFFFFF" text="#000000">
    To sum-up: We have a problem with TLR initialization since by
    default it uses networking code to compute initial "seeder" value
    which can execute user code in at least two situations:<br>
    <br>
    - when "sun.net.spi.nameservice.provider" system property is defined
    to use custom NameService provider<br>
    - when custom SecurityManager is in effect while TLR is being
    initialized<br>
    - also, when "java.util.secureRandomSeed" is defined, at least on
    Windows this means that default SecureRandom algorithm will be using
    networking code too to gather system entropy<br>
    <br>
    We could work-around these problems by delaying initialization of
    NameService provider(s), by-passing SecurityManager when obtaining
    MAC address from NetworkInterface and extending the semantics of
    "java.util.secureRandomSeed" property to specify explicit
    SecureRandom algorithm and provider to use when obtaining
    SecureRandom instance, like in the following patch:<br>
    <br>
       
    <a class="moz-txt-link-freetext" href="http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR.initialSeed/webrev.01/">http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR.initialSeed/webrev.01/</a><br>
    <br>
    But on the other hand this seems too many knobs to worry about.
    Ideally one would like to always use OS provided native seed source,
    but SecureRandom (with all the security providers infrastructure)
    seems too heavy-weight to be used in classes like ThreadLocalRandom
    or SplittableRandom by default since they can be initialized very
    early in the start-up sequence. I made an experiment with
    class-loading. Recent JDK9 build loads 381 classes when running the
    following empty program on Linux:<br>
    <br>
    public class test0 {<br>
            public static void main(String[] args) {<br>
            }<br>
    }<br>
    <br>
    ...ThreadLocalRandom is not among them. But in special
    configurations (like when using java agents) or in the future, it
    could be. The following program:<br>
    <br>
    public class test {<br>
            public static void main(String[] args) {<br>
                    java.util.concurrent.ThreadLocalRandom.current();<br>
            }<br>
    }<br>
    <br>
    ...loads 403 classes. That's 22 more than an empty program. The
    following classes are loaded in addition:<br>
    <br>
    + java.util.Random<br>
    + java.util.concurrent.ThreadLocalRandom<br>
    + java.net.NetworkInterface<br>
    + java.net.NetworkInterface$1<br>
    + java.net.InterfaceAddress<br>
    + java.net.InetAddress<br>
    + sun.security.action.GetBooleanAction<br>
    + java.net.InetAddress$1<br>
    + java.net.InetAddress$InetAddressHolder<br>
    + java.net.InetAddress$Cache<br>
    + java.net.InetAddress$Cache$Type<br>
    + java.net.InetAddressImplFactory<br>
    + java.net.InetAddressImpl<br>
    + java.net.Inet6AddressImpl<br>
    + sun.net.spi.nameservice.NameService<br>
    + java.net.InetAddress$2<br>
    + java.net.Inet4Address<br>
    + java.net.Inet6Address<br>
    + java.net.Inet6Address$Inet6AddressHolder<br>
    + java.net.DefaultInterface<br>
    + java.net.NetworkInterface$2<br>
    + sun.nio.ch.Interruptible<br>
    <br>
    If I run the same program but set the
    "java.util.secureRandomSeed=true", it loads 435 classes. Besides 381
    classes loaded by an empty program, the following 54 classes are
    loaded in addition:<br>
    <br>
    + java.util.Random<br>
    + java.util.concurrent.ThreadLocalRandom<br>
    + java.security.SecureRandom<br>
    + sun.security.jca.Providers<br>
    + java.lang.InheritableThreadLocal<br>
    + sun.security.jca.ProviderList<br>
    + sun.security.jca.ProviderConfig<br>
    + java.security.Provider<br>
    + sun.security.jca.ProviderList$3<br>
    + sun.security.jca.ProviderList$1<br>
    + java.security.Provider$ServiceKey<br>
    + java.security.Provider$EngineDescription<br>
    + sun.misc.FloatingDecimal<br>
    + sun.misc.FloatingDecimal$BinaryToASCIIConverter<br>
    + sun.misc.FloatingDecimal$ExceptionalBinaryToASCIIBuffer<br>
    + sun.misc.FloatingDecimal$BinaryToASCIIBuffer<br>
    + sun.misc.FloatingDecimal$1<br>
    + sun.misc.FloatingDecimal$ASCIIToBinaryConverter<br>
    + sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer<br>
    + sun.misc.FDBigInteger<br>
    + sun.security.jca.ProviderList$2<br>
    + java.security.Security<br>
    + java.security.Security$1<br>
    + java.util.Properties$LineReader<br>
    + java.util.AbstractList$Itr<br>
    + sun.security.jca.ProviderConfig$2<br>
    + sun.security.provider.Sun<br>
    + sun.security.provider.SunEntries<br>
    + sun.security.provider.SunEntries$1<br>
    + java.security.SecureRandomSpi<br>
    + sun.security.provider.NativePRNG<br>
    + sun.security.provider.NativePRNG$Variant<br>
    + sun.security.provider.NativePRNG$1<br>
    + sun.security.provider.NativePRNG$2<br>
    + java.net.URI<br>
    + java.net.URI$Parser<br>
    + sun.security.provider.NativePRNG$RandomIO<br>
    + sun.security.provider.NativePRNG$Blocking<br>
    + sun.security.provider.NativePRNG$NonBlocking<br>
    + java.util.LinkedHashMap$LinkedEntrySet<br>
    + java.util.LinkedHashMap$LinkedHashIterator<br>
    + java.util.LinkedHashMap$LinkedEntryIterator<br>
    + java.security.Provider$Service<br>
    + java.security.Provider$UString<br>
    + java.util.LinkedHashSet<br>
    + java.util.LinkedHashMap$LinkedValues<br>
    + java.util.LinkedHashMap$LinkedValueIterator<br>
    + java.util.Collections$UnmodifiableSet<br>
    + java.util.Collections$UnmodifiableCollection$1<br>
    + java.util.LinkedHashMap$LinkedKeySet<br>
    + java.util.LinkedHashMap$LinkedKeyIterator<br>
    + sun.security.jca.GetInstance<br>
    + sun.security.jca.GetInstance$Instance<br>
    + sun.nio.ch.Interruptible<br>
    <br>
    <br>
    This seems too heavy-weight even if the initialization issue on
    Windows where default SecureRandom algorithm is using networking
    code to gather system entropy is worked-around by requesting
    explicit "Windows-PRNG" SecureRandom algorithm from "SunMSCAPI"
    provider.<br>
    <br>
    Peeking around in the sun.security.provider package, I found there
    already is a minimal internal infrastructure for obtaining random
    seed. It's encapsulated in package-private abstract class
    sun.security.provider.SeedGenerator with 4 implementations. It turns
    out that, besides Java-only fall-back implementation called
    ThreadedSeedGenerator and generic URLSeedGenerator, there are also
    two implementations of NativeSeedGenerator (one for UNIX-es which is
    just an extension of URLSeedGenerator and the other for Windows
    which uses MS CryptoAPI). I made a few tweaks that allow this
    sub-infrastructure to be used directly in ThreadLocalRandom and
    SplittableRandom:<br>
    <br>
       
<a class="moz-txt-link-freetext" href="http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR_SR_SeedGenerator/webrev.01/">http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR_SR_SeedGenerator/webrev.01/</a><br>
    <br>
    The changes are as follows:<br>
    - modified SeedGenerator to be a public class (was package-private
    as are still all it's subclasses)<br>
    - made its only public static method package-private (was public for
    no reason)<br>
    - made its only abstract method public (was package-private)<br>
    - made SeedGenerator implement AutoCloseable with empty close()
    method (overriden in URLSeedGenerator to close the underlying
    stream)<br>
    - added public static factory method to return a new instance of
    NativeSeedGenerator (using /dev/urandom on UNIX-es, MSCAPI on
    Windows) and protected it with a runtime check so that it can only
    be used internally<br>
    <br>
    With these changes and modified TLR, running the test program (see
    above) loads only the following 15 additional classes besides those
    that are loaded by an empty program on Linux (and I assume the
    number is the same on Windows):<br>
    <br>
    <br>
    + java.util.Random<br>
    + java.util.concurrent.ThreadLocalRandom<br>
    + sun.security.provider.SeedGenerator<br>
    + sun.security.provider.SunEntries<br>
    + sun.security.provider.SunEntries$1<br>
    + java.security.Security<br>
    + java.security.Security$1<br>
    + java.util.Properties$LineReader<br>
    + sun.security.provider.SeedGenerator$URLSeedGenerator<br>
    + sun.security.provider.NativeSeedGenerator<br>
    + sun.security.provider.SeedGenerator$1<br>
    + sun.security.provider.SeedGenerator$URLSeedGenerator$1<br>
    + java.net.URI<br>
    + java.net.URI$Parser<br>
    + sun.nio.ch.Interruptible<br>
    <br>
    <br>
    So what do you think is the best direction to go further with this?
    Patching networking or exposing NativeSeedGenerator to internal JDK
    code?<br>
    <br>
    <br>
    Regards, Peter<br>
    <br>
  </body>
</html>