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