changeset 5448:a73386183d31

7180240: Disable alternative string hashing by default Summary: Disables by default the alternative hashing approach used by Hashtable, HashMap, WeakHashMap, ConcurrentHashMap for String keys introduced in 7122677 Reviewed-by: smarks
author mduigou
date Thu, 28 Jun 2012 11:41:26 -0700
parents 83f8283e4791
children aa0ad405f70b 9ca4ae899116
files src/share/classes/java/util/HashMap.java src/share/classes/java/util/Hashtable.java src/share/classes/java/util/WeakHashMap.java src/share/classes/java/util/concurrent/ConcurrentHashMap.java
diffstat 4 files changed, 78 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/HashMap.java	Wed Jun 27 21:10:26 2012 +0100
+++ b/src/share/classes/java/util/HashMap.java	Thu Jun 28 11:41:26 2012 -0700
@@ -176,17 +176,16 @@
     transient int modCount;
 
     /**
-     * The default threshold of capacity above which alternate hashing is used.
-     * Alternative hashing reduces the incidence of collisions due to weak hash
-     * code calculation.
+     * The default threshold of map capacity above which alternative hashing is
+     * used for String keys. Alternative hashing reduces the incidence of
+     * collisions due to weak hash code calculation for String keys.
      * <p/>
      * This value may be overridden by defining the system property
-     * {@code java.util.althashing.threshold}. A property value of {@code 1}
+     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
      * forces alternative hashing to be used at all times whereas
-     * {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures that
-     * alternative hashing is never used.
+     * {@code -1} value ensures that alternative hashing is never used.
      */
-    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 512;
+    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
 
     /**
      * holds values which can't be initialized until after VM is booted.
@@ -195,20 +194,19 @@
 
             // Unsafe mechanics
         /**
-         *
+         * Unsafe utilities
          */
         static final sun.misc.Unsafe UNSAFE;
 
         /**
-         * Offset of "final" hashmask field we must set in
-         * readObject() method.
+         * Offset of "final" hashSeed field we must set in readObject() method.
          */
         static final long HASHSEED_OFFSET;
 
         /**
-         * Table capacity above which to switch to use alternate hashing.
+         * Table capacity above which to switch to use alternative hashing.
          */
-        static final int ALTERNATE_HASHING_THRESHOLD;
+        static final int ALTERNATIVE_HASHING_THRESHOLD;
 
         static {
             String altThreshold = java.security.AccessController.doPrivileged(
@@ -219,20 +217,20 @@
             try {
                 threshold = (null != altThreshold)
                         ? Integer.parseInt(altThreshold)
-                        : ALTERNATE_HASHING_THRESHOLD_DEFAULT;
+                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
 
                 // disable alternative hashing if -1
-                if(threshold == -1) {
+                if (threshold == -1) {
                     threshold = Integer.MAX_VALUE;
                 }
 
-                if(threshold < 0) {
+                if (threshold < 0) {
                     throw new IllegalArgumentException("value must be positive integer.");
                 }
             } catch(IllegalArgumentException failed) {
                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
             }
-            ALTERNATE_HASHING_THRESHOLD = threshold;
+            ALTERNATIVE_HASHING_THRESHOLD = threshold;
 
             try {
                 UNSAFE = sun.misc.Unsafe.getUnsafe();
@@ -245,8 +243,8 @@
     }
 
     /**
-     * If {@code true} then perform alternate hashing to reduce the incidence of
-     * collisions due to weak hash code calculation.
+     * If {@code true} then perform alternative hashing of String keys to reduce
+     * the incidence of collisions due to weak hash code calculation.
      */
     transient boolean useAltHashing;
 
@@ -284,7 +282,7 @@
         threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
         table = new Entry[capacity];
         useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
         init();
     }
 
@@ -561,7 +559,7 @@
         Entry[] newTable = new Entry[newCapacity];
         boolean oldAltHashing = useAltHashing;
         useAltHashing |= sun.misc.VM.isBooted() &&
-                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
         boolean rehash = oldAltHashing ^ useAltHashing;
         transfer(newTable, rehash);
         table = newTable;
@@ -576,7 +574,7 @@
         for (Entry<K,V> e : table) {
             while(null != e) {
                 Entry<K,V> next = e.next;
-                if(rehash) {
+                if (rehash) {
                     e.hash = null == e.key ? 0 : hash(e.key);
                 }
                 int i = indexFor(e.hash, newCapacity);
@@ -1147,7 +1145,7 @@
         table = new Entry[capacity];
         threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
         useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
 
         init();  // Give subclass a chance to do its thing.
 
--- a/src/share/classes/java/util/Hashtable.java	Wed Jun 27 21:10:26 2012 +0100
+++ b/src/share/classes/java/util/Hashtable.java	Thu Jun 28 11:41:26 2012 -0700
@@ -164,17 +164,16 @@
     private static final long serialVersionUID = 1421746759512286392L;
 
     /**
-     * The default threshold of capacity above which alternate hashing is used.
-     * Alternative hashing reduces the incidence of collisions due to weak hash
-     * code calculation.
+     * The default threshold of map capacity above which alternative hashing is
+     * used for String keys. Alternative hashing reduces the incidence of
+     * collisions due to weak hash code calculation for String keys.
      * <p/>
      * This value may be overridden by defining the system property
-     * {@code java.util.althashing.threshold}. A property value of {@code 1}
+     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
      * forces alternative hashing to be used at all times whereas
-     * {@code -1 } value ensures that
-     * alternative hashing is never used.
+     * {@code -1} value ensures that alternative hashing is never used.
      */
-    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 512;
+    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = 512;
 
     /**
      * holds values which can't be initialized until after VM is booted.
@@ -182,9 +181,9 @@
     private static class Holder {
 
         /**
-         * Table capacity above which to switch to use alternate hashing.
+         * Table capacity above which to switch to use alternative hashing.
          */
-        static final int ALTERNATE_HASHING_THRESHOLD;
+        static final int ALTERNATIVE_HASHING_THRESHOLD;
 
         static {
             String altThreshold = java.security.AccessController.doPrivileged(
@@ -195,32 +194,39 @@
             try {
                 threshold = (null != altThreshold)
                         ? Integer.parseInt(altThreshold)
-                        : ALTERNATE_HASHING_THRESHOLD_DEFAULT;
+                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
 
                 // disable alternative hashing if -1
-                if(threshold == -1) {
+                if (threshold == -1) {
                     threshold = Integer.MAX_VALUE;
                 }
 
-                if(threshold < 0) {
+                if (threshold < 0) {
                     throw new IllegalArgumentException("value must be positive integer.");
                 }
             } catch(IllegalArgumentException failed) {
                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
             }
 
-            ALTERNATE_HASHING_THRESHOLD = threshold;
+            ALTERNATIVE_HASHING_THRESHOLD = threshold;
         }
     }
 
     /**
-     * If {@code true} then perform alternate hashing to reduce the incidence of
-     * collisions due to weak hash code calculation.
+     * If {@code true} then perform alternative hashing of String keys to reduce
+     * the incidence of collisions due to weak hash code calculation.
      */
     transient boolean useAltHashing;
 
     // Unsafe mechanics
+    /**
+    * Unsafe utilities
+    */
     private static final sun.misc.Unsafe UNSAFE;
+
+    /**
+    * Offset of "final" hashSeed field we must set in readObject() method.
+    */
     private static final long HASHSEED_OFFSET;
 
      static {
@@ -279,7 +285,7 @@
         table = new Entry[initialCapacity];
         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
         useAltHashing = sun.misc.VM.isBooted() &&
-                (initialCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (initialCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
     }
 
     /**
@@ -493,7 +499,7 @@
         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
         boolean currentAltHashing = useAltHashing;
         useAltHashing = sun.misc.VM.isBooted() &&
-                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
         boolean rehash = currentAltHashing ^ useAltHashing;
 
         table = newMap;
@@ -503,7 +509,7 @@
                 Entry<K,V> e = old;
                 old = old.next;
 
-                if(rehash) {
+                if (rehash) {
                     e.hash = hash(e.key);
                 }
                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
@@ -1015,7 +1021,7 @@
         threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
         count = 0;
         useAltHashing = sun.misc.VM.isBooted() &&
-                (length >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (length >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
 
         // Read the number of elements and then all the key/value objects
         for (; elements > 0; elements--) {
--- a/src/share/classes/java/util/WeakHashMap.java	Wed Jun 27 21:10:26 2012 +0100
+++ b/src/share/classes/java/util/WeakHashMap.java	Thu Jun 28 11:41:26 2012 -0700
@@ -185,17 +185,16 @@
     int modCount;
 
     /**
-    * The default threshold of capacity above which alternate hashing is
-    * used. Alternative hashing reduces the incidence of collisions due to
-    * weak hash code calculation.
-    * <p/>
-    * This value may be overridden by defining the system property
-    * {@code java.util.althashing.threshold} to an integer value. A property
-    * value of {@code 1} forces alternative hashing to be used at all times
-    * whereas {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures
-    * that alternative hashing is never used.
-    */
-    static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 512;
+     * The default threshold of map capacity above which alternative hashing is
+     * used for String keys. Alternative hashing reduces the incidence of
+     * collisions due to weak hash code calculation for String keys.
+     * <p/>
+     * This value may be overridden by defining the system property
+     * {@code jdk.map.althashing.threshold}. A property value of {@code 1}
+     * forces alternative hashing to be used at all times whereas
+     * {@code -1} value ensures that alternative hashing is never used.
+     */
+    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
 
     /**
      * holds values which can't be initialized until after VM is booted.
@@ -203,9 +202,9 @@
     private static class Holder {
 
         /**
-         * Table capacity above which to switch to use alternate hashing.
+         * Table capacity above which to switch to use alternative hashing.
          */
-        static final int ALTERNATE_HASHING_THRESHOLD;
+        static final int ALTERNATIVE_HASHING_THRESHOLD;
 
         static {
             String altThreshold = java.security.AccessController.doPrivileged(
@@ -216,20 +215,20 @@
             try {
                 threshold = (null != altThreshold)
                         ? Integer.parseInt(altThreshold)
-                        : ALTERNATE_HASHING_THRESHOLD_DEFAULT;
+                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
 
                 // disable alternative hashing if -1
-                if(threshold == -1) {
+                if (threshold == -1) {
                     threshold = Integer.MAX_VALUE;
                 }
 
-                if(threshold < 0) {
+                if (threshold < 0) {
                     throw new IllegalArgumentException("value must be positive integer.");
                 }
             } catch(IllegalArgumentException failed) {
                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
             }
-            ALTERNATE_HASHING_THRESHOLD = threshold;
+            ALTERNATIVE_HASHING_THRESHOLD = threshold;
         }
     }
 
@@ -276,7 +275,7 @@
         this.loadFactor = loadFactor;
         threshold = (int)(capacity * loadFactor);
         useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
     }
 
     /**
@@ -560,7 +559,7 @@
         Entry<K,V>[] newTable = newTable(newCapacity);
         boolean oldAltHashing = useAltHashing;
         useAltHashing |= sun.misc.VM.isBooted() &&
-                (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
+                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
         boolean rehash = oldAltHashing ^ useAltHashing;
         transfer(oldTable, newTable, rehash);
         table = newTable;
@@ -592,7 +591,7 @@
                     e.value = null; //  "   "
                     size--;
                 } else {
-                    if(rehash) {
+                    if (rehash) {
                         e.hash = hash(key);
                     }
                     int i = indexFor(e.hash, dest.length);
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jun 27 21:10:26 2012 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Jun 28 11:41:26 2012 -0700
@@ -183,11 +183,18 @@
     private static class Holder {
 
         /**
-        * Enable alternate hashing?
+        * Enable alternative hashing of String keys?
+        *
+        * <p>Unlike the other hash map implementations we do not implement a
+        * threshold for regulating whether alternative hashing is used for
+        * String keys. Alternative hashing is either enabled for all instances
+        * or disabled for all instances.
         */
-        static final boolean ALTERNATE_HASHING;
+        static final boolean ALTERNATIVE_HASHING;
 
         static {
+            // Use the "threshold" system property even though our threshold
+            // behaviour is "ON" or "OFF".
             String altThreshold = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetPropertyAction(
                     "jdk.map.althashing.threshold"));
@@ -196,20 +203,20 @@
             try {
                 threshold = (null != altThreshold)
                         ? Integer.parseInt(altThreshold)
-                        : 1;
+                        : Integer.MAX_VALUE;
 
                 // disable alternative hashing if -1
-                if(threshold == -1) {
+                if (threshold == -1) {
                     threshold = Integer.MAX_VALUE;
                 }
 
-                if(threshold < 0) {
+                if (threshold < 0) {
                     throw new IllegalArgumentException("value must be positive integer.");
                 }
             } catch(IllegalArgumentException failed) {
                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
             }
-            ALTERNATE_HASHING = threshold <= MAXIMUM_CAPACITY;
+            ALTERNATIVE_HASHING = threshold <= MAXIMUM_CAPACITY;
         }
     }
 
@@ -220,7 +227,7 @@
     private transient final int hashSeed = randomHashSeed(this);
 
     private static int randomHashSeed(ConcurrentHashMap instance) {
-        if (sun.misc.VM.isBooted() && Holder.ALTERNATE_HASHING) {
+        if (sun.misc.VM.isBooted() && Holder.ALTERNATIVE_HASHING) {
             return sun.misc.Hashing.randomHashSeed(instance);
         }