--- old/src/share/classes/java/util/SplittableRandom.java 2014-06-25 16:42:33.350291736 +0200 +++ new/src/share/classes/java/util/SplittableRandom.java 2014-06-25 16:42:33.256293358 +0200 @@ -25,7 +25,7 @@ package java.util; -import java.net.NetworkInterface; +import sun.security.provider.SeedGenerator; import java.util.concurrent.atomic.AtomicLong; import java.util.function.IntConsumer; import java.util.function.LongConsumer; @@ -227,45 +227,15 @@ private static final AtomicLong defaultGen = new AtomicLong(initialSeed()); private static long initialSeed() { - String pp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "java.util.secureRandomSeed")); - if (pp != null && pp.equalsIgnoreCase("true")) { - byte[] seedBytes = java.security.SecureRandom.getSeed(8); + try (SeedGenerator sg = SeedGenerator.getNativeInstance()) { + byte[] seedBytes = new byte[8]; + sg.getSeedBytes(seedBytes); long s = (long)(seedBytes[0]) & 0xffL; for (int i = 1; i < 8; ++i) s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); - return s; + return s ^ mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime()); } - long h = 0L; - try { - Enumeration ifcs = - NetworkInterface.getNetworkInterfaces(); - boolean retry = false; // retry once if getHardwareAddress is null - while (ifcs.hasMoreElements()) { - NetworkInterface ifc = ifcs.nextElement(); - if (!ifc.isVirtual()) { // skip fake addresses - byte[] bs = ifc.getHardwareAddress(); - if (bs != null) { - int n = bs.length; - int m = Math.min(n >>> 1, 4); - for (int i = 0; i < m; ++i) - h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i]; - if (m < 4) - h = (h << 8) ^ bs[n-1-m]; - h = mix64(h); - break; - } - else if (!retry) - retry = true; - else - break; - } - } - } catch (Exception ignore) { - } - return (h ^ mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); } // IllegalArgumentException messages --- old/src/share/classes/java/util/concurrent/ThreadLocalRandom.java 2014-06-25 16:42:33.588287630 +0200 +++ new/src/share/classes/java/util/concurrent/ThreadLocalRandom.java 2014-06-25 16:42:33.503289096 +0200 @@ -36,8 +36,7 @@ package java.util.concurrent; import java.io.ObjectStreamField; -import java.net.NetworkInterface; -import java.util.Enumeration; +import sun.security.provider.SeedGenerator; import java.util.Random; import java.util.Spliterator; import java.util.concurrent.atomic.AtomicInteger; @@ -137,45 +136,15 @@ private static final AtomicLong seeder = new AtomicLong(initialSeed()); private static long initialSeed() { - String pp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "java.util.secureRandomSeed")); - if (pp != null && pp.equalsIgnoreCase("true")) { - byte[] seedBytes = java.security.SecureRandom.getSeed(8); + try (SeedGenerator sg = SeedGenerator.getNativeInstance()) { + byte[] seedBytes = new byte[8]; + sg.getSeedBytes(seedBytes); long s = (long)(seedBytes[0]) & 0xffL; for (int i = 1; i < 8; ++i) s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); - return s; + return s ^ mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime()); } - long h = 0L; - try { - Enumeration ifcs = - NetworkInterface.getNetworkInterfaces(); - boolean retry = false; // retry once if getHardwareAddress is null - while (ifcs.hasMoreElements()) { - NetworkInterface ifc = ifcs.nextElement(); - if (!ifc.isVirtual()) { // skip fake addresses - byte[] bs = ifc.getHardwareAddress(); - if (bs != null) { - int n = bs.length; - int m = Math.min(n >>> 1, 4); - for (int i = 0; i < m; ++i) - h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i]; - if (m < 4) - h = (h << 8) ^ bs[n-1-m]; - h = mix64(h); - break; - } - else if (!retry) - retry = true; - else - break; - } - } - } catch (Exception ignore) { - } - return (h ^ mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); } /** --- old/src/share/classes/sun/security/provider/SeedGenerator.java 2014-06-25 16:42:33.830283454 +0200 +++ new/src/share/classes/sun/security/provider/SeedGenerator.java 2014-06-25 16:42:33.740285007 +0200 @@ -75,9 +75,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Random; + +import sun.misc.VM; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; import sun.security.util.Debug; -abstract class SeedGenerator { +public abstract class SeedGenerator implements AutoCloseable { // Static instance is created at link time private static SeedGenerator instance; @@ -102,7 +106,9 @@ if (egdSource.equals(SunEntries.URL_DEV_RANDOM) || egdSource.equals(SunEntries.URL_DEV_URANDOM)) { try { - instance = new NativeSeedGenerator(egdSource); + instance = new NativeSeedGenerator(egdSource) { + @Override public void close() {} // never close shared instance + }; if (debug != null) { debug.println( "Using operating system seed generator" + egdSource); @@ -115,7 +121,9 @@ } } else if (egdSource.length() != 0) { try { - instance = new URLSeedGenerator(egdSource); + instance = new URLSeedGenerator(egdSource) { + @Override public void close() {} // never close shared instance + }; if (debug != null) { debug.println("Using URL seed generator reading from " + egdSource); @@ -133,18 +141,46 @@ if (debug != null) { debug.println("Using default threaded seed generator"); } - instance = new ThreadedSeedGenerator(); + instance = new ThreadedSeedGenerator(); // close() is a no-op here + } + } + + @CallerSensitive + public static SeedGenerator getNativeInstance() { + Class caller = Reflection.getCallerClass(); + if (!VM.isSystemDomainLoader(caller.getClassLoader())) { + throw new SecurityException("Internal API"); + } + try { + return new NativeSeedGenerator(SunEntries.URL_DEV_URANDOM); + } catch (IOException e) { + // fall-back to default shared instance + return instance; } } + @CallerSensitive + public static SeedGenerator getDefaultInstance() { + Class caller = Reflection.getCallerClass(); + if (!VM.isSystemDomainLoader(caller.getClassLoader())) { + throw new SecurityException("Internal API"); + } + return instance; + } + /** * Fill result with bytes from the queue. Wait for it if it isn't ready. */ - static public void generateSeed(byte[] result) { + static void generateSeed(byte[] result) { instance.getSeedBytes(result); } - abstract void getSeedBytes(byte[] result); + public abstract void getSeedBytes(byte[] result); + + @Override + public void close() { + // nothing to close by default + } /** * Retrieve some system information, hashed. @@ -384,7 +420,7 @@ } @Override - void getSeedBytes(byte[] result) { + public void getSeedBytes(byte[] result) { for (int i = 0; i < result.length; i++) { result[i] = getSeedByte(); } @@ -527,7 +563,7 @@ } @Override - void getSeedBytes(byte[] result) { + public void getSeedBytes(byte[] result) { int len = result.length; int read = 0; try { @@ -546,5 +582,12 @@ " generated exception: " + ioe.getMessage(), ioe); } } + + @Override + public void close() { + try { + seedStream.close(); + } catch (IOException ignore) {} + } } } --- old/src/windows/classes/sun/security/provider/NativeSeedGenerator.java 2014-06-25 16:42:34.068279348 +0200 +++ new/src/windows/classes/sun/security/provider/NativeSeedGenerator.java 2014-06-25 16:42:33.973280987 +0200 @@ -55,7 +55,7 @@ private static native boolean nativeGenerateSeed(byte[] result); @Override - void getSeedBytes(byte[] result) { + public void getSeedBytes(byte[] result) { // fill array as a side effect if (nativeGenerateSeed(result) == false) { // should never happen if constructor check succeeds