RFR 8024253: ThreadLocal random can use SecureRandom for the initial seed

Peter Levart peter.levart at gmail.com
Mon Sep 16 12:46:51 UTC 2013


On 09/16/2013 01:32 PM, Doug Lea wrote:
> On 09/16/2013 05:35 AM, Alan Bateman wrote:
>> On 15/09/2013 17:32, Paul Sandoz wrote:
>>> Hi,
>>>
>>> http://cr.openjdk.java.net/~psandoz/tl/JDK-8024253-tlr-seed/webrev/
>>>
>>> Now that the hash seed functionality, which utilized 
>>> ThreadLocalRandom, has
>>> been removed from Hashtable and WeakHashMap we can update TLR to use 
>>> the same
>>> seed initialization functionality as SplittableRandom, which 
>>> includes using
>>> SecureRandom if the system property "java.util.secureRandomSeed" is 
>>> set to true.
>>>
>
> Thanks. This just re-instates a change we had to hold off on
> in last TLR updates because of the hash seed dependency.
>
>> Looks okay to me although it might be better to catch UHE rather than 
>> Exception.
>
> The intent is to ignore any problem in getting hashed host name
> short of a VM error. On the other hand, it is not nice to consume
> any unexpected mysterious RunTimeException. A coin flip...
>
> -Doug

Hi,

The InetAddress.getLocalHost() might throw SecurityException in some 
configurations (SecurityManager.checkConnect(localHostName, -1)). So 
perhaps, the call should be wrapped by 
AccessController.doPrivileged(...). But that's not so important. What 
worries me is that InetAddress.getLocalHost() involves name service 
look-up. It depends on configuration, but on my computer, it takes about 
5s to evaluate the hostname -> IP mapping the first time the program is 
run. The OS seems to cache this for a minute or so, because when I 
re-run the test program, it only takes 10ms. After a minute, the OS 
cache seems to expire and it again takes 5s to evaluate.

It may be that I have a strange unusual configuration (the name -> IP 
mapping is performed by DNS service even for local host name), but I 
have no other obvious problems using my machine.

I tried the following alternative:

     private static long interfacesHash() {
         long hash = 0L;
         try {
             Enumeration<NetworkInterface> ifcs = 
NetworkInterface.getNetworkInterfaces();
             while (ifcs.hasMoreElements()) {
                 hash ^= interfaceHash(ifcs.nextElement());
             }
         } catch (Exception e) {
             // ignore
         }
         return hash;
     }

     private static long interfaceHash(NetworkInterface ni) {
         long hash = 0L;
         Enumeration<InetAddress> ipAddresses = ni.getInetAddresses();
         while (ipAddresses.hasMoreElements()) {
             hash ^= mix64(ipAddresses.nextElement().hashCode());
         }
         Enumeration<NetworkInterface> subNis = ni.getSubInterfaces();
         while (subNis.hasMoreElements()) {
             hash ^= interfaceHash(subNis.nextElement());
         }
         return hash;
     }


This iterates all interfaces (with sub-interfaces) on the machine and 
XORs together the mix64-ed hashes of their IP addresses. It does't do 
any name service look-up and on my machine (with one ethernet and a 
loopback interface) it runs about 6-10x faster than 
InetAddress.getLocalHost() (that's when InetAddress.getLocalHost() runs 
fast - the OS caches the mapping):

InetAddress.getLocalHost() ~ 7-10 ms
interfacesHash() ~ 0.5-1.2ms

Note that in order to gain as much seed as possible from 
interfacesHash(), it should also be wrapped by 
AccessController.doPrivileged(...)

NetworkInterface also has one method called getHardwareAddress(). This 
might me interesting too...


Regards, Peter




More information about the core-libs-dev mailing list