Merge "FileInputStreamTest : Add test for skips of files larger than 2G."
diff --git a/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java b/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
index e5c3bdb..29cdffa 100644
--- a/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
+++ b/luni/src/test/java/libcore/java/util/jar/OldManifestTest.java
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
 import junit.framework.TestCase;
@@ -176,9 +178,12 @@
 
         // The Manifest-Version takes precedence,
         // and the Signature-Version gets no special treatment.
-        String[] lines = new String(os.toByteArray(), "UTF-8").split("\r\n");
-        assertEquals("Manifest-Version: 1.0", lines[0]);
-        assertEquals("Aardvark-Version: 3.0", lines[1]);
-        assertEquals("Signature-Version: 2.0", lines[2]);
+        List<String> lines = Arrays.asList(new String(os.toByteArray(), "UTF-8").split("\r\n"));
+        // The first line must always contain the Manifest-Version (or the Signature-Version if
+        // the ManifestVersion is missing.
+        assertEquals("Manifest-Version: 1.0", lines.get(0));
+
+        assertTrue(lines.contains("Aardvark-Version: 3.0"));
+        assertTrue(lines.contains("Signature-Version: 2.0"));
     }
 }
diff --git a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
index 0657f18..b99a3f1 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
@@ -26,6 +26,7 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Set;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -39,17 +40,18 @@
 
 public class KeyManagerFactoryTest extends TestCase {
 
-    private static TestKeyStore TEST_KEY_STORE;
+    private TestKeyStore testKeyStore;
 
-    // note the rare usage of DSA keys here in addition to RSA
-    private static TestKeyStore getTestKeyStore() throws Exception {
-        if (TEST_KEY_STORE == null) {
-            TEST_KEY_STORE = new TestKeyStore.Builder()
-                    .keyAlgorithms("RSA", "DH_RSA", "DSA", "DH_DSA", "EC", "EC_RSA")
-                    .aliasPrefix("rsa-dsa-ec-dh")
-                    .build();
-        }
-        return TEST_KEY_STORE;
+    protected void setUp() throws Exception {
+        // note the rare usage of DSA keys here in addition to RSA
+        testKeyStore = new TestKeyStore.Builder()
+                .keyAlgorithms("RSA", "DH_RSA", "DSA", "DH_DSA", "EC", "EC_RSA")
+                .aliasPrefix("rsa-dsa-ec-dh")
+                .build();
+    }
+
+    private TestKeyStore getTestKeyStore() throws Exception {
+        return testKeyStore;
     }
 
     public void test_KeyManagerFactory_getDefaultAlgorithm() throws Exception {
@@ -230,34 +232,30 @@
         X509Certificate[] certificateChain = km.getCertificateChain(alias);
         PrivateKey privateKey = km.getPrivateKey(alias);
 
-        String keyAlgName;
-        String sigAlgName;
-        if (keyType == null) {
-            keyAlgName = privateKey.getAlgorithm();
-            sigAlgName = keyAlgName;
-        } else {
-            // potentially handle EC_EC or EC_RSA
-            keyAlgName = TestKeyStore.keyAlgorithm(keyType);
-            sigAlgName = TestKeyStore.signatureAlgorithm(keyType);
-            X509Certificate certificate = certificateChain[0];
-            assertEquals(keyType, keyAlgName, certificate.getPublicKey().getAlgorithm());
-            assertEquals(keyType, keyAlgName, privateKey.getAlgorithm());
-            // skip this for EC which could return EC_RSA case instead of EC_EC
-            if (!keyType.equals("EC")) {
-                String expectedSigAlgName = sigAlgName.toUpperCase();
-                String actualSigAlgName = certificate.getSigAlgName().toUpperCase();
-                String expected = actualSigAlgName + " contains " + expectedSigAlgName;
-                assertTrue(expected, actualSigAlgName.contains(expectedSigAlgName));
-            }
-        }
+        String keyAlgName =  privateKey.getAlgorithm();
+
+        X509Certificate certificate = certificateChain[0];
+        assertEquals(keyType, keyAlgName, certificate.getPublicKey().getAlgorithm());
+
+        String sigAlgName = certificate.getSigAlgName();
 
         PrivateKeyEntry privateKeyEntry = getTestKeyStore().getPrivateKey(keyAlgName, sigAlgName);
-        if (!"EC".equals(keyAlgName)) {
-            assertEquals(keyType,
-                         Arrays.<Certificate>asList(privateKeyEntry.getCertificateChain()),
-                         Arrays.<Certificate>asList(certificateChain));
-            assertEquals(keyType,
-                         privateKeyEntry.getPrivateKey(), privateKey);
+
+        assertEquals(keyType,
+                     Arrays.<Certificate>asList(privateKeyEntry.getCertificateChain()),
+                     Arrays.<Certificate>asList(certificateChain));
+        assertEquals(keyType,
+                     privateKeyEntry.getPrivateKey(), privateKey);
+
+        if (keyType != null) {
+            assertEquals(TestKeyStore.keyAlgorithm(keyType), keyAlgName);
+
+            // Skip this when we're given only "DH" or "EC" instead of "DH_DSA",
+            // "EC_RSA", etc. since we don't know what the expected
+            // algorithm was.
+            if (!keyType.equals("DH") && !keyType.equals("EC")) {
+                assertTrue(sigAlgName.contains(TestKeyStore.signatureAlgorithm(keyType)));
+            }
         }
     }
 
diff --git a/ojluni/src/main/java/java/lang/JavaLangAccess.java b/ojluni/src/main/java/java/lang/JavaLangAccess.java
index 20d673e..2779c60 100644
--- a/ojluni/src/main/java/java/lang/JavaLangAccess.java
+++ b/ojluni/src/main/java/java/lang/JavaLangAccess.java
@@ -35,13 +35,6 @@
   /**
    * @hide
    */
-  public static int getStringHash32(String string) {
-      return string.hash32();
-  }
-
-  /**
-   * @hide
-   */
   public static <E extends Enum<E>>
           E[] getEnumConstantsShared(Class<E> klass) {
       return klass.getEnumConstantsShared();
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 7213e2d..0e66ad7 100755
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -2879,74 +2879,4 @@
      *          guaranteed to be from a pool of unique strings.
      */
     public native String intern();
-
-    /**
-     * Seed value used for each alternative hash calculated.
-     */
-    private static int HASHING_SEED;
-
-    private static int getHashingSeed() {
-        long nanos = System.nanoTime();
-        long now = System.currentTimeMillis();
-        int SEED_MATERIAL[] = {
-                System.identityHashCode(String.class),
-                System.identityHashCode(System.class),
-                (int) (nanos >>> 32),
-                (int) nanos,
-                (int) (now >>> 32),
-                (int) now,
-                (int) (System.nanoTime() >>> 2)
-        };
-
-        // Use murmur3 to scramble the seeding material.
-        // Inline implementation to avoid loading classes
-        int h1 = 0;
-
-        // body
-        for (int k1 : SEED_MATERIAL) {
-            k1 *= 0xcc9e2d51;
-            k1 = (k1 << 15) | (k1 >>> 17);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = (h1 << 13) | (h1 >>> 19);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail (always empty, as body is always 32-bit chunks)
-
-        // finalization
-
-        h1 ^= SEED_MATERIAL.length * 4;
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        HASHING_SEED = h1;
-        return HASHING_SEED;
-    }
-
-    /**
-     * Cached value of the alternative hashing algorithm result
-     */
-    // TODO(narayan): This adds a 4 byte overhead to all string objects. Is it
-    // worth the trouble ? hash32() below has been changed not to cache the calculated
-    // hash. This is likely to be expensive and needs further analysis.
-    //
-    // private transient int hash32 = 0;
-
-    /**
-     * Calculates a 32-bit hash value for this string.
-     *
-     * @return a 32-bit hash value for this string.
-     */
-    int hash32() {
-        char[] value = new char[count];
-        getChars(0, count, value, 0);
-        return sun.misc.Hashing.murmur3_32(getHashingSeed(), value, 0, count);
-    }
 }
diff --git a/ojluni/src/main/java/java/util/HashMap.java b/ojluni/src/main/java/java/util/HashMap.java
index 6d76a33..9403225 100755
--- a/ojluni/src/main/java/java/util/HashMap.java
+++ b/ojluni/src/main/java/java/util/HashMap.java
@@ -134,7 +134,7 @@
     /**
      * The default initial capacity - MUST be a power of two.
      */
-    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
+    static final int DEFAULT_INITIAL_CAPACITY = 4;
 
     /**
      * The maximum capacity, used if a higher value is implicitly specified
@@ -176,7 +176,9 @@
      *
      * @serial
      */
-    final float loadFactor;
+    // Android-Note: We always use a load factor of 0.75 and ignore any explicitly
+    // selected values.
+    final float loadFactor = DEFAULT_LOAD_FACTOR;
 
     /**
      * The number of times this HashMap has been structurally modified
@@ -188,62 +190,6 @@
     transient int modCount;
 
     /**
-     * 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.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                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);
-            }
-
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find. If 0 then
-     * alternative hashing is disabled.
-     */
-    transient int hashSeed = 0;
-
-    /**
      * Constructs an empty <tt>HashMap</tt> with the specified initial
      * capacity and load factor.
      *
@@ -256,13 +202,21 @@
         if (initialCapacity < 0)
             throw new IllegalArgumentException("Illegal initial capacity: " +
                                                initialCapacity);
-        if (initialCapacity > MAXIMUM_CAPACITY)
+        if (initialCapacity > MAXIMUM_CAPACITY) {
             initialCapacity = MAXIMUM_CAPACITY;
+        } else if (initialCapacity < DEFAULT_INITIAL_CAPACITY) {
+            initialCapacity = DEFAULT_INITIAL_CAPACITY;
+        }
+
         if (loadFactor <= 0 || Float.isNaN(loadFactor))
             throw new IllegalArgumentException("Illegal load factor: " +
                                                loadFactor);
+        // Android-Note: We always use the default load factor of 0.75f.
 
-        this.loadFactor = loadFactor;
+        // This might appear wrong but it's just awkward design. We always call
+        // inflateTable() when table == EMPTY_TABLE. That method will take "threshold"
+        // to mean "capacity" and then replace it with the real threshold (i.e, multiplied with
+        // the load factor).
         threshold = initialCapacity;
         init();
     }
@@ -331,7 +285,6 @@
 
         threshold = (int) thresholdFloat;
         table = new HashMapEntry[capacity];
-        initHashSeedAsNeeded(capacity);
     }
 
     // internal utilities
@@ -347,45 +300,6 @@
     }
 
     /**
-     * Initialize the hashing mask value. We defer initialization until we
-     * really need it.
-     */
-    final boolean initHashSeedAsNeeded(int capacity) {
-        boolean currentAltHashing = hashSeed != 0;
-        boolean useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean switching = currentAltHashing ^ useAltHashing;
-        if (switching) {
-            hashSeed = useAltHashing
-                ? sun.misc.Hashing.randomHashSeed(this)
-                : 0;
-        }
-        return switching;
-    }
-
-    /**
-     * Retrieve object hash code and applies a supplemental hash function to the
-     * result hash, which defends against poor quality hash functions.  This is
-     * critical because HashMap uses power-of-two length hash tables, that
-     * otherwise encounter collisions for hashCodes that do not differ
-     * in lower bits. Note: Null keys always map to hash 0, thus index 0.
-     */
-    final int hash(Object k) {
-        int h = hashSeed;
-        if (0 != h && k instanceof String) {
-            return sun.misc.Hashing.stringHash32((String) k);
-        }
-
-        h ^= 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).
-        h ^= (h >>> 20) ^ (h >>> 12);
-        return h ^ (h >>> 7) ^ (h >>> 4);
-    }
-
-    /**
      * Returns index for hash code h.
      */
     static int indexFor(int h, int length) {
@@ -476,7 +390,7 @@
             return null;
         }
 
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         for (HashMapEntry<K,V> e = table[indexFor(hash, table.length)];
              e != null;
              e = e.next) {
@@ -506,7 +420,7 @@
         }
         if (key == null)
             return putForNullKey(value);
-        int hash = hash(key);
+        int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         for (HashMapEntry<K,V> e = table[i]; e != null; e = e.next) {
             Object k;
@@ -547,7 +461,7 @@
      * addEntry.
      */
     private void putForCreate(K key, V value) {
-        int hash = null == key ? 0 : hash(key);
+        int hash = null == key ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
 
         /**
@@ -595,7 +509,7 @@
         }
 
         HashMapEntry[] newTable = new HashMapEntry[newCapacity];
-        transfer(newTable, initHashSeedAsNeeded(newCapacity));
+        transfer(newTable);
         table = newTable;
         threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
     }
@@ -603,14 +517,11 @@
     /**
      * Transfers all entries from current table to newTable.
      */
-    void transfer(HashMapEntry[] newTable, boolean rehash) {
+    void transfer(HashMapEntry[] newTable) {
         int newCapacity = newTable.length;
         for (HashMapEntry<K,V> e : table) {
             while(null != e) {
                 HashMapEntry<K,V> next = e.next;
-                if (rehash) {
-                    e.hash = null == e.key ? 0 : hash(e.key);
-                }
                 int i = indexFor(e.hash, newCapacity);
                 e.next = newTable[i];
                 newTable[i] = e;
@@ -683,7 +594,7 @@
         if (size == 0) {
             return null;
         }
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         HashMapEntry<K,V> prev = table[i];
         HashMapEntry<K,V> e = prev;
@@ -719,7 +630,7 @@
 
         Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
         Object key = entry.getKey();
-        int hash = (key == null) ? 0 : hash(key);
+        int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);
         int i = indexFor(hash, table.length);
         HashMapEntry<K,V> prev = table[i];
         HashMapEntry<K,V> e = prev;
@@ -895,7 +806,7 @@
     void addEntry(int hash, K key, V value, int bucketIndex) {
         if ((size >= threshold) && (null != table[bucketIndex])) {
             resize(2 * table.length);
-            hash = (null != key) ? hash(key) : 0;
+            hash = (null != key) ? sun.misc.Hashing.singleWordWangJenkinsHash(key) : 0;
             bucketIndex = indexFor(hash, table.length);
         }
 
diff --git a/ojluni/src/main/java/java/util/Hashtable.java b/ojluni/src/main/java/java/util/Hashtable.java
index 791d2b4..783d17b 100755
--- a/ojluni/src/main/java/java/util/Hashtable.java
+++ b/ojluni/src/main/java/java/util/Hashtable.java
@@ -168,80 +168,8 @@
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = 1421746759512286392L;
 
-    /**
-     * 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.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                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);
-            }
-
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find.
-     */
-    transient int hashSeed;
-
-    /**
-     * Initialize the hashing mask value.
-     */
-    final boolean initHashSeedAsNeeded(int capacity) {
-        boolean currentAltHashing = hashSeed != 0;
-        boolean useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean switching = currentAltHashing ^ useAltHashing;
-        if (switching) {
-            hashSeed = useAltHashing
-                ? sun.misc.Hashing.randomHashSeed(this)
-                : 0;
-        }
-        return switching;
-    }
-
-    private int hash(Object k) {
-        // hashSeed will be zero if alternative hashing is disabled.
-        return hashSeed ^ k.hashCode();
+    private static int hash(Object k) {
+        return k.hashCode();
     }
 
     /**
@@ -265,7 +193,6 @@
         this.loadFactor = loadFactor;
         table = new HashtableEntry[initialCapacity];
         threshold = (initialCapacity <= MAX_ARRAY_SIZE + 1) ? initialCapacity : MAX_ARRAY_SIZE + 1;
-        initHashSeedAsNeeded(initialCapacity);
     }
 
     /**
@@ -477,7 +404,6 @@
 
         modCount++;
         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
-        boolean rehash = initHashSeedAsNeeded(newCapacity);
 
         table = newMap;
 
@@ -486,9 +412,6 @@
                 HashtableEntry<K,V> e = old;
                 old = old.next;
 
-                if (rehash) {
-                    e.hash = hash(e.key);
-                }
                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                 e.next = newMap[index];
                 newMap[index] = e;
@@ -1086,7 +1009,6 @@
         HashtableEntry<K,V>[] newTable = new HashtableEntry[length];
         threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
         count = 0;
-        initHashSeedAsNeeded(length);
 
         // Read the number of elements and then all the key/value objects
         for (; elements > 0; elements--) {
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index 037c133..5a35728 100755
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -26,6 +26,8 @@
 
 package java.util;
 
+import sun.misc.Hashing;
+
 import java.io.*;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -265,11 +267,9 @@
      * faster to iterate using our linked list.
      */
     @Override
-    void transfer(HashMapEntry[] newTable, boolean rehash) {
+    void transfer(HashMapEntry[] newTable) {
         int newCapacity = newTable.length;
         for (LinkedHashMapEntry<K,V> e = header.after; e != header; e = e.after) {
-            if (rehash)
-                e.hash = (e.key == null) ? 0 : hash(e.key);
             int index = indexFor(e.hash, newCapacity);
             e.next = newTable[index];
             newTable[index] = e;
diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java
index 1e67600..7785e05 100755
--- a/ojluni/src/main/java/java/util/WeakHashMap.java
+++ b/ojluni/src/main/java/java/util/WeakHashMap.java
@@ -189,68 +189,6 @@
      */
     int modCount;
 
-    /**
-     * 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.
-     */
-    private static class Holder {
-
-        /**
-         * Table capacity above which to switch to use alternative hashing.
-         */
-        static final int ALTERNATIVE_HASHING_THRESHOLD;
-
-        static {
-            String altThreshold = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.map.althashing.threshold"));
-
-            int threshold;
-            try {
-                threshold = (null != altThreshold)
-                        ? Integer.parseInt(altThreshold)
-                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
-
-                // disable alternative hashing if -1
-                if (threshold == -1) {
-                    threshold = Integer.MAX_VALUE;
-                }
-
-                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);
-            }
-            ALTERNATIVE_HASHING_THRESHOLD = threshold;
-        }
-    }
-
-    /**
-     * If {@code true} then perform alternate hashing to reduce the incidence of
-     * collisions due to weak hash code calculation.
-     */
-    transient boolean useAltHashing;
-
-    /**
-     * A randomizing value associated with this instance that is applied to
-     * hash code of keys to make hash collisions harder to find.
-     *
-     * This hash seed is only used if {@code useAltHashing} is true.
-     */
-    transient int hashSeed;
-
     @SuppressWarnings("unchecked")
     private Entry<K,V>[] newTable(int n) {
         return (Entry<K,V>[]) new Entry[n];
@@ -281,13 +219,6 @@
         table = newTable(capacity);
         this.loadFactor = loadFactor;
         threshold = (int)(capacity * loadFactor);
-        useAltHashing = sun.misc.VM.isBooted() &&
-                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        if (useAltHashing) {
-            hashSeed = sun.misc.Hashing.randomHashSeed(this);
-        } else {
-            hashSeed = 0;
-        }
     }
 
     /**
@@ -356,34 +287,6 @@
     }
 
     /**
-     * Retrieve object hash code and applies a supplemental hash function to the
-     * result hash, which defends against poor quality hash functions.  This is
-     * critical because HashMap uses power-of-two length hash tables, that
-     * otherwise encounter collisions for hashCodes that do not differ
-     * in lower bits.
-     */
-    int hash(Object k) {
-
-        int h;
-        if (useAltHashing) {
-            h = hashSeed;
-            if (k instanceof String) {
-                return sun.misc.Hashing.stringHash32((String) k);
-            } else {
-                h ^= k.hashCode();
-            }
-        } else  {
-            h = 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).
-        h ^= (h >>> 20) ^ (h >>> 12);
-        return h ^ (h >>> 7) ^ (h >>> 4);
-    }
-
-    /**
      * Returns index for hash code h.
      */
     private static int indexFor(int h, int length) {
@@ -472,7 +375,7 @@
      */
     public V get(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -502,7 +405,7 @@
      */
     Entry<K,V> getEntry(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int index = indexFor(h, tab.length);
         Entry<K,V> e = tab[index];
@@ -525,7 +428,7 @@
      */
     public V put(K key, V value) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
 
@@ -569,14 +472,7 @@
         }
 
         Entry<K,V>[] newTable = newTable(newCapacity);
-        boolean oldAltHashing = useAltHashing;
-        useAltHashing |= sun.misc.VM.isBooted() &&
-                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
-        boolean rehash = oldAltHashing ^ useAltHashing;
-        if (rehash) {
-            hashSeed = sun.misc.Hashing.randomHashSeed(this);
-        }
-        transfer(oldTable, newTable, rehash);
+        transfer(oldTable, newTable);
         table = newTable;
 
         /*
@@ -588,13 +484,13 @@
             threshold = (int)(newCapacity * loadFactor);
         } else {
             expungeStaleEntries();
-            transfer(newTable, oldTable, false);
+            transfer(newTable, oldTable);
             table = oldTable;
         }
     }
 
     /** Transfers all entries from src to dest tables */
-    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest, boolean rehash) {
+    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
         for (int j = 0; j < src.length; ++j) {
             Entry<K,V> e = src[j];
             src[j] = null;
@@ -606,9 +502,6 @@
                     e.value = null; //  "   "
                     size--;
                 } else {
-                    if (rehash) {
-                        e.hash = hash(key);
-                    }
                     int i = indexFor(e.hash, dest.length);
                     e.next = dest[i];
                     dest[i] = e;
@@ -677,7 +570,7 @@
      */
     public V remove(Object key) {
         Object k = maskNull(key);
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         Entry<K,V>[] tab = getTable();
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
@@ -708,7 +601,7 @@
         Entry<K,V>[] tab = getTable();
         Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
         Object k = maskNull(entry.getKey());
-        int h = hash(k);
+        int h = sun.misc.Hashing.singleWordWangJenkinsHash(k);
         int i = indexFor(h, tab.length);
         Entry<K,V> prev = tab[i];
         Entry<K,V> e = prev;
diff --git a/ojluni/src/main/java/sun/misc/Hashing.java b/ojluni/src/main/java/sun/misc/Hashing.java
index 50e55ab..2b3b144 100755
--- a/ojluni/src/main/java/sun/misc/Hashing.java
+++ b/ojluni/src/main/java/sun/misc/Hashing.java
@@ -25,9 +25,6 @@
 package sun.misc;
 
 import java.util.concurrent.ThreadLocalRandom;
-// ----- BEGIN android -----
-import java.lang.JavaLangAccess;
-// ----- END android -----
 
 /**
  * Hashing utilities.
@@ -43,212 +40,18 @@
         throw new Error("No instances");
     }
 
-    public static int murmur3_32(byte[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
+    // Spread bits to regularize both segment and index locations,
+    // using variant of single-word Wang/Jenkins hash.
+    //
+    // Based on commit 1424a2a1a9fc53dc8b859a77c02c924.
+    public static int singleWordWangJenkinsHash(Object k) {
+        int h = k.hashCode();
 
-    public static int murmur3_32(int seed, byte[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    @SuppressWarnings("fallthrough")
-    public static int murmur3_32(int seed, byte[] data, int offset, int len) {
-        int h1 = seed;
-        int count = len;
-
-        // body
-        while (count >= 4) {
-            int k1 = (data[offset] & 0x0FF)
-                    | (data[offset + 1] & 0x0FF) << 8
-                    | (data[offset + 2] & 0x0FF) << 16
-                    | data[offset + 3] << 24;
-
-            count -= 4;
-            offset += 4;
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail
-
-        if (count > 0) {
-            int k1 = 0;
-
-            switch (count) {
-                case 3:
-                    k1 ^= (data[offset + 2] & 0xff) << 16;
-                // fall through
-                case 2:
-                    k1 ^= (data[offset + 1] & 0xff) << 8;
-                // fall through
-                case 1:
-                    k1 ^= (data[offset] & 0xff);
-                // fall through
-                default:
-                    k1 *= 0xcc9e2d51;
-                    k1 = Integer.rotateLeft(k1, 15);
-                    k1 *= 0x1b873593;
-                    h1 ^= k1;
-            }
-        }
-
-        // finalization
-
-        h1 ^= len;
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    public static int murmur3_32(char[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, char[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, char[] data, int offset, int len) {
-        int h1 = seed;
-
-        int off = offset;
-        int count = len;
-
-        // body
-        while (count >= 2) {
-            int k1 = (data[off++] & 0xFFFF) | (data[off++] << 16);
-
-            count -= 2;
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail
-
-        if (count > 0) {
-            int k1 = data[off];
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-            h1 ^= k1;
-        }
-
-        // finalization
-
-        h1 ^= len * (Character.SIZE / Byte.SIZE);
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    public static int murmur3_32(int[] data) {
-        return murmur3_32(0, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, int[] data) {
-        return murmur3_32(seed, data, 0, data.length);
-    }
-
-    public static int murmur3_32(int seed, int[] data, int offset, int len) {
-        int h1 = seed;
-
-        int off = offset;
-        int end = offset + len;
-
-        // body
-        while (off < end) {
-            int k1 = data[off++];
-
-            k1 *= 0xcc9e2d51;
-            k1 = Integer.rotateLeft(k1, 15);
-            k1 *= 0x1b873593;
-
-            h1 ^= k1;
-            h1 = Integer.rotateLeft(h1, 13);
-            h1 = h1 * 5 + 0xe6546b64;
-        }
-
-        // tail (always empty, as body is always 32-bit chunks)
-
-        // finalization
-
-        h1 ^= len * (Integer.SIZE / Byte.SIZE);
-
-        // finalization mix force all bits of a hash block to avalanche
-        h1 ^= h1 >>> 16;
-        h1 *= 0x85ebca6b;
-        h1 ^= h1 >>> 13;
-        h1 *= 0xc2b2ae35;
-        h1 ^= h1 >>> 16;
-
-        return h1;
-    }
-
-    /**
-     * Return a 32 bit hash value for the specified string. The algorithm is
-     * unspecified but will be consistent within a VM instance.
-     *
-     * @param string String to be hashed.
-     * @return hash value of the string.
-     */
-    public static int stringHash32(String string) {
-        // Android-changed: Access JavaLangAccess directly.
-        return JavaLangAccess.getStringHash32(string);
-    }
-
-    /**
-     * Return a non-zero 32-bit pseudo random value. The {@code instance} object
-     * may be used as part of the value.
-     *
-     * @param instance an object to use if desired in choosing value.
-     * @return a non-zero 32-bit pseudo random value.
-     */
-    public static int randomHashSeed(Object instance) {
-        int seed;
-        if (sun.misc.VM.isBooted()) {
-            seed = ThreadLocalRandom.current().nextInt();
-        } else {
-            // lower quality "random" seed value--still better than zero and not
-            // not practically reversible.
-            int hashing_seed[] = {
-                System.identityHashCode(Hashing.class),
-                System.identityHashCode(instance),
-                System.identityHashCode(Thread.currentThread()),
-                (int) Thread.currentThread().getId(),
-                (int) (System.currentTimeMillis() >>> 2), // resolution is poor
-                (int) (System.nanoTime() >>> 5), // resolution is poor
-                (int) (Runtime.getRuntime().freeMemory() >>> 4) // alloc min
-            };
-
-            seed = murmur3_32(hashing_seed);
-        }
-
-        // force to non-zero.
-        return (0 != seed) ? seed : 1;
+        h += (h <<  15) ^ 0xffffcd7d;
+        h ^= (h >>> 10);
+        h += (h <<   3);
+        h ^= (h >>>  6);
+        h += (h <<   2) + (h << 14);
+        return h ^ (h >>> 16);
     }
 }