On 09/16/2013 02:11 PM, Guy Steele wrote:
Okay, as long as we're obsessing: the code defends against the hardware address being longer than 8 bytes.
This was to protect ourselves from the impact of this code being used in some alternative universe in which hardware addresses are not always 48bits. But you are right that we could do a little better.
So how about this code? ... h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
On first glance the sign extension of byte to long conversion makes this suspicious, but I see that it cannot hurt. So, sure; thanks. Here's the full current version, including another minor tweak. (Paul: I'm committing to our CVS.) 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(); 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())); }