src/share/classes/java/util/WeakHashMap.java
Print this page
@@ -185,15 +185,41 @@
*
* @see ConcurrentModificationException
*/
int modCount;
+ private static class Holder {
+ static final boolean USE_HASHSEED;
+
+ static {
+ String hashSeedProp = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction(
+ "jdk.map.useRandomSeed"));
+ boolean localBool = (null != hashSeedProp)
+ ? Boolean.parseBoolean(hashSeedProp) : false;
+ USE_HASHSEED = localBool;
+ }
+ }
+
/**
* A randomizing value associated with this instance that is applied to
* hash code of keys to make hash collisions harder to find.
+ *
+ * Non-final so it can be set lazily, but be sure not to set more than once.
*/
- transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
+ transient int hashSeed;
+
+ /**
+ * Initialize the hashing mask value.
+ */
+ final void initHashSeed() {
+ if (sun.misc.VM.isBooted() && Holder.USE_HASHSEED) {
+ // Do not set hashSeed more than once!
+ // assert hashSeed == 0;
+ hashSeed = sun.misc.Hashing.randomHashSeed(this);
+ }
+ }
@SuppressWarnings("unchecked")
private Entry<K,V>[] newTable(int n) {
return (Entry<K,V>[]) new Entry<?,?>[n];
}
@@ -221,10 +247,11 @@
while (capacity < initialCapacity)
capacity <<= 1;
table = newTable(capacity);
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
+ initHashSeed();
}
/**
* Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
* capacity and the default load factor (0.75).
@@ -296,13 +323,10 @@
* critical because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits.
*/
final int hash(Object k) {
- if (k instanceof String) {
- return ((String) k).hash32();
- }
int h = hashSeed ^ k.hashCode();
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).