On 09/16/2013 03:54 PM, Doug Lea wrote:
On 09/16/2013 08:46 AM, Peter Levart wrote:
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.
NetworkInterface also has one method called getHardwareAddress().
This might me
interesting too...
Using NetworkInterface.getHardwareAddress() is a good idea; thanks!
Using only one of them should suffice. And just giving up on
SecurityException seems fine.
Could you check that this performs reasonably on your
unusually-configured machine?
I checked and it performs fast. It doesn't involve name service look-up.
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);
long s = (long)(seedBytes[0]) & 0xffL;
for (int i = 1; i < 8; ++i)
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
return s;
}
long h = 0L;
try {
Enumeration<NetworkInterface> ifcs =
NetworkInterface.getNetworkInterfaces();
if (ifcs.hasMoreElements()) {
byte[] bs = ifcs.nextElement().getHardwareAddress();
if (bs != null) {
for (int i = 0; i < 8 && i < bs.length; ++i)
h = (h << 8) ^ bs[i];
}
}
} catch (Exception ignore) {
}
return (mix64(h ^ System.currentTimeMillis()) ^
mix64(System.nanoTime()));
But not every interface has hardware address (loopback interface for
example) and the order of returned interfaces is not defined. Also with
security manager installed (System.setSecurityManager(new
RMISecurityManager()) and no extra policy, the above code always
evaluates 'h' to 0. The following is more robust (I included only the
2nd part after SecureRandom and added some prints to see what gets
evaluated):
public static long initialSeed() {
long h = 0L;
try {
h = AccessController.doPrivileged(new
PrivilegedExceptionAction<Long>() {
@Override
public Long run() throws Exception {
long h = 0L;
Enumeration<NetworkInterface> ifcs =
NetworkInterface.getNetworkInterfaces();
while (ifcs.hasMoreElements()) {
NetworkInterface ifc = ifcs.nextElement();
System.out.println(ifc);
byte[] bs = ifc.getHardwareAddress();
System.out.println(Arrays.toString(bs));
if (bs != null) {
for (int i = 0; i < 8 && i < bs.length; ++i)
h = (h << 8) ^ bs[i];
break;
}
}
return h;
}
});
} catch (Exception ignore) {
}
return (
mix64(h ^ System.currentTimeMillis()) ^
mix64(System.nanoTime())
);
}
Regards, Peter