changeset 17587:64e7af0827e4

Merge
author ddehaven
date Mon, 22 Aug 2016 10:02:10 -0700
parents 1c3ef7e04a28 71716def08ac
children 2193be826227
files src/java.base/share/classes/java/lang/reflect/AbstractClassLoaderValue.java src/java.base/share/classes/java/lang/reflect/ClassLoaderValue.java test/java/lang/reflect/ClassLoaderValue/Driver.java test/java/lang/reflect/ClassLoaderValue/java.base/java/lang/reflect/ClassLoaderValueTest.java
diffstat 193 files changed, 3940 insertions(+), 2298 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Aug 22 10:35:16 2016 -0700
+++ b/.hgtags	Mon Aug 22 10:02:10 2016 -0700
@@ -374,3 +374,4 @@
 47699aa2e69ec2702542dc73eb01de3bfb61aea0 jdk-9+129
 6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130
 8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131
+d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132
--- a/make/copy/Copy-java.base.gmk	Mon Aug 22 10:35:16 2016 -0700
+++ b/make/copy/Copy-java.base.gmk	Mon Aug 22 10:02:10 2016 -0700
@@ -183,7 +183,7 @@
 
 DEF_POLICY_SRC_LIST := $(DEF_POLICY_SRC)
 
-ifeq ($(OPENJDK_TARGET_OS), windows)
+ifneq ($(filter $(OPENJDK_TARGET_OS), windows solaris), )
   DEF_POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/lib/security/default.policy
 endif
 
--- a/src/java.base/macosx/classes/apple/security/AppleProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/macosx/classes/apple/security/AppleProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package apple.security;
 
 import java.security.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * The Apple Security Provider.
@@ -74,7 +75,7 @@
 
     public AppleProvider() {
         /* We are the Apple provider */
-        super("Apple", 9.0d, info);
+        super("Apple", PROVIDER_VER, info);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,7 +107,12 @@
             throw new InvalidKeySpecException("Key length is negative");
         }
         try {
-            this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
+            this.prf = Mac.getInstance(prfAlgo);
+            // SunPKCS11 requires a non-empty PBE password
+            if (passwdBytes.length == 0 &&
+                this.prf.getProvider().getName().startsWith("SunPKCS11")) {
+                this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
+            }
         } catch (NoSuchAlgorithmException nsae) {
             // not gonna happen; re-throw just in case
             InvalidKeySpecException ike = new InvalidKeySpecException();
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import java.security.AccessController;
 import java.security.Provider;
 import java.security.SecureRandom;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 
 /**
@@ -104,7 +105,7 @@
 
     public SunJCE() {
         /* We are the "SunJCE" provider */
-        super("SunJCE", 9.0d, info);
+        super("SunJCE", PROVIDER_VER, info);
 
         final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" +
             "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
--- a/src/java.base/share/classes/java/io/BufferedReader.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/BufferedReader.java	Mon Aug 22 10:02:10 2016 -0700
@@ -560,7 +560,7 @@
      * @since 1.8
      */
     public Stream<String> lines() {
-        Iterator<String> iter = new Iterator<String>() {
+        Iterator<String> iter = new Iterator<>() {
             String nextLine = null;
 
             @Override
--- a/src/java.base/share/classes/java/io/ByteArrayOutputStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/ByteArrayOutputStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -187,7 +187,7 @@
      * @return  the current contents of this output stream, as a byte array.
      * @see     java.io.ByteArrayOutputStream#size()
      */
-    public synchronized byte toByteArray()[] {
+    public synchronized byte[] toByteArray() {
         return Arrays.copyOf(buf, count);
     }
 
--- a/src/java.base/share/classes/java/io/CharArrayWriter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/CharArrayWriter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -165,7 +165,7 @@
      *
      * @param  csq
      *         The character sequence to append.  If {@code csq} is
-     *         {@code null}, then the four characters "{@code null}" are
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -173,7 +173,7 @@
      * @since  1.5
      */
     public CharArrayWriter append(CharSequence csq) {
-        String s = (csq == null ? "null" : csq.toString());
+        String s = String.valueOf(csq);
         write(s, 0, s.length());
         return this;
     }
@@ -193,7 +193,7 @@
      *         The character sequence from which a subsequence will be
      *         appended.  If {@code csq} is {@code null}, then characters
      *         will be appended as if {@code csq} contained the four
-     *         characters "{@code null}".
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -212,9 +212,8 @@
      * @since  1.5
      */
     public CharArrayWriter append(CharSequence csq, int start, int end) {
-        String s = (csq == null ? "null" : csq).subSequence(start, end).toString();
-        write(s, 0, s.length());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
@@ -251,7 +250,7 @@
      *
      * @return an array of chars copied from the input data.
      */
-    public char toCharArray()[] {
+    public char[] toCharArray() {
         synchronized (lock) {
             return Arrays.copyOf(buf, count);
         }
--- a/src/java.base/share/classes/java/io/FileSystem.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/FileSystem.java	Mon Aug 22 10:02:10 2016 -0700
@@ -228,13 +228,8 @@
     static boolean useCanonPrefixCache = true;
 
     private static boolean getBooleanProperty(String prop, boolean defaultVal) {
-        String val = System.getProperty(prop);
-        if (val == null) return defaultVal;
-        if (val.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            return false;
-        }
+        return Boolean.parseBoolean(System.getProperty(prop,
+                String.valueOf(defaultVal)));
     }
 
     static {
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1265,22 +1265,21 @@
         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
         Boolean result = Caches.subclassAudits.get(key);
         if (result == null) {
-            result = Boolean.valueOf(auditSubclass(cl));
+            result = auditSubclass(cl);
             Caches.subclassAudits.putIfAbsent(key, result);
         }
-        if (result.booleanValue()) {
-            return;
+        if (!result) {
+            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
         }
-        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
     }
 
     /**
      * Performs reflective checks on given subclass to verify that it doesn't
-     * override security-sensitive non-final methods.  Returns true if subclass
-     * is "safe", false otherwise.
+     * override security-sensitive non-final methods.  Returns TRUE if subclass
+     * is "safe", FALSE otherwise.
      */
-    private static boolean auditSubclass(final Class<?> subcl) {
-        Boolean result = AccessController.doPrivileged(
+    private static Boolean auditSubclass(Class<?> subcl) {
+        return AccessController.doPrivileged(
             new PrivilegedAction<>() {
                 public Boolean run() {
                     for (Class<?> cl = subcl;
@@ -1303,7 +1302,6 @@
                 }
             }
         );
-        return result.booleanValue();
     }
 
     /**
--- a/src/java.base/share/classes/java/io/ObjectOutputStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1050,22 +1050,21 @@
         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
         Boolean result = Caches.subclassAudits.get(key);
         if (result == null) {
-            result = Boolean.valueOf(auditSubclass(cl));
+            result = auditSubclass(cl);
             Caches.subclassAudits.putIfAbsent(key, result);
         }
-        if (result.booleanValue()) {
-            return;
+        if (!result) {
+            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
         }
-        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
     }
 
     /**
      * Performs reflective checks on given subclass to verify that it doesn't
-     * override security-sensitive non-final methods.  Returns true if subclass
-     * is "safe", false otherwise.
+     * override security-sensitive non-final methods.  Returns TRUE if subclass
+     * is "safe", FALSE otherwise.
      */
-    private static boolean auditSubclass(final Class<?> subcl) {
-        Boolean result = AccessController.doPrivileged(
+    private static Boolean auditSubclass(Class<?> subcl) {
+        return AccessController.doPrivileged(
             new PrivilegedAction<>() {
                 public Boolean run() {
                     for (Class<?> cl = subcl;
@@ -1088,7 +1087,6 @@
                 }
             }
         );
-        return result.booleanValue();
     }
 
     /**
--- a/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1509,11 +1509,9 @@
     private static String getPackageName(Class<?> cl) {
         String s = cl.getName();
         int i = s.lastIndexOf('[');
-        if (i >= 0) {
-            s = s.substring(i + 2);
-        }
-        i = s.lastIndexOf('.');
-        return (i >= 0) ? s.substring(0, i) : "";
+        i = (i < 0) ? 0 : i + 2;
+        int j = s.lastIndexOf('.');
+        return (i < j) ? s.substring(i, j) : "";
     }
 
     /**
@@ -1535,14 +1533,14 @@
     private static String getMethodSignature(Class<?>[] paramTypes,
                                              Class<?> retType)
     {
-        StringBuilder sbuf = new StringBuilder();
-        sbuf.append('(');
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
         for (int i = 0; i < paramTypes.length; i++) {
-            appendClassSignature(sbuf, paramTypes[i]);
+            appendClassSignature(sb, paramTypes[i]);
         }
-        sbuf.append(')');
-        appendClassSignature(sbuf, retType);
-        return sbuf.toString();
+        sb.append(')');
+        appendClassSignature(sb, retType);
+        return sb.toString();
     }
 
     /**
--- a/src/java.base/share/classes/java/io/OutputStreamWriter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -233,22 +233,16 @@
 
     @Override
     public Writer append(CharSequence csq, int start, int end) throws IOException {
-        if (csq == null) {
-            write("null".subSequence(start, end).toString());
-            return this;
-        } else {
-            return append(csq.subSequence(start, end));
-        }
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     @Override
     public Writer append(CharSequence csq) throws IOException {
-        if (csq == null) {
-            se.write("null");
-        } else if (csq instanceof CharBuffer) {
+        if (csq instanceof CharBuffer) {
             se.write((CharBuffer) csq);
         } else {
-            se.write(csq.toString());
+            se.write(String.valueOf(csq));
         }
         return this;
     }
--- a/src/java.base/share/classes/java/io/PrintStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/PrintStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -568,7 +568,7 @@
      * @param      b   The {@code boolean} to be printed
      */
     public void print(boolean b) {
-        write(b ? "true" : "false");
+        write(String.valueOf(b));
     }
 
     /**
@@ -663,10 +663,7 @@
      * @param      s   The {@code String} to be printed
      */
     public void print(String s) {
-        if (s == null) {
-            s = "null";
-        }
-        write(s);
+        write(String.valueOf(s));
     }
 
     /**
@@ -1068,10 +1065,7 @@
      * @since  1.5
      */
     public PrintStream append(CharSequence csq) {
-        if (csq == null)
-            print("null");
-        else
-            print(csq.toString());
+        print(String.valueOf(csq));
         return this;
     }
 
@@ -1111,9 +1105,8 @@
      * @since  1.5
      */
     public PrintStream append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
--- a/src/java.base/share/classes/java/io/PrintWriter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/PrintWriter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -504,7 +504,7 @@
      * @param      b   The {@code boolean} to be printed
      */
     public void print(boolean b) {
-        write(b ? "true" : "false");
+        write(String.valueOf(b));
     }
 
     /**
@@ -599,10 +599,7 @@
      * @param      s   The {@code String} to be printed
      */
     public void print(String s) {
-        if (s == null) {
-            s = "null";
-        }
-        write(s);
+        write(String.valueOf(s));
     }
 
     /**
@@ -1005,10 +1002,7 @@
      * @since  1.5
      */
     public PrintWriter append(CharSequence csq) {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
@@ -1047,9 +1041,8 @@
      * @since  1.5
      */
     public PrintWriter append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
--- a/src/java.base/share/classes/java/io/SequenceInputStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/SequenceInputStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -65,12 +65,7 @@
      */
     public SequenceInputStream(Enumeration<? extends InputStream> e) {
         this.e = e;
-        try {
-            nextStream();
-        } catch (IOException ex) {
-            // This should never happen
-            throw new Error("panic");
-        }
+        peekNextStream();
     }
 
     /**
@@ -86,16 +81,10 @@
      */
     public SequenceInputStream(InputStream s1, InputStream s2) {
         Vector<InputStream> v = new Vector<>(2);
-
         v.addElement(s1);
         v.addElement(s2);
         e = v.elements();
-        try {
-            nextStream();
-        } catch (IOException ex) {
-            // This should never happen
-            throw new Error("panic");
-        }
+        peekNextStream();
     }
 
     /**
@@ -105,14 +94,17 @@
         if (in != null) {
             in.close();
         }
+        peekNextStream();
+    }
 
+    private void peekNextStream() {
         if (e.hasMoreElements()) {
             in = (InputStream) e.nextElement();
             if (in == null)
                 throw new NullPointerException();
+        } else {
+            in = null;
         }
-        else in = null;
-
     }
 
     /**
--- a/src/java.base/share/classes/java/io/StringBufferInputStream.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/StringBufferInputStream.java	Mon Aug 22 10:02:10 2016 -0700
@@ -108,6 +108,7 @@
      *             <code>-1</code> if there is no more data because the end of
      *             the stream has been reached.
      */
+    @SuppressWarnings("deprecation")
     public synchronized int read(byte b[], int off, int len) {
         if (b == null) {
             throw new NullPointerException();
@@ -126,12 +127,8 @@
         if (len <= 0) {
             return 0;
         }
-        String  s = buffer;
-        int cnt = len;
-        while (--cnt >= 0) {
-            b[off++] = (byte)s.charAt(pos++);
-        }
-
+        buffer.getBytes(pos, pos + len, b, off);
+        pos += len;
         return len;
     }
 
--- a/src/java.base/share/classes/java/io/StringReader.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/StringReader.java	Mon Aug 22 10:02:10 2016 -0700
@@ -142,8 +142,8 @@
      */
     public boolean ready() throws IOException {
         synchronized (lock) {
-        ensureOpen();
-        return true;
+            ensureOpen();
+            return true;
         }
     }
 
--- a/src/java.base/share/classes/java/io/StringWriter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/StringWriter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -139,7 +139,7 @@
      *
      * @param  csq
      *         The character sequence to append.  If {@code csq} is
-     *         {@code null}, then the four characters "{@code null}" are
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -147,10 +147,7 @@
      * @since  1.5
      */
     public StringWriter append(CharSequence csq) {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
@@ -170,7 +167,7 @@
      *         The character sequence from which a subsequence will be
      *         appended.  If {@code csq} is {@code null}, then characters
      *         will be appended as if {@code csq} contained the four
-     *         characters "{@code null}".
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -189,9 +186,8 @@
      * @since  1.5
      */
     public StringWriter append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
--- a/src/java.base/share/classes/java/io/Writer.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/io/Writer.java	Mon Aug 22 10:02:10 2016 -0700
@@ -221,7 +221,7 @@
      *
      * @param  csq
      *         The character sequence to append.  If {@code csq} is
-     *         {@code null}, then the four characters "{@code null}" are
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -232,10 +232,7 @@
      * @since  1.5
      */
     public Writer append(CharSequence csq) throws IOException {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
@@ -256,7 +253,7 @@
      *         The character sequence from which a subsequence will be
      *         appended.  If {@code csq} is {@code null}, then characters
      *         will be appended as if {@code csq} contained the four
-     *         characters "{@code null}".
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -278,9 +275,8 @@
      * @since  1.5
      */
     public Writer append(CharSequence csq, int start, int end) throws IOException {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Mon Aug 22 10:02:10 2016 -0700
@@ -36,7 +36,6 @@
 import java.lang.invoke.LambdaForm.NamedFunction;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Field;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
@@ -308,7 +307,7 @@
         /*non-public*/ char fieldTypeChar(int i) {
             return typeChars.charAt(i);
         }
-        Object fieldSignature() {
+        String fieldSignature() {
             return typeChars;
         }
         public Class<? extends BoundMethodHandle> fieldHolder() {
--- a/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java	Mon Aug 22 10:02:10 2016 -0700
@@ -27,6 +27,7 @@
 
 import java.util.Arrays;
 import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
@@ -96,14 +97,8 @@
                                         int whichCache,
                                         Object constraint,
                                         NamedFunction getTargetFn) {
-        String debugString;
-        switch(whichCache) {
-            case MethodTypeForm.LF_REBIND:            debugString = "BMH.reinvoke";      break;
-            case MethodTypeForm.LF_DELEGATE:          debugString = "MH.delegate";       break;
-            default:                                  debugString = "MH.reinvoke";       break;
-        }
         // No pre-action needed.
-        return makeReinvokerForm(target, whichCache, constraint, debugString, true, getTargetFn, null);
+        return makeReinvokerForm(target, whichCache, constraint, null, true, getTargetFn, null);
     }
     /** Create a LF which simply reinvokes a target of the given basic type. */
     static LambdaForm makeReinvokerForm(MethodHandle target,
@@ -114,6 +109,10 @@
                                         NamedFunction getTargetFn,
                                         NamedFunction preActionFn) {
         MethodType mtype = target.type().basicType();
+        Kind kind = whichKind(whichCache);
+        if (debugString == null) {
+            debugString = kind.defaultLambdaName;
+        }
         boolean customized = (whichCache < 0 ||
                 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
         boolean hasPreAction = (preActionFn != null);
@@ -145,13 +144,21 @@
             targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
             names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
         }
-        form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline);
+        form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline, kind);
         if (!customized) {
             form = mtype.form().setCachedLambdaForm(whichCache, form);
         }
         return form;
     }
 
+    private static Kind whichKind(int whichCache) {
+        switch(whichCache) {
+            case MethodTypeForm.LF_REBIND:   return BOUND_REINVOKER;
+            case MethodTypeForm.LF_DELEGATE: return DELEGATE;
+            default:                         return REINVOKER;
+        }
+    }
+
     static final NamedFunction NF_getTarget;
     static {
         try {
@@ -160,5 +167,13 @@
         } catch (ReflectiveOperationException ex) {
             throw newInternalError(ex);
         }
+        // The Holder class will contain pre-generated DelegatingMethodHandles resolved
+        // speculatively using MemberName.getFactory().resolveOrNull. However, that
+        // doesn't initialize the class, which subtly breaks inlining etc. By forcing
+        // initialization of the Holder class we avoid these issues.
+        UNSAFE.ensureClassInitialized(Holder.class);
     }
+
+    /* Placeholder class for DelegatingMethodHandles generated ahead of time */
+    final class Holder {}
 }
--- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Mon Aug 22 10:02:10 2016 -0700
@@ -38,6 +38,7 @@
 import java.util.Objects;
 
 import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 import static java.lang.invoke.MethodHandleStatics.newInternalError;
@@ -189,14 +190,15 @@
     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
         boolean needsInit = (which == LF_INVSTATIC_INIT);
         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
-        String linkerName, lambdaName;
+        String linkerName;
+        LambdaForm.Kind kind;
         switch (which) {
-        case LF_INVVIRTUAL:    linkerName = "linkToVirtual";    lambdaName = "DMH.invokeVirtual";    break;
-        case LF_INVSTATIC:     linkerName = "linkToStatic";     lambdaName = "DMH.invokeStatic";     break;
-        case LF_INVSTATIC_INIT:linkerName = "linkToStatic";     lambdaName = "DMH.invokeStaticInit"; break;
-        case LF_INVSPECIAL:    linkerName = "linkToSpecial";    lambdaName = "DMH.invokeSpecial";    break;
-        case LF_INVINTERFACE:  linkerName = "linkToInterface";  lambdaName = "DMH.invokeInterface";  break;
-        case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";    lambdaName = "DMH.newInvokeSpecial"; break;
+        case LF_INVVIRTUAL:    linkerName = "linkToVirtual";   kind = DIRECT_INVOKE_VIRTUAL;     break;
+        case LF_INVSTATIC:     linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC;      break;
+        case LF_INVSTATIC_INIT:linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC_INIT; break;
+        case LF_INVSPECIAL:    linkerName = "linkToSpecial";   kind = DIRECT_INVOKE_SPECIAL;     break;
+        case LF_INVINTERFACE:  linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE;   break;
+        case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";   kind = DIRECT_NEW_INVOKE_SPECIAL; break;
         default:  throw new InternalError("which="+which);
         }
 
@@ -240,11 +242,11 @@
             result = NEW_OBJ;
         }
         names[LINKER_CALL] = new Name(linker, outArgs);
-        lambdaName += "_" + shortenSignature(basicTypeSignature(mtype));
-        LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
+        String lambdaName = kind.defaultLambdaName + "_" + shortenSignature(basicTypeSignature(mtype));
+        LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result, kind);
 
         // This is a tricky bit of code.  Don't send it through the LF interpreter.
-        lform.compileToBytecode(Holder.class);
+        lform.compileToBytecode();
         return lform;
     }
 
@@ -705,7 +707,7 @@
     }
 
     static {
-        // The DMH class will contain pre-generated DirectMethodHandles resolved
+        // The Holder class will contain pre-generated DirectMethodHandles resolved
         // speculatively using MemberName.getFactory().resolveOrNull. However, that
         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
         // initialization of the Holder class we avoid these issues.
@@ -713,5 +715,5 @@
     }
 
     /* Placeholder class for DirectMethodHandles generated ahead of time */
-    private final class Holder {}
+    final class Holder {}
 }
--- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java	Mon Aug 22 10:02:10 2016 -0700
@@ -29,21 +29,82 @@
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
 
+import java.util.ArrayList;
+import java.util.HashSet;
+
 /**
  * Helper class to assist the GenerateJLIClassesPlugin to get access to
  * generate classes ahead of time.
  */
 class GenerateJLIClassesHelper {
 
-    static byte[] generateDMHClassBytes(String className,
+    static byte[] generateBasicFormsClassBytes(String className) {
+        ArrayList<LambdaForm> forms = new ArrayList<>();
+        ArrayList<String> names = new ArrayList<>();
+        HashSet<String> dedupSet = new HashSet<>();
+        for (LambdaForm.BasicType type : LambdaForm.BasicType.values()) {
+            LambdaForm zero = LambdaForm.zeroForm(type);
+            String name = zero.kind.defaultLambdaName
+                   + "_" + zero.returnType().basicTypeChar();
+            if (dedupSet.add(name)) {
+                names.add(name);
+                forms.add(zero);
+            }
+
+            LambdaForm identity = LambdaForm.identityForm(type);
+            name = identity.kind.defaultLambdaName
+                   + "_" + identity.returnType().basicTypeChar();
+            if (dedupSet.add(name)) {
+                names.add(name);
+                forms.add(identity);
+            }
+        }
+        return generateCodeBytesForLFs(className,
+                names.toArray(new String[0]),
+                forms.toArray(new LambdaForm[0]));
+    }
+
+    static byte[] generateDirectMethodHandleHolderClassBytes(String className,
             MethodType[] methodTypes, int[] types) {
         LambdaForm[] forms = new LambdaForm[methodTypes.length];
+        String[] names = new String[methodTypes.length];
         for (int i = 0; i < forms.length; i++) {
             forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i],
                                                                  types[i]);
-            methodTypes[i] = forms[i].methodType();
+            names[i] = forms[i].kind.defaultLambdaName;
         }
-        return generateCodeBytesForLFs(className, forms, methodTypes);
+        return generateCodeBytesForLFs(className, names, forms);
+    }
+
+    static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
+            MethodType[] methodTypes) {
+
+        HashSet<MethodType> dedupSet = new HashSet<>();
+        ArrayList<LambdaForm> forms = new ArrayList<>();
+        ArrayList<String> names = new ArrayList<>();
+        for (int i = 0; i < methodTypes.length; i++) {
+            // generate methods representing the DelegatingMethodHandle
+            if (dedupSet.add(methodTypes[i])) {
+                // reinvokers are variant with the associated SpeciesData
+                // and shape of the target LF, but we can easily pregenerate
+                // the basic reinvokers associated with Species_L. Ultimately we
+                // may want to consider pregenerating more of these, which will
+                // require an even more complex naming scheme
+                LambdaForm reinvoker = makeReinvokerFor(methodTypes[i]);
+                forms.add(reinvoker);
+                String speciesSig = BoundMethodHandle
+                        .speciesData(reinvoker).fieldSignature();
+                assert(speciesSig.equals("L"));
+                names.add(reinvoker.kind.defaultLambdaName + "_" + speciesSig);
+
+                LambdaForm delegate = makeDelegateFor(methodTypes[i]);
+                forms.add(delegate);
+                names.add(delegate.kind.defaultLambdaName);
+            }
+        }
+        return generateCodeBytesForLFs(className,
+                names.toArray(new String[0]),
+                forms.toArray(new LambdaForm[0]));
     }
 
     /*
@@ -51,22 +112,45 @@
      * a class with a specified name.
      */
     private static byte[] generateCodeBytesForLFs(String className,
-            LambdaForm[] forms, MethodType[] types) {
-        assert(forms.length == types.length);
+            String[] names, LambdaForm[] forms) {
 
         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
         cw.visit(Opcodes.V1_8, Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
                 className, null, InvokerBytecodeGenerator.INVOKER_SUPER_NAME, null);
         cw.visitSource(className.substring(className.lastIndexOf('/') + 1), null);
+
         for (int i = 0; i < forms.length; i++) {
-            InvokerBytecodeGenerator g
-                    = new InvokerBytecodeGenerator(className, forms[i], types[i]);
-            g.setClassWriter(cw);
-            g.addMethod();
+            addMethod(className, names[i], forms[i],
+                    forms[i].methodType(), cw);
         }
         return cw.toByteArray();
     }
 
+    private static void addMethod(String className, String methodName, LambdaForm form,
+            MethodType type, ClassWriter cw) {
+        InvokerBytecodeGenerator g
+                = new InvokerBytecodeGenerator(className, methodName, form, type);
+        g.setClassWriter(cw);
+        g.addMethod();
+    }
+
+    private static LambdaForm makeReinvokerFor(MethodType type) {
+        MethodHandle emptyHandle = MethodHandles.empty(type);
+        return DelegatingMethodHandle.makeReinvokerForm(emptyHandle,
+                MethodTypeForm.LF_REBIND,
+                BoundMethodHandle.speciesData_L(),
+                BoundMethodHandle.speciesData_L().getterFunction(0));
+    }
+
+    private static LambdaForm makeDelegateFor(MethodType type) {
+        MethodHandle handle = MethodHandles.empty(type);
+        return DelegatingMethodHandle.makeReinvokerForm(
+                handle,
+                MethodTypeForm.LF_DELEGATE,
+                DelegatingMethodHandle.class,
+                DelegatingMethodHandle.NF_getTarget);
+    }
+
     static Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
             final String types) {
         for (char c : types.toCharArray()) {
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Mon Aug 22 10:02:10 2016 -0700
@@ -46,6 +46,7 @@
 
 import static java.lang.invoke.LambdaForm.*;
 import static java.lang.invoke.LambdaForm.BasicType.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 
@@ -125,9 +126,15 @@
     }
 
     /** For generating customized code for a single LambdaForm. */
-    InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
+    private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
+        this(className, form.debugName, form, invokerType);
+    }
+
+    /** For generating customized code for a single LambdaForm. */
+    InvokerBytecodeGenerator(String className, String invokerName,
+            LambdaForm form, MethodType invokerType) {
         this(form, form.names.length,
-             className, form.debugName, invokerType);
+             className, invokerName, invokerType);
         // Create an array to map name indexes to locals indexes.
         Name[] names = form.names;
         for (int i = 0, index = 0; i < localsMap.length; i++) {
@@ -597,10 +604,47 @@
         return c.getName().replace('.', '/');
     }
 
+    private static MemberName resolveFrom(String name, MethodType type, Class<?> holder) {
+        MemberName member = new MemberName(holder, name, type, REF_invokeStatic);
+        MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder);
+
+        return resolvedMember;
+    }
+
+    private static MemberName lookupPregenerated(LambdaForm form) {
+        if (form.customized != null) {
+            // No pre-generated version for customized LF
+            return null;
+        }
+        MethodType invokerType = form.methodType();
+        String name = form.kind.methodName;
+        switch (form.kind) {
+            case BOUND_REINVOKER: {
+                name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature();
+                return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
+            }
+            case DELEGATE:                  return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
+            case ZERO:                      // fall-through
+            case IDENTITY: {
+                name = name + "_" + form.returnType().basicTypeChar();
+                return resolveFrom(name, invokerType, LambdaForm.Holder.class);
+            }
+            case DIRECT_INVOKE_INTERFACE:   // fall-through
+            case DIRECT_INVOKE_SPECIAL:     // fall-through
+            case DIRECT_INVOKE_STATIC:      // fall-through
+            case DIRECT_INVOKE_STATIC_INIT: // fall-through
+            case DIRECT_INVOKE_VIRTUAL:     return resolveFrom(name, invokerType, DirectMethodHandle.Holder.class);
+        }
+        return null;
+    }
+
     /**
      * Generate customized bytecode for a given LambdaForm.
      */
     static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
+        MemberName pregenerated = lookupPregenerated(form);
+        if (pregenerated != null)  return pregenerated; // pre-generated bytecode
+
         InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
         return g.loadMethod(g.generateCustomizedCodeBytes());
     }
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Mon Aug 22 10:02:10 2016 -0700
@@ -41,6 +41,7 @@
 import static java.lang.invoke.LambdaForm.BasicType.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
 import static java.lang.invoke.MethodHandleStatics.*;
+import java.util.Objects;
 
 /**
  * The symbolic, non-executable form of a method handle's invocation semantics.
@@ -127,6 +128,7 @@
     final MethodHandle customized;
     @Stable final Name[] names;
     final String debugName;
+    final Kind kind;
     MemberName vmentry;   // low-level behavior, or null if not yet prepared
     private boolean isCompiled;
 
@@ -266,12 +268,48 @@
         }
     }
 
+    enum Kind {
+        GENERIC(""),
+        ZERO("zero"),
+        IDENTITY("identity"),
+        BOUND_REINVOKER("BMH.reinvoke"),
+        REINVOKER("MH.reinvoke"),
+        DELEGATE("MH.delegate"),
+        DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
+        DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
+        DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
+        DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
+        DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
+        DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
+
+        final String defaultLambdaName;
+        final String methodName;
+
+        private Kind(String defaultLambdaName) {
+            this.defaultLambdaName = defaultLambdaName;
+            int p = defaultLambdaName.indexOf('.');
+            if (p > -1) {
+                this.methodName = defaultLambdaName.substring(p + 1);
+            } else {
+                this.methodName = defaultLambdaName;
+            }
+        }
+    }
+
     LambdaForm(String debugName,
                int arity, Name[] names, int result) {
-        this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null);
+        this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
+    }
+    LambdaForm(String debugName,
+               int arity, Name[] names, int result, Kind kind) {
+        this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, kind);
     }
     LambdaForm(String debugName,
                int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
+        this(debugName, arity, names, result, forceInline, customized, Kind.GENERIC);
+    }
+    LambdaForm(String debugName,
+               int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) {
         assert(namesOK(arity, names));
         this.arity = arity;
         this.result = fixResult(result, names);
@@ -279,6 +317,7 @@
         this.debugName = fixDebugName(debugName);
         this.forceInline = forceInline;
         this.customized = customized;
+        this.kind = kind;
         int maxOutArity = normalize();
         if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
             // Cannot use LF interpreter on very high arity expressions.
@@ -288,11 +327,15 @@
     }
     LambdaForm(String debugName,
                int arity, Name[] names) {
-        this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
+        this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
     }
     LambdaForm(String debugName,
                int arity, Name[] names, boolean forceInline) {
-        this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null);
+        this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
+    }
+    LambdaForm(String debugName,
+               int arity, Name[] names, boolean forceInline, Kind kind) {
+        this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind);
     }
     LambdaForm(String debugName,
                Name[] formals, Name[] temps, Name result) {
@@ -325,6 +368,7 @@
         this.debugName = "LF.zero";
         this.forceInline = true;
         this.customized = null;
+        this.kind = Kind.GENERIC;
         assert(nameRefsAreLegal());
         assert(isEmpty());
         String sig = null;
@@ -395,7 +439,7 @@
 
     /** Customize LambdaForm for a particular MethodHandle */
     LambdaForm customize(MethodHandle mh) {
-        LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
+        LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh, kind);
         if (COMPILE_THRESHOLD >= 0 && isCompiled) {
             // If shared LambdaForm has been compiled, compile customized version as well.
             customForm.compileToBytecode();
@@ -773,28 +817,6 @@
         }
     }
 
-    /**
-     * Generate optimizable bytecode for this form after first looking for a
-     * pregenerated version in a specified class.
-     */
-    void compileToBytecode(Class<?> lookupClass) {
-        if (vmentry != null && isCompiled) {
-            return;  // already compiled somehow
-        }
-        MethodType invokerType = methodType();
-        assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
-        int dot = debugName.indexOf('.');
-        String methodName = (dot > 0) ? debugName.substring(dot + 1) : debugName;
-        MemberName member = new MemberName(lookupClass, methodName, invokerType, REF_invokeStatic);
-        MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, lookupClass);
-        if (resolvedMember != null) {
-            vmentry = resolvedMember;
-            isCompiled = true;
-        } else {
-            compileToBytecode();
-        }
-    }
-
     private static void computeInitialPreparedForms() {
         // Find all predefined invokers and associate them with canonical empty lambda forms.
         for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
@@ -1828,7 +1850,7 @@
         // bootstrap dependency on this method in case we're interpreting LFs
         if (isVoid) {
             Name[] idNames = new Name[] { argument(0, L_TYPE) };
-            idForm = new LambdaForm(idMem.getName(), 1, idNames, VOID_RESULT);
+            idForm = new LambdaForm(idMem.getName(), 1, idNames, VOID_RESULT, Kind.IDENTITY);
             idForm.compileToBytecode();
             idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
 
@@ -1836,15 +1858,17 @@
             zeFun = idFun;
         } else {
             Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
-            idForm = new LambdaForm(idMem.getName(), 2, idNames, 1);
+            idForm = new LambdaForm(idMem.getName(), 2, idNames, 1, Kind.IDENTITY);
             idForm.compileToBytecode();
-            idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
+            idFun = new NamedFunction(idMem, MethodHandleImpl.makeIntrinsic(
+                    idMem.getInvocationType(), idForm, MethodHandleImpl.Intrinsic.IDENTITY));
 
             Object zeValue = Wrapper.forBasicType(btChar).zero();
             Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
-            zeForm = new LambdaForm(zeMem.getName(), 1, zeNames, 1);
+            zeForm = new LambdaForm(zeMem.getName(), 1, zeNames, 1, Kind.ZERO);
             zeForm.compileToBytecode();
-            zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm));
+            zeFun = new NamedFunction(zeMem, MethodHandleImpl.makeIntrinsic(
+                    zeMem.getInvocationType(), zeForm, MethodHandleImpl.Intrinsic.ZERO));
         }
 
         LF_zero[ord] = zeForm;
@@ -1901,8 +1925,17 @@
         if (USE_PREDEFINED_INTERPRET_METHODS)
             computeInitialPreparedForms();
         NamedFunction.initializeInvokers();
+
+        // The Holder class will contain pre-generated forms resolved
+        // using MemberName.getFactory(). However, that doesn't initialize the
+        // class, which subtly breaks inlining etc. By forcing
+        // initialization of the Holder class we avoid these issues.
+        UNSAFE.ensureClassInitialized(Holder.class);
     }
 
+    /* Placeholder class for zero and identity forms generated ahead of time */
+    final class Holder {}
+
     // The following hack is necessary in order to suppress TRACE_INTERPRETER
     // during execution of the static initializes of this class.
     // Turning on TRACE_INTERPRETER too early will cause
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1718,10 +1718,19 @@
             }
 
             @Override
-            public byte[] generateDMHClassBytes(String className,
-            MethodType[] methodTypes, int[] types) {
+            public byte[] generateDirectMethodHandleHolderClassBytes(
+                    String className, MethodType[] methodTypes, int[] types) {
                 return GenerateJLIClassesHelper
-                        .generateDMHClassBytes(className, methodTypes, types);
+                        .generateDirectMethodHandleHolderClassBytes(
+                                className, methodTypes, types);
+            }
+
+            @Override
+            public byte[] generateDelegatingMethodHandleHolderClassBytes(
+                    String className, MethodType[] methodTypes) {
+                return GenerateJLIClassesHelper
+                        .generateDelegatingMethodHandleHolderClassBytes(
+                                className, methodTypes);
             }
 
             @Override
@@ -1730,6 +1739,12 @@
                 return GenerateJLIClassesHelper
                         .generateConcreteBMHClassBytes(types);
             }
+
+            @Override
+            public byte[] generateBasicFormsClassBytes(final String className) {
+                return GenerateJLIClassesHelper
+                        .generateBasicFormsClassBytes(className);
+            }
         });
     }
 
@@ -1925,7 +1940,7 @@
      * @return whether the counter has reached the limit.
      */
     static boolean countedLoopPredicate(int counter, int limit) {
-        return counter <= limit;
+        return counter < limit;
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Aug 22 10:02:10 2016 -0700
@@ -4583,7 +4583,8 @@
      *     // assume MH_decrement is a handle to x-1 of type int
      *     MethodHandle[]
      *         indexVar = {start, MH_increment}, // i = start; i = i+1
-     *         loopLimit = {end, null, MH_lessThan, returnVar }, // i<end
+     *         loopLimit = {end, null,
+     *                       filterArgument(MH_lessThan, 0, MH_decrement), returnVar}, // i-1<end
      *         bodyClause = {init,
      *                       filterArgument(dropArguments(body, 1, int.class), 0, MH_decrement}; // v = body(i-1, v)
      *     return loop(indexVar, loopLimit, bodyClause);
@@ -4619,12 +4620,12 @@
         MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;
         MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);
         MethodHandle actualEnd = end == null ? constant(int.class, 0) : end;
+        MethodHandle decr = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter);
         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
         MethodHandle[] loopLimit = {actualEnd, null,
-                MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
-        MethodHandle[] bodyClause = {actualInit,
-                filterArgument(dropArguments(actualBody, 1, int.class), 0,
-                        MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
+                filterArgument(MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), 0, decr),
+                returnVar};
+        MethodHandle[] bodyClause = {actualInit, filterArgument(dropArguments(actualBody, 1, int.class), 0, decr)};
         return loop(indexVar, loopLimit, bodyClause);
     }
 
--- a/src/java.base/share/classes/java/lang/reflect/AbstractClassLoaderValue.java	Mon Aug 22 10:35:16 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang.reflect;
-
-import jdk.internal.loader.BootLoader;
-import jdk.internal.misc.JavaLangAccess;
-import jdk.internal.misc.SharedSecrets;
-
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BiFunction;
-import java.util.function.Supplier;
-
-/**
- * AbstractClassLoaderValue is a superclass of root-{@link ClassLoaderValue}
- * and {@link Sub sub}-ClassLoaderValue.
- *
- * @param <CLV> the type of concrete ClassLoaderValue (this type)
- * @param <V>   the type of values associated with ClassLoaderValue
- */
-abstract class AbstractClassLoaderValue<CLV extends AbstractClassLoaderValue<CLV, V>, V> {
-
-    /**
-     * Sole constructor.
-     */
-    AbstractClassLoaderValue() {}
-
-    /**
-     * Returns the key component of this ClassLoaderValue. The key component of
-     * the root-{@link ClassLoaderValue} is the ClassLoaderValue itself,
-     * while the key component of a {@link #sub(Object) sub}-ClassLoaderValue
-     * is what was given to construct it.
-     *
-     * @return the key component of this ClassLoaderValue.
-     */
-    public abstract Object key();
-
-    /**
-     * Constructs new sub-ClassLoaderValue of this ClassLoaderValue with given
-     * key component.
-     *
-     * @param key the key component of the sub-ClassLoaderValue.
-     * @param <K> the type of the key component.
-     * @return a sub-ClassLoaderValue of this ClassLoaderValue for given key
-     */
-    public <K> Sub<K> sub(K key) {
-        return new Sub<>(key);
-    }
-
-    /**
-     * Returns {@code true} if this ClassLoaderValue is equal to given {@code clv}
-     * or if this ClassLoaderValue was derived from given {@code clv} by a chain
-     * of {@link #sub(Object)} invocations.
-     *
-     * @param clv the ClassLoaderValue to test this against
-     * @return if this ClassLoaderValue is equal to given {@code clv} or
-     * its descendant
-     */
-    public abstract boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv);
-
-    /**
-     * Returns the value associated with this ClassLoaderValue and given ClassLoader
-     * or {@code null} if there is none.
-     *
-     * @param cl the ClassLoader for the associated value
-     * @return the value associated with this ClassLoaderValue and given ClassLoader
-     * or {@code null} if there is none.
-     */
-    public V get(ClassLoader cl) {
-        Object val = AbstractClassLoaderValue.<CLV>map(cl).get(this);
-        try {
-            return extractValue(val);
-        } catch (Memoizer.RecursiveInvocationException e) {
-            // propagate recursive get() for the same key that is just
-            // being calculated in computeIfAbsent()
-            throw e;
-        } catch (Throwable t) {
-            // don't propagate exceptions thrown from Memoizer - pretend
-            // that there was no entry
-            // (computeIfAbsent invocation will try to remove it anyway)
-            return null;
-        }
-    }
-
-    /**
-     * Associates given value {@code v} with this ClassLoaderValue and given
-     * ClassLoader and returns {@code null} if there was no previously associated
-     * value or does nothing and returns previously associated value if there
-     * was one.
-     *
-     * @param cl the ClassLoader for the associated value
-     * @param v  the value to associate
-     * @return previously associated value or null if there was none
-     */
-    public V putIfAbsent(ClassLoader cl, V v) {
-        ConcurrentHashMap<CLV, Object> map = map(cl);
-        @SuppressWarnings("unchecked")
-        CLV clv = (CLV) this;
-        while (true) {
-            try {
-                Object val = map.putIfAbsent(clv, v);
-                return extractValue(val);
-            } catch (Memoizer.RecursiveInvocationException e) {
-                // propagate RecursiveInvocationException for the same key that
-                // is just being calculated in computeIfAbsent
-                throw e;
-            } catch (Throwable t) {
-                // don't propagate exceptions thrown from foreign Memoizer -
-                // pretend that there was no entry and retry
-                // (foreign computeIfAbsent invocation will try to remove it anyway)
-            }
-            // TODO:
-            // Thread.onSpinLoop(); // when available
-        }
-    }
-
-    /**
-     * Removes the value associated with this ClassLoaderValue and given
-     * ClassLoader if the associated value is equal to given value {@code v} and
-     * returns {@code true} or does nothing and returns {@code false} if there is
-     * no currently associated value or it is not equal to given value {@code v}.
-     *
-     * @param cl the ClassLoader for the associated value
-     * @param v  the value to compare with currently associated value
-     * @return {@code true} if the association was removed or {@code false} if not
-     */
-    public boolean remove(ClassLoader cl, Object v) {
-        return AbstractClassLoaderValue.<CLV>map(cl).remove(this, v);
-    }
-
-    /**
-     * Returns the value associated with this ClassLoaderValue and given
-     * ClassLoader if there is one or computes the value by invoking given
-     * {@code mappingFunction}, associates it and returns it.
-     * <p>
-     * Computation and association of the computed value is performed atomically
-     * by the 1st thread that requests a particular association while holding a
-     * lock associated with this ClassLoaderValue and given ClassLoader.
-     * Nested calls from the {@code mappingFunction} to {@link #get},
-     * {@link #putIfAbsent} or {@link #computeIfAbsent} for the same association
-     * are not allowed and throw {@link IllegalStateException}. Nested call to
-     * {@link #remove} for the same association is allowed but will always return
-     * {@code false} regardless of passed-in comparison value. Nested calls for
-     * other association(s) are allowed, but care should be taken to avoid
-     * deadlocks. When two threads perform nested computations of the overlapping
-     * set of associations they should always request them in the same order.
-     *
-     * @param cl              the ClassLoader for the associated value
-     * @param mappingFunction the function to compute the value
-     * @return the value associated with this ClassLoaderValue and given
-     * ClassLoader.
-     * @throws IllegalStateException if a direct or indirect invocation from
-     *                               within given {@code mappingFunction} that
-     *                               computes the value of a particular association
-     *                               to {@link #get}, {@link #putIfAbsent} or
-     *                               {@link #computeIfAbsent}
-     *                               for the same association is attempted.
-     */
-    public V computeIfAbsent(ClassLoader cl,
-                             BiFunction<
-                                 ? super ClassLoader,
-                                 ? super CLV,
-                                 ? extends V
-                                 > mappingFunction) throws IllegalStateException {
-        ConcurrentHashMap<CLV, Object> map = map(cl);
-        @SuppressWarnings("unchecked")
-        CLV clv = (CLV) this;
-        Memoizer<CLV, V> mv = null;
-        while (true) {
-            Object val = (mv == null) ? map.get(clv) : map.putIfAbsent(clv, mv);
-            if (val == null) {
-                if (mv == null) {
-                    // create Memoizer lazily when 1st needed and restart loop
-                    mv = new Memoizer<>(cl, clv, mappingFunction);
-                    continue;
-                }
-                // mv != null, therefore sv == null was a result of successful
-                // putIfAbsent
-                try {
-                    // trigger Memoizer to compute the value
-                    V v = mv.get();
-                    // attempt to replace our Memoizer with the value
-                    map.replace(clv, mv, v);
-                    // return computed value
-                    return v;
-                } catch (Throwable t) {
-                    // our Memoizer has thrown, attempt to remove it
-                    map.remove(clv, mv);
-                    // propagate exception because it's from our Memoizer
-                    throw t;
-                }
-            } else {
-                try {
-                    return extractValue(val);
-                } catch (Memoizer.RecursiveInvocationException e) {
-                    // propagate recursive attempts to calculate the same
-                    // value as being calculated at the moment
-                    throw e;
-                } catch (Throwable t) {
-                    // don't propagate exceptions thrown from foreign Memoizer -
-                    // pretend that there was no entry and retry
-                    // (foreign computeIfAbsent invocation will try to remove it anyway)
-                }
-            }
-            // TODO:
-            // Thread.onSpinLoop(); // when available
-        }
-    }
-
-    /**
-     * Removes all values associated with given ClassLoader {@code cl} and
-     * {@link #isEqualOrDescendantOf(AbstractClassLoaderValue) this or descendants}
-     * of this ClassLoaderValue.
-     * This is not an atomic operation. Other threads may see some associations
-     * be already removed and others still present while this method is executing.
-     * <p>
-     * The sole intention of this method is to cleanup after a unit test that
-     * tests ClassLoaderValue directly. It is not intended for use in
-     * actual algorithms.
-     *
-     * @param cl the associated ClassLoader of the values to be removed
-     */
-    public void removeAll(ClassLoader cl) {
-        ConcurrentHashMap<CLV, Object> map = map(cl);
-        for (Iterator<CLV> i = map.keySet().iterator(); i.hasNext(); ) {
-            if (i.next().isEqualOrDescendantOf(this)) {
-                i.remove();
-            }
-        }
-    }
-
-    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
-
-    /**
-     * @return a ConcurrentHashMap for given ClassLoader
-     */
-    @SuppressWarnings("unchecked")
-    private static <CLV extends AbstractClassLoaderValue<CLV, ?>>
-    ConcurrentHashMap<CLV, Object> map(ClassLoader cl) {
-        return (ConcurrentHashMap<CLV, Object>)
-            (cl == null ? BootLoader.getClassLoaderValueMap()
-                        : JLA.createOrGetClassLoaderValueMap(cl));
-    }
-
-    /**
-     * @return value extracted from the {@link Memoizer} if given
-     * {@code memoizerOrValue} parameter is a {@code Memoizer} or
-     * just return given parameter.
-     */
-    @SuppressWarnings("unchecked")
-    private V extractValue(Object memoizerOrValue) {
-        if (memoizerOrValue instanceof Memoizer) {
-            return ((Memoizer<?, V>) memoizerOrValue).get();
-        } else {
-            return (V) memoizerOrValue;
-        }
-    }
-
-    /**
-     * A memoized supplier that invokes given {@code mappingFunction} just once
-     * and remembers the result or thrown exception for subsequent calls.
-     * If given mappingFunction returns null, it is converted to NullPointerException,
-     * thrown from the Memoizer's {@link #get()} method and remembered.
-     * If the Memoizer is invoked recursively from the given {@code mappingFunction},
-     * {@link RecursiveInvocationException} is thrown, but it is not remembered.
-     * The in-flight call to the {@link #get()} can still complete successfully if
-     * such exception is handled by the mappingFunction.
-     */
-    private static final class Memoizer<CLV extends AbstractClassLoaderValue<CLV, V>, V>
-        implements Supplier<V> {
-
-        private final ClassLoader cl;
-        private final CLV clv;
-        private final BiFunction<? super ClassLoader, ? super CLV, ? extends V>
-            mappingFunction;
-
-        private volatile V v;
-        private volatile Throwable t;
-        private boolean inCall;
-
-        Memoizer(ClassLoader cl,
-                 CLV clv,
-                 BiFunction<? super ClassLoader, ? super CLV, ? extends V>
-                     mappingFunction
-        ) {
-            this.cl = cl;
-            this.clv = clv;
-            this.mappingFunction = mappingFunction;
-        }
-
-        @Override
-        public V get() throws RecursiveInvocationException {
-            V v = this.v;
-            if (v != null) return v;
-            Throwable t = this.t;
-            if (t == null) {
-                synchronized (this) {
-                    if ((v = this.v) == null && (t = this.t) == null) {
-                        if (inCall) {
-                            throw new RecursiveInvocationException();
-                        }
-                        inCall = true;
-                        try {
-                            this.v = v = Objects.requireNonNull(
-                                mappingFunction.apply(cl, clv));
-                        } catch (Throwable x) {
-                            this.t = t = x;
-                        } finally {
-                            inCall = false;
-                        }
-                    }
-                }
-            }
-            if (v != null) return v;
-            if (t instanceof Error) {
-                throw (Error) t;
-            } else if (t instanceof RuntimeException) {
-                throw (RuntimeException) t;
-            } else {
-                throw new UndeclaredThrowableException(t);
-            }
-        }
-
-        static class RecursiveInvocationException extends IllegalStateException {
-            private static final long serialVersionUID = 1L;
-
-            RecursiveInvocationException() {
-                super("Recursive call");
-            }
-        }
-    }
-
-    /**
-     * sub-ClassLoaderValue is an inner class of {@link AbstractClassLoaderValue}
-     * and also a subclass of it. It can therefore be instantiated as an inner
-     * class of either an instance of root-{@link ClassLoaderValue} or another
-     * instance of itself. This enables composing type-safe compound keys of
-     * arbitrary length:
-     * <pre>{@code
-     * ClassLoaderValue<V> clv = new ClassLoaderValue<>();
-     * ClassLoaderValue<V>.Sub<K1>.Sub<K2>.Sub<K3> clv_k123 =
-     *     clv.sub(k1).sub(k2).sub(k3);
-     * }</pre>
-     * From which individual components are accessible in a type-safe way:
-     * <pre>{@code
-     * K1 k1 = clv_k123.parent().parent().key();
-     * K2 k2 = clv_k123.parent().key();
-     * K3 k3 = clv_k123.key();
-     * }</pre>
-     * This allows specifying non-capturing lambdas for the mapping function of
-     * {@link #computeIfAbsent(ClassLoader, BiFunction)} operation that can
-     * access individual key components from passed-in
-     * sub-[sub-...]ClassLoaderValue instance in a type-safe way.
-     *
-     * @param <K> the type of {@link #key()} component contained in the
-     *            sub-ClassLoaderValue.
-     */
-    final class Sub<K> extends AbstractClassLoaderValue<Sub<K>, V> {
-
-        private final K key;
-
-        Sub(K key) {
-            this.key = key;
-        }
-
-        /**
-         * @return the parent ClassLoaderValue this sub-ClassLoaderValue
-         * has been {@link #sub(Object) derived} from.
-         */
-        public AbstractClassLoaderValue<CLV, V> parent() {
-            return AbstractClassLoaderValue.this;
-        }
-
-        /**
-         * @return the key component of this sub-ClassLoaderValue.
-         */
-        @Override
-        public K key() {
-            return key;
-        }
-
-        /**
-         * sub-ClassLoaderValue is a descendant of given {@code clv} if it is
-         * either equal to it or if its {@link #parent() parent} is a
-         * descendant of given {@code clv}.
-         */
-        @Override
-        public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
-            return equals(Objects.requireNonNull(clv)) ||
-                   parent().isEqualOrDescendantOf(clv);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof Sub)) return false;
-            @SuppressWarnings("unchecked")
-            Sub<?> that = (Sub<?>) o;
-            return this.parent().equals(that.parent()) &&
-                   Objects.equals(this.key, that.key);
-        }
-
-        @Override
-        public int hashCode() {
-            return 31 * parent().hashCode() +
-                   Objects.hashCode(key);
-        }
-    }
-}
--- a/src/java.base/share/classes/java/lang/reflect/ClassLoaderValue.java	Mon Aug 22 10:35:16 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang.reflect;
-
-import java.util.Objects;
-import java.util.function.BiFunction;
-
-/**
- * root-ClassLoaderValue. Each instance defines a separate namespace for
- * associated values.
- * <p>
- * ClassLoaderValue allows associating a
- * {@link #computeIfAbsent(ClassLoader, BiFunction) computed} non-null value with
- * a {@code (ClassLoader, keys...)} tuple. The associated value, as well as the
- * keys are strongly reachable from the associated ClassLoader so care should be
- * taken to use such keys and values that only reference types resolvable from
- * the associated ClassLoader. Failing that, ClassLoader leaks are inevitable.
- * <p>
- * Example usage:
- * <pre>{@code
- * // create a root instance which represents a namespace and declares the type of
- * // associated values (Class instances in this example)
- * static final ClassLoaderValue<Class<?>> proxyClasses = new ClassLoaderValue<>();
- *
- * // create a compound key composed of a Module and a list of interfaces
- * Module module = ...;
- * List<Class<?>> interfaces = ...;
- * ClassLoaderValue<Class<?>>.Sub<Module>.Sub<List<Class<?>>> key =
- *     proxyClasses.sub(module).sub(interfaces);
- *
- * // use the compound key together with ClassLoader to lazily associate
- * // the value with tuple (loader, module, interfaces) and return it
- * ClassLoader loader = ...;
- * Class<?> proxyClass = key.computeIfAbsent(loader, (ld, ky) -> {
- *     List<Class<?>> intfcs = ky.key();
- *     Module m = ky.parent().key();
- *     Class<?> clazz = defineProxyClass(ld, m, intfcs);
- *     return clazz;
- * });
- * }</pre>
- * <p>
- * {@code classLoaderValue.<operation>(classLoader, ...)} represents an operation
- * to {@link #get}, {@link #putIfAbsent}, {@link #computeIfAbsent} or {@link #remove}
- * a value associated with a (classLoader, classLoaderValue) tuple. ClassLoader
- * instances and root-{@link ClassLoaderValue} instances are compared using
- * identity equality while {@link Sub sub}-ClassLoaderValue instances define
- * {@link #equals(Object) equality} in terms of equality of its
- * {@link Sub#parent() parent} ClassLoaderValue and its
- * {@link #key() key} component.
- *
- * @param <V> the type of value(s) associated with the root-ClassLoaderValue and
- *            all its {@link #sub(Object) descendants}.
- * @author Peter Levart
- * @since 9
- */
-final class ClassLoaderValue<V>
-    extends AbstractClassLoaderValue<ClassLoaderValue<V>, V> {
-
-    /**
-     * Constructs new root-ClassLoaderValue representing its own namespace.
-     */
-    public ClassLoaderValue() {}
-
-    /**
-     * @return the key component of this root-ClassLoaderValue (itself).
-     */
-    @Override
-    public ClassLoaderValue<V> key() {
-        return this;
-    }
-
-    /**
-     * root-ClassLoaderValue can only be equal to itself and has no predecessors.
-     */
-    @Override
-    public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
-        return equals(Objects.requireNonNull(clv));
-    }
-}
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Aug 22 10:02:10 2016 -0700
@@ -29,11 +29,9 @@
 import java.security.PrivilegedAction;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -49,6 +47,7 @@
 import jdk.internal.misc.VM;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
+import jdk.internal.loader.ClassLoaderValue;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.action.GetPropertyAction;
 import sun.security.util.SecurityConstants;
--- a/src/java.base/share/classes/java/security/AuthProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/security/AuthProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,9 +50,24 @@
      * @param name the provider name.
      * @param version the provider version number.
      * @param info a description of the provider and its services.
+     * @deprecated use {@link #AuthProvider(String, String, String)} instead.
      */
+    @Deprecated(since="9")
     protected AuthProvider(String name, double version, String info) {
-        super(name, version, info);
+        super(name, Double.toString(version), info);
+    }
+
+    /**
+     * Constructs a provider with the specified name, version string,
+     * and information.
+     *
+     * @param name the provider name.
+     * @param versionStr the provider version string.
+     * @param info a description of the provider and its services.
+     * @since 9
+     */
+    protected AuthProvider(String name, String versionStr, String info) {
+        super(name, versionStr, info);
     }
 
     /**
--- a/src/java.base/share/classes/java/security/Provider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/security/Provider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -67,14 +67,14 @@
  * <tr><td>{@code Provider.id name}</td>
   *    <td>{@code String.valueOf(provider.getName())}</td>
  * <tr><td>{@code Provider.id version}</td>
- *     <td>{@code String.valueOf(provider.getVersion())}</td>
+ *     <td>{@code String.valueOf(provider.getVersionStr())}</td>
  * <tr><td>{@code Provider.id info}</td>
        <td>{@code String.valueOf(provider.getInfo())}</td>
  * <tr><td>{@code Provider.id className}</td>
  *     <td>{@code provider.getClass().getName()}</td>
  * </table>
  *
- * <p>Each provider has a name and a version number. A provider normally
+ * <p>Each provider has a name and a version string. A provider normally
  * identifies itself with a file named {@code java.security.Provider}
  * in the resource directory {@code META-INF/services}.
  * Security providers are looked up via the {@link ServiceLoader} mechanism
@@ -102,11 +102,10 @@
 public abstract class Provider extends Properties {
 
     // Declare serialVersionUID to be compatible with JDK1.1
-    static final long serialVersionUID = -4298000515446427739L;
+    private static final long serialVersionUID = -4298000515446427739L;
 
     private static final sun.security.util.Debug debug =
-        sun.security.util.Debug.getInstance
-        ("provider", "Provider");
+        sun.security.util.Debug.getInstance("provider", "Provider");
 
     /**
      * The provider name.
@@ -129,6 +128,12 @@
      */
     private double version;
 
+    /**
+     * The provider version string.
+     *
+     * @serial
+     */
+    private String versionStr;
 
     private transient Set<Map.Entry<Object,Object>> entrySet = null;
     private transient int entrySetCallCount = 0;
@@ -174,19 +179,83 @@
         }
     }
 
+    private static double parseVersionStr(String s) {
+        try {
+            int firstDotIdx = s.indexOf('.');
+            int nextDotIdx = s.indexOf('.', firstDotIdx + 1);
+            if (nextDotIdx != -1) {
+                s = s.substring(0, nextDotIdx);
+            }
+            int endIdx = s.indexOf('-');
+            if (endIdx > 0) {
+                s = s.substring(0, endIdx);
+            }
+            endIdx = s.indexOf('+');
+            if (endIdx > 0) {
+                s = s.substring(0, endIdx);
+            }
+            return Double.parseDouble(s);
+        } catch (NullPointerException | NumberFormatException e) {
+            return 0d;
+        }
+    }
+
     /**
      * Constructs a provider with the specified name, version number,
-     * and information.
+     * and information. Calling this constructor is equivalent to call the
+     * {@link #Provider(String, String, String)} with {@code name}
+     * name, {@code Double.toString(version)}, and {@code info}.
      *
      * @param name the provider name.
      *
      * @param version the provider version number.
      *
      * @param info a description of the provider and its services.
+     *
+     * @deprecated use {@link #Provider(String, String, String)} instead.
      */
+    @Deprecated(since="9")
     protected Provider(String name, double version, String info) {
         this.name = name;
         this.version = version;
+        this.versionStr = Double.toString(version);
+        this.info = info;
+        putId();
+        initialized = true;
+    }
+
+    /**
+     * Constructs a provider with the specified name, version string,
+     * and information.
+     *
+     * <p>The version string contains a version number optionally followed
+     * by other information separated by one of the characters of '+', '-'.
+     *
+     * The format for the version number is:
+     *
+     * <blockquote><pre>
+     *     ^[0-9]+(\.[0-9]+)*
+     * </pre></blockquote>
+     *
+     * <p>In order to return the version number in a double, when there are
+     * more than two components (separated by '.' as defined above), only
+     * the first two components are retained. The resulting string is then
+     * passed to {@link Double#valueOf(String)} to generate version number,
+     * i.e. {@link #getVersion}.
+     * <p>If the conversion failed, value 0 will be used.
+     *
+     * @param name the provider name.
+     *
+     * @param versionStr the provider version string.
+     *
+     * @param info a description of the provider and its services.
+     *
+     * @since 9
+     */
+    protected Provider(String name, String versionStr, String info) {
+        this.name = name;
+        this.versionStr = versionStr;
+        this.version = parseVersionStr(versionStr);
         this.info = info;
         putId();
         initialized = true;
@@ -250,12 +319,26 @@
      * Returns the version number for this provider.
      *
      * @return the version number for this provider.
+     *
+     * @deprecated use {@link #getVersionStr} instead.
      */
+    @Deprecated(since="9")
     public double getVersion() {
         return version;
     }
 
     /**
+     * Returns the version string for this provider.
+     *
+     * @return the version string for this provider.
+     *
+     * @since 9
+     */
+    public String getVersionStr() {
+        return versionStr;
+    }
+
+    /**
      * Returns a human-readable description of the provider and its
      * services.  This may return an HTML page, with relevant links.
      *
@@ -266,14 +349,14 @@
     }
 
     /**
-     * Returns a string with the name and the version number
+     * Returns a string with the name and the version string
      * of this provider.
      *
-     * @return the string with the name and the version number
+     * @return the string with the name and the version string
      * for this provider.
      */
     public String toString() {
-        return name + " version " + version;
+        return name + " version " + versionStr;
     }
 
     /*
@@ -601,7 +684,7 @@
     public synchronized Object compute(Object key, BiFunction<? super Object,
             ? super Object, ? extends Object> remappingFunction) {
         check("putProviderProperty." + name);
-        check("removeProviderProperty" + name);
+        check("removeProviderProperty." + name);
 
         if (debug != null) {
             debug.println("Compute " + name + " provider property " + key);
@@ -632,7 +715,7 @@
     public synchronized Object computeIfAbsent(Object key, Function<? super Object,
             ? extends Object> mappingFunction) {
         check("putProviderProperty." + name);
-        check("removeProviderProperty" + name);
+        check("removeProviderProperty." + name);
 
         if (debug != null) {
             debug.println("ComputeIfAbsent " + name + " provider property " +
@@ -662,7 +745,7 @@
     public synchronized Object computeIfPresent(Object key, BiFunction<? super Object,
             ? super Object, ? extends Object> remappingFunction) {
         check("putProviderProperty." + name);
-        check("removeProviderProperty" + name);
+        check("removeProviderProperty." + name);
 
         if (debug != null) {
             debug.println("ComputeIfPresent " + name + " provider property " +
@@ -695,7 +778,7 @@
     public synchronized Object merge(Object key, Object value,  BiFunction<? super Object,
             ? super Object, ? extends Object>  remappingFunction) {
         check("putProviderProperty." + name);
-        check("removeProviderProperty" + name);
+        check("removeProviderProperty." + name);
 
         if (debug != null) {
             debug.println("Merge " + name + " provider property " + key);
@@ -787,11 +870,21 @@
     private void putId() {
         // note: name and info may be null
         super.put("Provider.id name", String.valueOf(name));
-        super.put("Provider.id version", String.valueOf(version));
+        super.put("Provider.id version", String.valueOf(versionStr));
         super.put("Provider.id info", String.valueOf(info));
         super.put("Provider.id className", this.getClass().getName());
     }
 
+   /**
+    * Reads the {@code ObjectInputStream} for the default serializable fields.
+    * If the serialized field {@code versionStr} is found in the STREAM FIELDS,
+    * its String value will be used to populate both the version string and
+    * version number. If {@code versionStr} is not found, but {@code version}
+    * is, then its double value will be used to populate both fields.
+    *
+    * @param in the {@code ObjectInputStream} to read
+    * @serial
+    */
     private void readObject(ObjectInputStream in)
                 throws IOException, ClassNotFoundException {
         Map<Object,Object> copy = new HashMap<>();
@@ -800,6 +893,13 @@
         }
         defaults = null;
         in.defaultReadObject();
+        if (this.versionStr == null) {
+            // set versionStr based on version when not found in serialized bytes
+            this.versionStr = Double.toString(this.version);
+        } else {
+            // otherwise, set version based on versionStr
+            this.version = parseVersionStr(this.versionStr);
+        }
         implClear();
         initialized = true;
         putAll(copy);
@@ -904,8 +1004,8 @@
             if (!checkLegacy(key)) {
                 return null;
             }
-            legacyStrings.computeIfAbsent((String) key,
-                    (Function<? super String, ? extends String>) remappingFunction);
+            legacyStrings.compute((String) key,
+                    (BiFunction<? super String,? super String, ? extends String>) remappingFunction);
         }
         return super.compute(key, remappingFunction);
     }
@@ -1913,7 +2013,5 @@
             return provider.getName() + ": " + type + "." + algorithm
                 + " -> " + className + aString + attrs + "\r\n";
         }
-
     }
-
 }
--- a/src/java.base/share/classes/java/text/DateFormatSymbols.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/text/DateFormatSymbols.java	Mon Aug 22 10:02:10 2016 -0700
@@ -399,7 +399,10 @@
      * Calendar Elements in the Unicode Locale Data Markup Language
      * (LDML) specification</a> for more details.
      *
-     * @return the month strings.
+     * @return the month strings. Use
+     * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+     * etc. to index the result array.
      */
     public String[] getMonths() {
         return Arrays.copyOf(months, months.length);
@@ -407,7 +410,9 @@
 
     /**
      * Sets month strings. For example: "January", "February", etc.
-     * @param newMonths the new month strings.
+     * @param newMonths the new month strings. The array should
+     * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
      */
     public void setMonths(String[] newMonths) {
         months = Arrays.copyOf(newMonths, newMonths.length);
@@ -427,7 +432,10 @@
      * Calendar Elements in the Unicode Locale Data Markup Language
      * (LDML) specification</a> for more details.
      *
-     * @return the short month strings.
+     * @return the short month strings. Use
+     * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+     * etc. to index the result array.
      */
     public String[] getShortMonths() {
         return Arrays.copyOf(shortMonths, shortMonths.length);
@@ -435,7 +443,9 @@
 
     /**
      * Sets short month strings. For example: "Jan", "Feb", etc.
-     * @param newShortMonths the new short month strings.
+     * @param newShortMonths the new short month strings. The array should
+     * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
      */
     public void setShortMonths(String[] newShortMonths) {
         shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
@@ -444,8 +454,10 @@
 
     /**
      * Gets weekday strings. For example: "Sunday", "Monday", etc.
-     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @return the weekday strings. Use
+     * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+     * the result array.
      */
     public String[] getWeekdays() {
         return Arrays.copyOf(weekdays, weekdays.length);
@@ -454,8 +466,8 @@
     /**
      * Sets weekday strings. For example: "Sunday", "Monday", etc.
      * @param newWeekdays the new weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
+     * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
      */
     public void setWeekdays(String[] newWeekdays) {
         weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
@@ -464,8 +476,10 @@
 
     /**
      * Gets short weekday strings. For example: "Sun", "Mon", etc.
-     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @return the short weekday strings. Use
+     * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+     * the result array.
      */
     public String[] getShortWeekdays() {
         return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
@@ -474,8 +488,8 @@
     /**
      * Sets short weekday strings. For example: "Sun", "Mon", etc.
      * @param newShortWeekdays the new short weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
+     * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
      */
     public void setShortWeekdays(String[] newShortWeekdays) {
         shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
--- a/src/java.base/share/classes/java/util/Date.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/util/Date.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -952,6 +952,9 @@
      * without affecting its internal state.
      */
     static final long getMillisOf(Date date) {
+        if (date.getClass() != Date.class) {
+            return date.getTime();
+        }
         if (date.cdate == null || date.cdate.isNormalized()) {
             return date.fastTime;
         }
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Mon Aug 22 10:02:10 2016 -0700
@@ -147,11 +147,7 @@
      * @return the previous value
      */
     public final boolean getAndSet(boolean newValue) {
-        boolean prev;
-        do {
-            prev = get();
-        } while (!compareAndSet(prev, newValue));
-        return prev;
+        return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Mon Aug 22 10:02:10 2016 -0700
@@ -263,6 +263,47 @@
      * is theoretically possible, so we additionally add a
      * storeStoreFence after lock acquisition CAS.
      *
+     * ----------------------------------------------------------------
+     * Here's an informal proof that plain reads by _successful_
+     * readers see plain writes from preceding but not following
+     * writers (following Boehm and the C++ standard [atomics.fences]):
+     *
+     * Because of the total synchronization order of accesses to
+     * volatile long state containing the sequence number, writers and
+     * _successful_ readers can be globally sequenced.
+     *
+     * int x, y;
+     *
+     * Writer 1:
+     * inc sequence (odd - "locked")
+     * storeStoreFence();
+     * x = 1; y = 2;
+     * inc sequence (even - "unlocked")
+     *
+     * Successful Reader:
+     * read sequence (even)
+     * // must see writes from Writer 1 but not Writer 2
+     * r1 = x; r2 = y;
+     * acquireFence();
+     * read sequence (even - validated unchanged)
+     * // use r1 and r2
+     *
+     * Writer 2:
+     * inc sequence (odd - "locked")
+     * storeStoreFence();
+     * x = 3; y = 4;
+     * inc sequence (even - "unlocked")
+     *
+     * Visibility of writer 1's stores is normal - reader's initial
+     * read of state synchronizes with writer 1's final write to state.
+     * Lack of visibility of writer 2's plain writes is less obvious.
+     * If reader's read of x or y saw writer 2's write, then (assuming
+     * semantics of C++ fences) the storeStoreFence would "synchronize"
+     * with reader's acquireFence and reader's validation read must see
+     * writer 2's initial write to state and so validation must fail.
+     * But making this "proof" formal and rigorous is an open problem!
+     * ----------------------------------------------------------------
+     *
      * The memory layout keeps lock state and queue pointers together
      * (normally on the same cache line). This usually works well for
      * read-mostly loads. In most other cases, the natural tendency of
@@ -276,14 +317,14 @@
     /** Number of processors, for spin control */
     private static final int NCPU = Runtime.getRuntime().availableProcessors();
 
-    /** Maximum number of retries before enqueuing on acquisition */
-    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
+    /** Maximum number of retries before enqueuing on acquisition; at least 1 */
+    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
 
-    /** Maximum number of retries before blocking at head on acquisition */
-    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
+    /** Maximum number of tries before blocking at head on acquisition */
+    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 1;
 
     /** Maximum number of retries before re-blocking */
-    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
+    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 1;
 
     /** The period for yielding when waiting for overflow spinlock */
     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
@@ -1228,6 +1269,11 @@
                         WCOWAIT.compareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null) // help release
                         LockSupport.unpark(w);
+                    if (Thread.interrupted()) {
+                        if (interruptible)
+                            return cancelWaiter(node, p, true);
+                        wasInterrupted = true;
+                    }
                     if (h == (pp = p.prev) || h == p || pp == null) {
                         long m, s, ns;
                         do {
@@ -1264,11 +1310,6 @@
                                 LockSupport.parkNanos(this, time);
                         }
                         node.thread = null;
-                        if (Thread.interrupted()) {
-                            if (interruptible)
-                                return cancelWaiter(node, p, true);
-                            wasInterrupted = true;
-                        }
                     }
                 }
             }
--- a/src/java.base/share/classes/java/util/stream/Collectors.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/Collectors.java	Mon Aug 22 10:02:10 2016 -0700
@@ -295,7 +295,13 @@
     public static <T>
     Collector<T, ?, Set<T>> toSet() {
         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
-                                   (left, right) -> { left.addAll(right); return left; },
+                                   (left, right) -> {
+                                       if (left.size() < right.size()) {
+                                           right.addAll(left); return right;
+                                       } else {
+                                           left.addAll(right); return left;
+                                       }
+                                   },
                                    CH_UNORDERED_ID);
     }
 
--- a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java	Mon Aug 22 10:02:10 2016 -0700
@@ -861,6 +861,13 @@
      * be enabled by default, since this list may include cipher suites which
      * do not meet quality of service requirements for those defaults.  Such
      * cipher suites might be useful in specialized applications.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return  an array of cipher suite names
      * @see     #getEnabledCipherSuites()
@@ -880,6 +887,13 @@
      * or the requisite certificates (and private keys) for the suite are
      * not available, or an anonymous suite is enabled but authentication
      * is required.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return  an array of cipher suite names
      * @see     #getSupportedCipherSuites()
@@ -896,6 +910,14 @@
      * fail.  Following a successful call to this method, only suites
      * listed in the {@code suites} parameter are enabled for use.
      * <P>
+     * Note that the standard list of cipher suite names may be found in the
+     * <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list or might not
+     * use the recommended name for a certain cipher suite.
+     * <P>
      * See {@link #getEnabledCipherSuites()} for more information
      * on why a specific cipher suite may never be used on a engine.
      *
--- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,12 @@
      * <p>
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
-     * {@code setCipherSuites(cipherSuites);}.
+     * {@code setCipherSuites(cipherSuites);}.  Note that the
+     * standard list of cipher suite names may be found in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list.
      *
      * @param cipherSuites the array of ciphersuites (or null)
      */
@@ -123,6 +128,12 @@
      * Calling this constructor is equivalent to calling the no-args
      * constructor followed by
      * {@code setCipherSuites(cipherSuites); setProtocols(protocols);}.
+     * Note that the standard list of cipher suite names may be found in the
+     * <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list.
      *
      * @param cipherSuites the array of ciphersuites (or null)
      * @param protocols the array of protocols (or null)
@@ -139,6 +150,13 @@
     /**
      * Returns a copy of the array of ciphersuites or null if none
      * have been set.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return a copy of the array of ciphersuites or null if none
      * have been set.
@@ -150,7 +168,13 @@
     /**
      * Sets the array of ciphersuites.
      *
-     * @param cipherSuites the array of ciphersuites (or null)
+     * @param cipherSuites the array of ciphersuites (or null).  Note that the
+     * standard list of cipher suite names may be found in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list or might not
+     * use the recommended name for a certain cipher suite.
      */
     public void setCipherSuites(String[] cipherSuites) {
         this.cipherSuites = clone(cipherSuites);
--- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java	Mon Aug 22 10:02:10 2016 -0700
@@ -195,6 +195,13 @@
      * or the requisite certificates (and private keys) for the suite are
      * not available, or an anonymous suite is enabled but authentication
      * is required.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return an array of cipher suites enabled
      * @see #getSupportedCipherSuites()
@@ -215,6 +222,14 @@
      * in this ServerSocket's authentication context will not be used
      * in any case, even if they are enabled.
      * <P>
+     * Note that the standard list of cipher suite names may be found in the
+     * <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list or might not
+     * use the recommended name for a certain cipher suite.
+     * <P>
      * <code>SSLSocket</code>s returned from <code>accept()</code>
      * inherit this setting.
      *
@@ -236,6 +251,13 @@
      * be enabled by default, since this list may include cipher suites which
      * do not meet quality of service requirements for those defaults.  Such
      * cipher suites are useful in specialized applications.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return an array of cipher suite names
      * @see #getEnabledCipherSuites()
--- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,6 +123,13 @@
      * will use one of these cipher suites.  The minimum quality of service
      * for these defaults requires confidentiality protection and server
      * authentication (that is, no anonymous cipher suites).
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @see #getSupportedCipherSuites()
      * @return array of the cipher suites enabled by default
@@ -137,6 +144,13 @@
      * be enabled by default, since this list may include cipher suites which
      * do not meet quality of service requirements for those defaults.  Such
      * cipher suites are useful in specialized applications.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return an array of cipher suite names
      * @see #getDefaultCipherSuites()
--- a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java	Mon Aug 22 10:02:10 2016 -0700
@@ -265,6 +265,13 @@
      * be enabled by default, since this list may include cipher suites which
      * do not meet quality of service requirements for those defaults.  Such
      * cipher suites might be useful in specialized applications.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return an array of cipher suite names
      * @see #getEnabledCipherSuites()
@@ -284,6 +291,13 @@
      * or the requisite certificates (and private keys) for the suite are
      * not available, or an anonymous suite is enabled but authentication
      * is required.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @return an array of cipher suite names
      * @see #getSupportedCipherSuites()
@@ -300,6 +314,14 @@
      * fail.  Following a successful call to this method, only suites
      * listed in the <code>suites</code> parameter are enabled for use.
      * <P>
+     * Note that the standard list of cipher suite names may be found in the
+     * <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation.  Providers
+     * may support cipher suite names not found in this list or might not
+     * use the recommended name for a certain cipher suite.
+     * <P>
      * See {@link #getEnabledCipherSuites()} for more information
      * on why a specific ciphersuite may never be used on a connection.
      *
--- a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -148,6 +148,13 @@
      * will use one of these cipher suites.  The minimum quality of service
      * for these defaults requires confidentiality protection and server
      * authentication (that is, no anonymous cipher suites).
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @see #getSupportedCipherSuites()
      * @return array of the cipher suites enabled by default
@@ -160,6 +167,13 @@
      * be enabled by default, since this list may include cipher suites which
      * do not meet quality of service requirements for those defaults.  Such
      * cipher suites are useful in specialized applications.
+     * <P>
+     * The returned array includes cipher suites from the list of standard
+     * cipher suite names in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#ciphersuites">
+     * JSSE Cipher Suite Names</a> section of the Java Cryptography
+     * Architecture Standard Algorithm Name Documentation, and may also
+     * include other cipher suites that the provider supports.
      *
      * @see #getDefaultCipherSuites()
      * @return an array of cipher suite names
--- a/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js	Mon Aug 22 10:02:10 2016 -0700
@@ -53,6 +53,7 @@
 var Files = Java.type("java.nio.file.Files");
 var System = Java.type("java.lang.System");
 var URI = Java.type("java.net.URI");
+var Collections = Java.type("java.util.Collections");
 
 // JavaFX classes used
 var StackPane = Java.type("javafx.scene.layout.StackPane");
@@ -100,7 +101,7 @@
             print("did you miss specifying jrt-fs.jar with -cp option?");
             usage();
         }
-        return FileSystems.newFileSystem(uri, null, cls.classLoader);
+        return FileSystems.newFileSystem(uri, Collections.emptyMap(), cls.classLoader);
     }
 }
 
--- a/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js	Mon Aug 22 10:02:10 2016 -0700
@@ -34,7 +34,6 @@
  * but also compiled and delivered as part of the jrtfs.jar to support access
  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
- */
 
 // classes used
 var Files = Java.type("java.nio.file.Files");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/loader/AbstractClassLoaderValue.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.loader;
+
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+
+/**
+ * AbstractClassLoaderValue is a superclass of root-{@link ClassLoaderValue}
+ * and {@link Sub sub}-ClassLoaderValue.
+ *
+ * @param <CLV> the type of concrete ClassLoaderValue (this type)
+ * @param <V>   the type of values associated with ClassLoaderValue
+ */
+public abstract class AbstractClassLoaderValue<CLV extends AbstractClassLoaderValue<CLV, V>, V> {
+
+    /**
+     * Sole constructor.
+     */
+    AbstractClassLoaderValue() {}
+
+    /**
+     * Returns the key component of this ClassLoaderValue. The key component of
+     * the root-{@link ClassLoaderValue} is the ClassLoaderValue itself,
+     * while the key component of a {@link #sub(Object) sub}-ClassLoaderValue
+     * is what was given to construct it.
+     *
+     * @return the key component of this ClassLoaderValue.
+     */
+    public abstract Object key();
+
+    /**
+     * Constructs new sub-ClassLoaderValue of this ClassLoaderValue with given
+     * key component.
+     *
+     * @param key the key component of the sub-ClassLoaderValue.
+     * @param <K> the type of the key component.
+     * @return a sub-ClassLoaderValue of this ClassLoaderValue for given key
+     */
+    public <K> Sub<K> sub(K key) {
+        return new Sub<>(key);
+    }
+
+    /**
+     * Returns {@code true} if this ClassLoaderValue is equal to given {@code clv}
+     * or if this ClassLoaderValue was derived from given {@code clv} by a chain
+     * of {@link #sub(Object)} invocations.
+     *
+     * @param clv the ClassLoaderValue to test this against
+     * @return if this ClassLoaderValue is equal to given {@code clv} or
+     * its descendant
+     */
+    public abstract boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv);
+
+    /**
+     * Returns the value associated with this ClassLoaderValue and given ClassLoader
+     * or {@code null} if there is none.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @return the value associated with this ClassLoaderValue and given ClassLoader
+     * or {@code null} if there is none.
+     */
+    public V get(ClassLoader cl) {
+        Object val = AbstractClassLoaderValue.<CLV>map(cl).get(this);
+        try {
+            return extractValue(val);
+        } catch (Memoizer.RecursiveInvocationException e) {
+            // propagate recursive get() for the same key that is just
+            // being calculated in computeIfAbsent()
+            throw e;
+        } catch (Throwable t) {
+            // don't propagate exceptions thrown from Memoizer - pretend
+            // that there was no entry
+            // (computeIfAbsent invocation will try to remove it anyway)
+            return null;
+        }
+    }
+
+    /**
+     * Associates given value {@code v} with this ClassLoaderValue and given
+     * ClassLoader and returns {@code null} if there was no previously associated
+     * value or does nothing and returns previously associated value if there
+     * was one.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @param v  the value to associate
+     * @return previously associated value or null if there was none
+     */
+    public V putIfAbsent(ClassLoader cl, V v) {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        @SuppressWarnings("unchecked")
+        CLV clv = (CLV) this;
+        while (true) {
+            try {
+                Object val = map.putIfAbsent(clv, v);
+                return extractValue(val);
+            } catch (Memoizer.RecursiveInvocationException e) {
+                // propagate RecursiveInvocationException for the same key that
+                // is just being calculated in computeIfAbsent
+                throw e;
+            } catch (Throwable t) {
+                // don't propagate exceptions thrown from foreign Memoizer -
+                // pretend that there was no entry and retry
+                // (foreign computeIfAbsent invocation will try to remove it anyway)
+            }
+            // TODO:
+            // Thread.onSpinLoop(); // when available
+        }
+    }
+
+    /**
+     * Removes the value associated with this ClassLoaderValue and given
+     * ClassLoader if the associated value is equal to given value {@code v} and
+     * returns {@code true} or does nothing and returns {@code false} if there is
+     * no currently associated value or it is not equal to given value {@code v}.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @param v  the value to compare with currently associated value
+     * @return {@code true} if the association was removed or {@code false} if not
+     */
+    public boolean remove(ClassLoader cl, Object v) {
+        return AbstractClassLoaderValue.<CLV>map(cl).remove(this, v);
+    }
+
+    /**
+     * Returns the value associated with this ClassLoaderValue and given
+     * ClassLoader if there is one or computes the value by invoking given
+     * {@code mappingFunction}, associates it and returns it.
+     * <p>
+     * Computation and association of the computed value is performed atomically
+     * by the 1st thread that requests a particular association while holding a
+     * lock associated with this ClassLoaderValue and given ClassLoader.
+     * Nested calls from the {@code mappingFunction} to {@link #get},
+     * {@link #putIfAbsent} or {@link #computeIfAbsent} for the same association
+     * are not allowed and throw {@link IllegalStateException}. Nested call to
+     * {@link #remove} for the same association is allowed but will always return
+     * {@code false} regardless of passed-in comparison value. Nested calls for
+     * other association(s) are allowed, but care should be taken to avoid
+     * deadlocks. When two threads perform nested computations of the overlapping
+     * set of associations they should always request them in the same order.
+     *
+     * @param cl              the ClassLoader for the associated value
+     * @param mappingFunction the function to compute the value
+     * @return the value associated with this ClassLoaderValue and given
+     * ClassLoader.
+     * @throws IllegalStateException if a direct or indirect invocation from
+     *                               within given {@code mappingFunction} that
+     *                               computes the value of a particular association
+     *                               to {@link #get}, {@link #putIfAbsent} or
+     *                               {@link #computeIfAbsent}
+     *                               for the same association is attempted.
+     */
+    public V computeIfAbsent(ClassLoader cl,
+                             BiFunction<
+                                 ? super ClassLoader,
+                                 ? super CLV,
+                                 ? extends V
+                                 > mappingFunction) throws IllegalStateException {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        @SuppressWarnings("unchecked")
+        CLV clv = (CLV) this;
+        Memoizer<CLV, V> mv = null;
+        while (true) {
+            Object val = (mv == null) ? map.get(clv) : map.putIfAbsent(clv, mv);
+            if (val == null) {
+                if (mv == null) {
+                    // create Memoizer lazily when 1st needed and restart loop
+                    mv = new Memoizer<>(cl, clv, mappingFunction);
+                    continue;
+                }
+                // mv != null, therefore sv == null was a result of successful
+                // putIfAbsent
+                try {
+                    // trigger Memoizer to compute the value
+                    V v = mv.get();
+                    // attempt to replace our Memoizer with the value
+                    map.replace(clv, mv, v);
+                    // return computed value
+                    return v;
+                } catch (Throwable t) {
+                    // our Memoizer has thrown, attempt to remove it
+                    map.remove(clv, mv);
+                    // propagate exception because it's from our Memoizer
+                    throw t;
+                }
+            } else {
+                try {
+                    return extractValue(val);
+                } catch (Memoizer.RecursiveInvocationException e) {
+                    // propagate recursive attempts to calculate the same
+                    // value as being calculated at the moment
+                    throw e;
+                } catch (Throwable t) {
+                    // don't propagate exceptions thrown from foreign Memoizer -
+                    // pretend that there was no entry and retry
+                    // (foreign computeIfAbsent invocation will try to remove it anyway)
+                }
+            }
+            // TODO:
+            // Thread.onSpinLoop(); // when available
+        }
+    }
+
+    /**
+     * Removes all values associated with given ClassLoader {@code cl} and
+     * {@link #isEqualOrDescendantOf(AbstractClassLoaderValue) this or descendants}
+     * of this ClassLoaderValue.
+     * This is not an atomic operation. Other threads may see some associations
+     * be already removed and others still present while this method is executing.
+     * <p>
+     * The sole intention of this method is to cleanup after a unit test that
+     * tests ClassLoaderValue directly. It is not intended for use in
+     * actual algorithms.
+     *
+     * @param cl the associated ClassLoader of the values to be removed
+     */
+    public void removeAll(ClassLoader cl) {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        for (Iterator<CLV> i = map.keySet().iterator(); i.hasNext(); ) {
+            if (i.next().isEqualOrDescendantOf(this)) {
+                i.remove();
+            }
+        }
+    }
+
+    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+    /**
+     * @return a ConcurrentHashMap for given ClassLoader
+     */
+    @SuppressWarnings("unchecked")
+    private static <CLV extends AbstractClassLoaderValue<CLV, ?>>
+    ConcurrentHashMap<CLV, Object> map(ClassLoader cl) {
+        return (ConcurrentHashMap<CLV, Object>)
+            (cl == null ? BootLoader.getClassLoaderValueMap()
+                        : JLA.createOrGetClassLoaderValueMap(cl));
+    }
+
+    /**
+     * @return value extracted from the {@link Memoizer} if given
+     * {@code memoizerOrValue} parameter is a {@code Memoizer} or
+     * just return given parameter.
+     */
+    @SuppressWarnings("unchecked")
+    private V extractValue(Object memoizerOrValue) {
+        if (memoizerOrValue instanceof Memoizer) {
+            return ((Memoizer<?, V>) memoizerOrValue).get();
+        } else {
+            return (V) memoizerOrValue;
+        }
+    }
+
+    /**
+     * A memoized supplier that invokes given {@code mappingFunction} just once
+     * and remembers the result or thrown exception for subsequent calls.
+     * If given mappingFunction returns null, it is converted to NullPointerException,
+     * thrown from the Memoizer's {@link #get()} method and remembered.
+     * If the Memoizer is invoked recursively from the given {@code mappingFunction},
+     * {@link RecursiveInvocationException} is thrown, but it is not remembered.
+     * The in-flight call to the {@link #get()} can still complete successfully if
+     * such exception is handled by the mappingFunction.
+     */
+    private static final class Memoizer<CLV extends AbstractClassLoaderValue<CLV, V>, V>
+        implements Supplier<V> {
+
+        private final ClassLoader cl;
+        private final CLV clv;
+        private final BiFunction<? super ClassLoader, ? super CLV, ? extends V>
+            mappingFunction;
+
+        private volatile V v;
+        private volatile Throwable t;
+        private boolean inCall;
+
+        Memoizer(ClassLoader cl,
+                 CLV clv,
+                 BiFunction<? super ClassLoader, ? super CLV, ? extends V>
+                     mappingFunction
+        ) {
+            this.cl = cl;
+            this.clv = clv;
+            this.mappingFunction = mappingFunction;
+        }
+
+        @Override
+        public V get() throws RecursiveInvocationException {
+            V v = this.v;
+            if (v != null) return v;
+            Throwable t = this.t;
+            if (t == null) {
+                synchronized (this) {
+                    if ((v = this.v) == null && (t = this.t) == null) {
+                        if (inCall) {
+                            throw new RecursiveInvocationException();
+                        }
+                        inCall = true;
+                        try {
+                            this.v = v = Objects.requireNonNull(
+                                mappingFunction.apply(cl, clv));
+                        } catch (Throwable x) {
+                            this.t = t = x;
+                        } finally {
+                            inCall = false;
+                        }
+                    }
+                }
+            }
+            if (v != null) return v;
+            if (t instanceof Error) {
+                throw (Error) t;
+            } else if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
+            } else {
+                throw new UndeclaredThrowableException(t);
+            }
+        }
+
+        static class RecursiveInvocationException extends IllegalStateException {
+            private static final long serialVersionUID = 1L;
+
+            RecursiveInvocationException() {
+                super("Recursive call");
+            }
+        }
+    }
+
+    /**
+     * sub-ClassLoaderValue is an inner class of {@link AbstractClassLoaderValue}
+     * and also a subclass of it. It can therefore be instantiated as an inner
+     * class of either an instance of root-{@link ClassLoaderValue} or another
+     * instance of itself. This enables composing type-safe compound keys of
+     * arbitrary length:
+     * <pre>{@code
+     * ClassLoaderValue<V> clv = new ClassLoaderValue<>();
+     * ClassLoaderValue<V>.Sub<K1>.Sub<K2>.Sub<K3> clv_k123 =
+     *     clv.sub(k1).sub(k2).sub(k3);
+     * }</pre>
+     * From which individual components are accessible in a type-safe way:
+     * <pre>{@code
+     * K1 k1 = clv_k123.parent().parent().key();
+     * K2 k2 = clv_k123.parent().key();
+     * K3 k3 = clv_k123.key();
+     * }</pre>
+     * This allows specifying non-capturing lambdas for the mapping function of
+     * {@link #computeIfAbsent(ClassLoader, BiFunction)} operation that can
+     * access individual key components from passed-in
+     * sub-[sub-...]ClassLoaderValue instance in a type-safe way.
+     *
+     * @param <K> the type of {@link #key()} component contained in the
+     *            sub-ClassLoaderValue.
+     */
+    public final class Sub<K> extends AbstractClassLoaderValue<Sub<K>, V> {
+
+        private final K key;
+
+        Sub(K key) {
+            this.key = key;
+        }
+
+        /**
+         * @return the parent ClassLoaderValue this sub-ClassLoaderValue
+         * has been {@link #sub(Object) derived} from.
+         */
+        public AbstractClassLoaderValue<CLV, V> parent() {
+            return AbstractClassLoaderValue.this;
+        }
+
+        /**
+         * @return the key component of this sub-ClassLoaderValue.
+         */
+        @Override
+        public K key() {
+            return key;
+        }
+
+        /**
+         * sub-ClassLoaderValue is a descendant of given {@code clv} if it is
+         * either equal to it or if its {@link #parent() parent} is a
+         * descendant of given {@code clv}.
+         */
+        @Override
+        public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
+            return equals(Objects.requireNonNull(clv)) ||
+                   parent().isEqualOrDescendantOf(clv);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Sub)) return false;
+            @SuppressWarnings("unchecked")
+            Sub<?> that = (Sub<?>) o;
+            return this.parent().equals(that.parent()) &&
+                   Objects.equals(this.key, that.key);
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * parent().hashCode() +
+                   Objects.hashCode(key);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaderValue.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.loader;
+
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * root-ClassLoaderValue. Each instance defines a separate namespace for
+ * associated values.
+ * <p>
+ * ClassLoaderValue allows associating a
+ * {@link #computeIfAbsent(ClassLoader, BiFunction) computed} non-null value with
+ * a {@code (ClassLoader, keys...)} tuple. The associated value, as well as the
+ * keys are strongly reachable from the associated ClassLoader so care should be
+ * taken to use such keys and values that only reference types resolvable from
+ * the associated ClassLoader. Failing that, ClassLoader leaks are inevitable.
+ * <p>
+ * Example usage:
+ * <pre>{@code
+ * // create a root instance which represents a namespace and declares the type of
+ * // associated values (Class instances in this example)
+ * static final ClassLoaderValue<Class<?>> proxyClasses = new ClassLoaderValue<>();
+ *
+ * // create a compound key composed of a Module and a list of interfaces
+ * Module module = ...;
+ * List<Class<?>> interfaces = ...;
+ * ClassLoaderValue<Class<?>>.Sub<Module>.Sub<List<Class<?>>> key =
+ *     proxyClasses.sub(module).sub(interfaces);
+ *
+ * // use the compound key together with ClassLoader to lazily associate
+ * // the value with tuple (loader, module, interfaces) and return it
+ * ClassLoader loader = ...;
+ * Class<?> proxyClass = key.computeIfAbsent(loader, (ld, ky) -> {
+ *     List<Class<?>> intfcs = ky.key();
+ *     Module m = ky.parent().key();
+ *     Class<?> clazz = defineProxyClass(ld, m, intfcs);
+ *     return clazz;
+ * });
+ * }</pre>
+ * <p>
+ * {@code classLoaderValue.<operation>(classLoader, ...)} represents an operation
+ * to {@link #get}, {@link #putIfAbsent}, {@link #computeIfAbsent} or {@link #remove}
+ * a value associated with a (classLoader, classLoaderValue) tuple. ClassLoader
+ * instances and root-{@link ClassLoaderValue} instances are compared using
+ * identity equality while {@link Sub sub}-ClassLoaderValue instances define
+ * {@link #equals(Object) equality} in terms of equality of its
+ * {@link Sub#parent() parent} ClassLoaderValue and its
+ * {@link #key() key} component.
+ *
+ * @param <V> the type of value(s) associated with the root-ClassLoaderValue and
+ *            all its {@link #sub(Object) descendants}.
+ * @author Peter Levart
+ * @since 9
+ */
+public final class ClassLoaderValue<V>
+    extends AbstractClassLoaderValue<ClassLoaderValue<V>, V> {
+
+    /**
+     * Constructs new root-ClassLoaderValue representing its own namespace.
+     */
+    public ClassLoaderValue() {}
+
+    /**
+     * @return the key component of this root-ClassLoaderValue (itself).
+     */
+    @Override
+    public ClassLoaderValue<V> key() {
+        return this;
+    }
+
+    /**
+     * root-ClassLoaderValue can only be equal to itself and has no predecessors.
+     */
+    @Override
+    public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
+        return equals(Objects.requireNonNull(clv));
+    }
+}
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Mon Aug 22 10:02:10 2016 -0700
@@ -51,8 +51,17 @@
      * an {@code int} representing method type.  Used by
      * GenerateJLIClassesPlugin to generate such a class during the jlink phase.
      */
-    byte[] generateDMHClassBytes(String className, MethodType[] methodTypes,
-            int[] types);
+    byte[] generateDirectMethodHandleHolderClassBytes(String className,
+            MethodType[] methodTypes, int[] types);
+
+    /**
+     * Returns a {@code byte[]} containing the bytecode for a class implementing
+     * DelegatingMethodHandles of each {@code MethodType} kind in the
+     * {@code methodTypes} argument.  Used by GenerateJLIClassesPlugin to
+     * generate such a class during the jlink phase.
+     */
+    byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
+            MethodType[] methodTypes);
 
     /**
      * Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle
@@ -63,4 +72,10 @@
      */
     Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
             final String types);
+
+    /**
+     * Returns a {@code byte[]} containing the bytecode for a class implementing
+     * the zero and identity forms of all {@code LambdaForm.BasicType}s.
+     */
+    byte[] generateBasicFormsClassBytes(final String className);
 }
--- a/src/java.base/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,9 +24,8 @@
  */
 
 /**
- * java.base defines and exports the core APIs of the Java SE platform.
+ * Defines the foundational APIs of the Java SE Platform.
  */
-
 module java.base {
 
     exports java.io;
--- a/src/java.base/share/classes/sun/security/jca/ProviderList.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/jca/ProviderList.java	Mon Aug 22 10:02:10 2016 -0700
@@ -76,7 +76,7 @@
     // dummy provider object to use during initialization
     // used to avoid explicit null checks in various places
     private static final Provider EMPTY_PROVIDER =
-        new Provider("##Empty##", 1.0d, "initialization in progress") {
+        new Provider("##Empty##", "1.0", "initialization in progress") {
             private static final long serialVersionUID = 1151354171352296389L;
             // override getService() to return null slightly faster
             public Service getService(String type, String algorithm) {
--- a/src/java.base/share/classes/sun/security/provider/MD4.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/provider/MD4.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import java.security.*;
 
 import static sun.security.provider.ByteArrayAccess.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * The MD4 class is used to compute an MD4 message digest over a given
@@ -65,7 +66,8 @@
     private static final Provider md4Provider;
 
     static {
-        md4Provider = new Provider("MD4Provider", 9.0d, "MD4 MessageDigest") {
+        md4Provider = new Provider("MD4Provider", PROVIDER_VER,
+            "MD4 MessageDigest") {
             private static final long serialVersionUID = -8850464997518327965L;
         };
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.base/share/classes/sun/security/provider/Sun.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/provider/Sun.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 import java.security.*;
 
 import sun.security.action.PutAllAction;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
+
 
 /**
  * The SUN Security Provider.
@@ -47,7 +49,7 @@
 
     public Sun() {
         /* We are the SUN provider */
-        super("SUN", 9.0d, INFO);
+        super("SUN", PROVIDER_VER, INFO);
 
         // if there is no security manager installed, put directly into
         // the provider. Otherwise, create a temporary map and use a
--- a/src/java.base/share/classes/sun/security/provider/VerificationProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/provider/VerificationProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
 import sun.security.action.PutAllAction;
 
 import sun.security.rsa.SunRsaSignEntries;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
+
 
 /**
  * Provider used for verification of signed JAR files *if* the Sun and
@@ -61,7 +63,7 @@
     }
 
     public VerificationProvider() {
-        super("SunJarVerification", 9.0d, "Jar Verification Provider");
+        super("SunJarVerification", PROVIDER_VER, "Jar Verification Provider");
         // register all algorithms normally registered by the Sun and SunRsaSign
         // providers, but only if they are missing
         if (ACTIVE == false) {
--- a/src/java.base/share/classes/sun/security/rsa/SunRsaSign.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/rsa/SunRsaSign.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 import java.security.*;
 
 import sun.security.action.PutAllAction;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Provider class for the RSA signature provider. Supports RSA keyfactory,
@@ -43,7 +44,7 @@
     private static final long serialVersionUID = 866040293550393045L;
 
     public SunRsaSign() {
-        super("SunRsaSign", 9.0d, "Sun RSA signature provider");
+        super("SunRsaSign", PROVIDER_VER, "Sun RSA signature provider");
 
         // if there is no security manager installed, put directly into
         // the provider. Otherwise, create a temporary map and use a
--- a/src/java.base/share/classes/sun/security/ssl/JsseJce.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/JsseJce.java	Mon Aug 22 10:02:10 2016 -0700
@@ -44,6 +44,7 @@
 import sun.security.util.ECUtil;
 
 import static sun.security.ssl.SunJSSE.cryptoProvider;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * This class contains a few static methods for interaction with the JCA/JCE
@@ -90,7 +91,7 @@
         private static final long serialVersionUID = -3284138292032213752L;
 
         SunCertificates(final Provider p) {
-            super("SunCertificates", 9.0d, "SunJSSE internal");
+            super("SunCertificates", PROVIDER_VER, "SunJSSE internal");
             AccessController.doPrivileged(new PrivilegedAction<Object>() {
                 @Override
                 public Object run() {
--- a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java	Mon Aug 22 10:02:10 2016 -0700
@@ -27,6 +27,7 @@
 package sun.security.ssl;
 
 import java.security.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * The JSSE provider.
@@ -104,7 +105,7 @@
 
     // standard constructor
     protected SunJSSE() {
-        super("SunJSSE", 9.0d, info);
+        super("SunJSSE", PROVIDER_VER, info);
         subclassCheck();
         if (Boolean.TRUE.equals(fips)) {
             throw new ProviderException
@@ -132,7 +133,7 @@
 
     private SunJSSE(java.security.Provider cryptoProvider,
             String providerName) {
-        super("SunJSSE", 9.0d, fipsInfo + providerName + ")");
+        super("SunJSSE", PROVIDER_VER, fipsInfo + providerName + ")");
         subclassCheck();
         if (cryptoProvider == null) {
             // Calling Security.getProvider() will cause other providers to be
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Mon Aug 22 10:02:10 2016 -0700
@@ -3631,8 +3631,8 @@
                 if (time != null) {
                     if (time.matches("\\d\\d:\\d\\d:\\d\\d")) {
                         c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(time.substring(0, 2)));
-                        c.set(Calendar.MINUTE, Integer.valueOf(time.substring(0, 2)));
-                        c.set(Calendar.SECOND, Integer.valueOf(time.substring(0, 2)));
+                        c.set(Calendar.MINUTE, Integer.valueOf(time.substring(3, 5)));
+                        c.set(Calendar.SECOND, Integer.valueOf(time.substring(6, 8)));
                         c.set(Calendar.MILLISECOND, 0);
                     } else {
                         throw ioe;
--- a/src/java.base/share/classes/sun/security/util/SecurityConstants.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/security/util/SecurityConstants.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import java.security.BasicPermission;
 import java.security.SecurityPermission;
 import java.security.AllPermission;
+import sun.security.action.GetPropertyAction;
 
 /**
  * Permission constants and string constants used to create permissions
@@ -145,4 +146,7 @@
     // java.lang.SecurityManager
     public static final SocketPermission LOCAL_LISTEN_PERMISSION =
         new SocketPermission("localhost:0", SOCKET_LISTEN_ACTION);
+
+    public static final String PROVIDER_VER =
+        GetPropertyAction.privilegedGetProperty("java.specification.version");
 }
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -143,8 +143,8 @@
         defaultLocaleProviderAdapter = Type.CLDR;
         if (!typeList.isEmpty()) {
             // bona fide preference exists
-            if (!typeList.contains(Type.CLDR)) {
-                // Append FALLBACK as the last resort.
+            if (!(typeList.contains(Type.CLDR) || (typeList.contains(Type.JRE)))) {
+                // Append FALLBACK as the last resort when no ResourceBundleBasedAdapter is available.
                 typeList.add(Type.FALLBACK);
                 defaultLocaleProviderAdapter = Type.FALLBACK;
             }
--- a/src/java.compact1/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.compact1/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Aggregates {@code java.base}, {@code java.logging}, and {@code java.scripting}.
+ */
 module java.compact1 {
     requires public java.logging;
     requires public java.scripting;
--- a/src/java.compact2/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.compact2/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Supplements {@code java.compact1} with JDBC, JAXP, and RMI.
+ */
 module java.compact2 {
     requires public java.compact1;
     requires public java.rmi;
--- a/src/java.compact3/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.compact3/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,10 @@
  * questions.
  */
 
+/**
+ * Supplements {@code java.compact2} with JDBC RowSet, JMX, JNDI, Compiler,
+ * Instrumentation, Preferences, Security, and XML cryptography APIs.
+ */
 module java.compact3 {
     requires public java.compact2;
     requires public java.compiler;
--- a/src/java.datatransfer/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.datatransfer/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,10 +24,8 @@
  */
 
 /**
- * Provides interfaces and classes for transferring data between and
- * within applications.
+ * Defines an API for transferring data between and within applications.
  */
-
 module java.datatransfer {
     exports java.awt.datatransfer;
     exports sun.datatransfer to java.desktop;
--- a/src/java.desktop/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.desktop/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,9 +24,9 @@
  */
 
 /**
-  * java.desktop defines and exports the user interface, graphics
-  * and imaging APIs of the Java SE platform.
-  */
+ * Defines the AWT and Swing user interface toolkits, plus APIs for
+ * accessibility, audio, imaging, printing, and JavaBeans.
+ */
 module java.desktop {
     requires public java.datatransfer;
     requires public java.xml;
--- a/src/java.httpclient/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.httpclient/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the high-level HTTP and WebSocket API.
+ */
 module java.httpclient {
     requires java.base;
     exports java.net.http;
--- a/src/java.instrument/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.instrument/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,10 @@
  * questions.
  */
 
+/**
+ * Defines services that allow agents to
+ * instrument programs running on the JVM.
+ */
 module java.instrument {
     exports java.lang.instrument;
 }
--- a/src/java.logging/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.logging/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Java Logging API.
+ */
 module java.logging {
     exports java.util.logging;
     provides jdk.internal.logger.DefaultLoggerFinder with
--- a/src/java.management/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.management/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,12 @@
  * questions.
  */
 
+/**
+ * Defines the Java Management Extensions (JMX) API.
+ * <P>
+ * The JMX API consists of interfaces for monitoring and management of the
+ * JVM and other components in the Java runtime.
+ */
 module java.management {
     requires public java.rmi;
     requires java.logging;
--- a/src/java.naming/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.naming/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Java Naming and Directory Interface (JNDI) API.
+ */
 module java.naming {
     requires java.security.sasl;
 
--- a/src/java.naming/share/classes/sun/security/provider/certpath/ldap/JdkLDAP.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.naming/share/classes/sun/security/provider/certpath/ldap/JdkLDAP.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.util.List;
 import java.security.*;
 import java.security.cert.CertStoreParameters;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Provider class for the JdkLDAP provider.
@@ -69,7 +70,7 @@
     }
 
     public JdkLDAP() {
-        super("JdkLDAP", 9.0d, "JdkLDAP Provider (implements LDAP CertStore)");
+        super("JdkLDAP", PROVIDER_VER, "JdkLDAP Provider (implements LDAP CertStore)");
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.prefs/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.prefs/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Preferences API.
+ */
 module java.prefs {
     requires java.xml;
 
--- a/src/java.rmi/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.rmi/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Remote Method Invocation (RMI) API.
+ */
 module java.rmi {
     requires java.logging;
 
--- a/src/java.scripting/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.scripting/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Scripting API.
+ */
 module java.scripting {
     exports javax.script;
     uses javax.script.ScriptEngineFactory;
--- a/src/java.se.ee/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.se.ee/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,12 @@
  * questions.
  */
 
+/**
+ * Defines the full API of the Java SE Platform.
+ * <P>
+ * This module requires {@code java.se} and supplements it with modules
+ * that define CORBA and Java EE APIs. These modules are upgradeable.
+ */
 module java.se.ee {
 
     requires public java.se;
--- a/src/java.se/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.se/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,13 @@
  * questions.
  */
 
+/**
+ * Defines the core Java SE API.
+ * <P>
+ * The modules defining
+ * CORBA and Java EE APIs are not required by this module, but they are
+ * required by {@code java.se.ee}.
+ */
 module java.se {
     requires public java.compact3;
     requires public java.datatransfer;
--- a/src/java.security.jgss/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.security.jgss/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,11 @@
  * questions.
  */
 
+/**
+ * Defines the Java binding of the IETF Generic Security Services API (GSS-API).
+ * <P>
+ * This module also contains GSS-API mechanisms including Kerberos v5 and SPNEGO.
+ */
 module java.security.jgss {
     requires java.naming;
     exports javax.security.auth.kerberos;
--- a/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -33,6 +33,7 @@
 import java.security.ProviderException;
 import sun.security.jgss.krb5.Krb5MechFactory;
 import sun.security.jgss.spnego.SpNegoMechFactory;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Defines the Sun JGSS provider.
@@ -99,7 +100,7 @@
 
     public SunProvider() {
         /* We are the Sun JGSS provider */
-        super("SunJGSS", 9.0d, INFO);
+        super("SunJGSS", PROVIDER_VER, INFO);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 import java.security.PrivilegedAction;
 import org.ietf.jgss.Oid;
 import sun.security.action.PutAllAction;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Defines the Sun NativeGSS provider for plugging in the
@@ -120,7 +121,7 @@
 
     public SunNativeProvider() {
         /* We are the Sun NativeGSS provider */
-        super(NAME, 9.0d, INFO);
+        super(NAME, PROVIDER_VER, INFO);
 
         if (MECH_MAP != null) {
             AccessController.doPrivileged(new PutAllAction(this, MECH_MAP));
--- a/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.InvalidParameterException;
 import java.security.ProviderException;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * The SASL provider.
@@ -98,7 +99,7 @@
     }
 
     public Provider() {
-        super("SunSASL", 9.0d, info);
+        super("SunSASL", PROVIDER_VER, info);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.security.sasl/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.security.sasl/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,13 @@
  * questions.
  */
 
+/**
+ * Defines Java support for the IETF Simple Authentication and Security Layer
+ * (SASL).
+ * <P>
+ * This module also contains SASL mechanisms including DIGEST-MD5,
+ * CRAM-MD5, and NTLM.
+ */
 module java.security.sasl {
     requires java.logging;
 
--- a/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java	Mon Aug 22 10:02:10 2016 -0700
@@ -134,7 +134,7 @@
         private static final long serialVersionUID = 2745808869881593918L;
         final static Provider INSTANCE = new NoneProvider();
         private NoneProvider() {
-            super("None", 1.0d, "none");
+            super("None", "1.0", "none");
         }
     }
 
--- a/src/java.smartcardio/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.smartcardio/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Java Smart Card I/O API.
+ */
 module java.smartcardio {
     exports javax.smartcardio;
     provides java.security.Provider with sun.security.smartcardio.SunPCSC;
--- a/src/java.smartcardio/share/classes/sun/security/smartcardio/SunPCSC.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.smartcardio/share/classes/sun/security/smartcardio/SunPCSC.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import java.security.*;
 
 import javax.smartcardio.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Provider object for PC/SC.
@@ -65,7 +66,7 @@
     }
 
     public SunPCSC() {
-        super("SunPCSC", 9.0d, "Sun PC/SC provider");
+        super("SunPCSC", PROVIDER_VER, "Sun PC/SC provider");
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/java.sql.rowset/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.sql.rowset/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the JDBC RowSet API.
+ */
 module java.sql.rowset {
     requires public java.logging;
     requires public java.naming;
--- a/src/java.sql/share/classes/javax/sql/DataSource.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.sql/share/classes/javax/sql/DataSource.java	Mon Aug 22 10:02:10 2016 -0700
@@ -64,7 +64,7 @@
  * <P>
  * A driver that is accessed via a {@code DataSource} object does not
  * register itself with the {@code DriverManager}.  Rather, a
- * {@code DataSource} object is retrieved though a lookup operation
+ * {@code DataSource} object is retrieved through a lookup operation
  * and then used to create a {@code Connection} object.  With a basic
  * implementation, the connection obtained through a {@code DataSource}
  * object is identical to a connection obtained through the
--- a/src/java.sql/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.sql/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the JDBC API.
+ */
 module java.sql {
     requires public java.logging;
     requires public java.xml;
--- a/src/java.transaction/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.transaction/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,12 @@
  * questions.
  */
 
+/**
+ * Defines a subset of the Java Transaction API (JTA) to support CORBA interop.
+ * <P>
+ * The subset consists of RMI exception types which are mapped to CORBA system
+ * exceptions by the 'Java Language to IDL Mapping Specification'.
+ */
 module java.transaction {
     requires public java.rmi;
     exports javax.transaction;
--- a/src/java.xml.crypto/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.xml.crypto/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines an API for XML cryptography.
+ */
 module java.xml.crypto {
     requires public java.xml;
     requires java.logging;
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java	Mon Aug 22 10:02:10 2016 -0700
@@ -28,7 +28,7 @@
  * ===========================================================================
  */
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: XMLDSigRI.java 1400021 2012-10-19 10:16:04Z coheigea $
@@ -59,6 +59,13 @@
         "C14N 1.0, C14N 1.1, Exclusive C14N, Base64, Enveloped, XPath, " +
         "XPath2, XSLT TransformServices)";
 
+    private static final String VER =
+        AccessController.doPrivileged(new PrivilegedAction<>() {
+            public String run() {
+                return System.getProperty("java.specification.version");
+            }
+        });
+
     private static final class ProviderService extends Provider.Service {
 
         ProviderService(Provider p, String type, String algo, String cn) {
@@ -129,7 +136,7 @@
 
     public XMLDSigRI() {
         /* We are the XMLDSig provider */
-        super("XMLDSig", 9.0d, INFO);
+        super("XMLDSig", VER, INFO);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 import sun.security.util.CurveDB;
 import sun.security.util.NamedCurve;
 import sun.security.util.ECParameters;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * Provider class for the Elliptic Curve provider.
@@ -142,7 +143,8 @@
     }
 
     public SunEC() {
-        super("SunEC", 9.0d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
+        super("SunEC", PROVIDER_VER,
+            "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 putEntries(useFullImplementation);
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,6 @@
 /**
  * The handle for an RSA or DSA key using the Microsoft Crypto API.
  *
- * @see DSAPrivateKey
  * @see RSAPrivateKey
  * @see RSAPublicKey
  *
@@ -41,9 +40,35 @@
 {
     private static final long serialVersionUID = -1088859394025049194L;
 
-    // Native handle
-    protected long hCryptProv = 0;
-    protected long hCryptKey = 0;
+    static class NativeHandles {
+        long hCryptProv = 0;
+        long hCryptKey = 0;
+
+        public NativeHandles(long hCryptProv, long hCryptKey) {
+            this.hCryptProv = hCryptProv;
+            this.hCryptKey = hCryptKey;
+        }
+
+        /**
+         * Finalization method
+         */
+        protected void finalize() throws Throwable
+        {
+            try {
+                synchronized(this)
+                {
+                    cleanUp(hCryptProv, hCryptKey);
+                    hCryptProv = 0;
+                    hCryptKey = 0;
+                }
+
+            } finally {
+                super.finalize();
+            }
+        }
+    }
+
+    protected NativeHandles handles;
 
     // Key length
     protected int keyLength = 0;
@@ -51,32 +76,13 @@
     /**
      * Construct a Key object.
      */
-    protected Key(long hCryptProv, long hCryptKey, int keyLength)
+    protected Key(NativeHandles handles, int keyLength)
     {
-        this.hCryptProv = hCryptProv;
-        this.hCryptKey = hCryptKey;
+        this.handles = handles;
         this.keyLength = keyLength;
     }
 
     /**
-     * Finalization method
-     */
-    protected void finalize() throws Throwable
-    {
-        try {
-            synchronized(this)
-            {
-                cleanUp(hCryptProv, hCryptKey);
-                hCryptProv = 0;
-                hCryptKey = 0;
-            }
-
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /**
      * Native method to cleanup the key handle.
      */
     private native static void cleanUp(long hCryptProv, long hCryptKey);
@@ -96,7 +102,7 @@
      */
     public long getHCryptKey()
     {
-        return hCryptKey;
+        return handles.hCryptKey;
     }
 
     /**
@@ -104,12 +110,12 @@
      */
     public long getHCryptProvider()
     {
-        return hCryptProv;
+        return handles.hCryptProv;
     }
 
     /**
      * Returns the standard algorithm name for this key. For
-     * example, "DSA" would indicate that this key is a DSA key.
+     * example, "RSA" would indicate that this key is a RSA key.
      * See Appendix A in the <a href=
      * "../../../guide/security/CryptoSpec.html#AppA">
      * Java Cryptography Architecture API Specification &amp; Reference </a>
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java	Mon Aug 22 10:02:10 2016 -0700
@@ -168,7 +168,7 @@
             }
             certChain = chain;
         }
-    };
+    }
 
     /*
      * An X.509 certificate factory.
@@ -798,7 +798,8 @@
             }
 
             storeWithUniqueAlias(alias, new KeyEntry(alias,
-                    new RSAPrivateKey(hCryptProv, hCryptKey, keyLength),
+                    new RSAPrivateKey(new Key.NativeHandles(hCryptProv,
+                            hCryptKey), keyLength),
                     certChain));
         }
         catch (Throwable e)
@@ -854,7 +855,6 @@
      * Load keys and/or certificates from keystore into Collection.
      *
      * @param name Name of keystore.
-     * @param entries Collection of key/certificate.
      */
     private native void loadKeysOrCertificateChains(String name)
             throws KeyStoreException;
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,8 +41,9 @@
      */
     RSAKeyPair(long hCryptProv, long hCryptKey, int keyLength)
     {
-        privateKey = new RSAPrivateKey(hCryptProv, hCryptKey, keyLength);
-        publicKey = new RSAPublicKey(hCryptProv, hCryptKey, keyLength);
+        Key.NativeHandles handles = new Key.NativeHandles(hCryptProv, hCryptKey);
+        privateKey = new RSAPrivateKey(handles, keyLength);
+        publicKey = new RSAPublicKey(handles, keyLength);
     }
 
     public RSAPrivateKey getPrivate() {
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,15 @@
      */
     RSAPrivateKey(long hCryptProv, long hCryptKey, int keyLength)
     {
-        super(hCryptProv, hCryptKey, keyLength);
+        super(new NativeHandles(hCryptProv, hCryptKey), keyLength);
+    }
+
+    /**
+     * Construct an RSAPrivateKey object.
+     */
+    RSAPrivateKey(NativeHandles handles, int keyLength)
+    {
+        super(handles, keyLength);
     }
 
     /**
@@ -63,8 +71,8 @@
     public String toString()
     {
         return "RSAPrivateKey [size=" + keyLength + " bits, type=" +
-            getKeyType(hCryptKey) + ", container=" +
-            getContainerName(hCryptProv) + "]";
+            getKeyType(handles.hCryptKey) + ", container=" +
+            getContainerName(handles.hCryptProv) + "]";
     }
 
     // This class is not serializable
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,15 @@
      */
     RSAPublicKey(long hCryptProv, long hCryptKey, int keyLength)
     {
-        super(hCryptProv, hCryptKey, keyLength);
+        super(new NativeHandles(hCryptProv, hCryptKey), keyLength);
+    }
+
+    /**
+     * Construct an RSAPublicKey object.
+     */
+    RSAPublicKey(NativeHandles handles, int keyLength)
+    {
+        super(handles, keyLength);
     }
 
     /**
@@ -77,8 +85,8 @@
         StringBuffer sb = new StringBuffer();
 
         sb.append("RSAPublicKey [size=").append(keyLength)
-            .append(" bits, type=").append(getKeyType(hCryptKey))
-            .append(", container=").append(getContainerName(hCryptProv))
+            .append(" bits, type=").append(getKeyType(handles.hCryptKey))
+            .append(", container=").append(getContainerName(handles.hCryptProv))
             .append("]\n  modulus: ").append(getModulus())
             .append("\n  public exponent: ").append(getPublicExponent());
 
@@ -93,7 +101,7 @@
         if (exponent == null) {
 
             try {
-                publicKeyBlob = getPublicKeyBlob(hCryptKey);
+                publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
                 exponent = new BigInteger(1, getExponent(publicKeyBlob));
 
             } catch (KeyException e) {
@@ -112,7 +120,7 @@
         if (modulus == null) {
 
             try {
-                publicKeyBlob = getPublicKeyBlob(hCryptKey);
+                publicKeyBlob = getPublicKeyBlob(handles.hCryptKey);
                 modulus = new BigInteger(1, getModulus(publicKeyBlob));
 
             } catch (KeyException e) {
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java	Mon Aug 22 10:02:10 2016 -0700
@@ -33,6 +33,7 @@
 import java.security.ProviderException;
 import java.util.HashMap;
 import java.util.Arrays;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 /**
  * A Cryptographic Service Provider for the Microsoft Crypto API.
@@ -124,7 +125,7 @@
     }
 
     public SunMSCAPI() {
-        super("SunMSCAPI", 9.0d, INFO);
+        super("SunMSCAPI", PROVIDER_VER, INFO);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Mon Aug 22 10:02:10 2016 -0700
@@ -358,38 +358,50 @@
             BOOL bHasNoPrivateKey = FALSE;
             DWORD dwPublicKeyLength = 0;
 
-            if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL,
-                                                    &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
+            // First, probe it silently
+            if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL,
+                    &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
+                && GetLastError() != NTE_SILENT_CONTEXT)
             {
                 bHasNoPrivateKey = TRUE;
-
-            } else {
-                // Private key is available
-
-                BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
-
-                // Skip certificate if cannot find private key
-                if (bGetUserKey == FALSE)
-                {
-                    if (bCallerFreeProv)
-                        ::CryptReleaseContext(hCryptProv, NULL);
-
-                    continue;
+            }
+            else
+            {
+                if (bCallerFreeProv == TRUE) {
+                    ::CryptReleaseContext(hCryptProv, NULL);
+                    bCallerFreeProv = FALSE;
                 }
 
-                // Set cipher mode to ECB
-                DWORD dwCipherMode = CRYPT_MODE_ECB;
-                ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
+                // Second, acquire the key normally (not silently)
+                if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL,
+                        &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
+                {
+                    bHasNoPrivateKey = TRUE;
+                }
+                else
+                {
+                    // Private key is available
+                    BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
 
+                    // Skip certificate if cannot find private key
+                    if (bGetUserKey == FALSE) {
+                        if (bCallerFreeProv)
+                            ::CryptReleaseContext(hCryptProv, NULL);
+                        continue;
+                    }
 
-                // If the private key is present in smart card, we may not be able to
-                // determine the key length by using the private key handle. However,
-                // since public/private key pairs must have the same length, we could
-                // determine the key length of the private key by using the public key
-                // in the certificate.
-                dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
-                        &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+                    // Set cipher mode to ECB
+                    DWORD dwCipherMode = CRYPT_MODE_ECB;
+                    ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
 
+                    // If the private key is present in smart card, we may not be able to
+                    // determine the key length by using the private key handle. However,
+                    // since public/private key pairs must have the same length, we could
+                    // determine the key length of the private key by using the public key
+                    // in the certificate.
+                    dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                            &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+                }
             }
             PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
 
@@ -398,8 +410,7 @@
             //
             if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
             {
-
-                for (unsigned int i=0; i < pCertChainContext->cChain; i++)
+                for (DWORD i = 0; i < pCertChainContext->cChain; i++)
                 {
                     // Found cert chain
                     PCERT_SIMPLE_CHAIN rgpChain =
@@ -449,6 +460,7 @@
                         // cert collection
                         env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
                     }
+
                     if (bHasNoPrivateKey)
                     {
                         // Generate certificate chain and store into cert chain
@@ -1367,43 +1379,57 @@
     HCRYPTPROV hCryptProv = NULL;
     HCRYPTKEY hKey = NULL;
     DWORD dwKeySpec;
+    BOOL bCallerFreeProv = FALSE;
+    BOOL bRes;
 
     __try
     {
         if (usePrivateKey == JNI_TRUE) {
             // Locate the key container for the certificate's private key
-            if (!(::CryptAcquireCertificatePrivateKey(
-                (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
-                &dwKeySpec, NULL))) {
 
+            // First, probe it silently
+            bRes = ::CryptAcquireCertificatePrivateKey(
+                    (PCCERT_CONTEXT) pCertContext, CRYPT_ACQUIRE_SILENT_FLAG,
+                    NULL, &hCryptProv, &dwKeySpec, &bCallerFreeProv);
+
+            if (bRes == FALSE && GetLastError() != NTE_SILENT_CONTEXT)
+            {
+                ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
+                __leave;
+            }
+
+            if (bCallerFreeProv == TRUE) {
+                ::CryptReleaseContext(hCryptProv, NULL);
+                bCallerFreeProv = FALSE;
+            }
+
+            // Now, do it normally (not silently)
+            if (::CryptAcquireCertificatePrivateKey(
+                    (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
+                    &dwKeySpec, &bCallerFreeProv) == FALSE)
+            {
                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                 __leave;
             }
 
             // Get a handle to the private key
-            if (!(::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))) {
+            if (::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey) == FALSE) {
                 ThrowException(env, KEY_EXCEPTION, GetLastError());
                 __leave;
             }
-
-        } else { // use public key
+        }
+        else // use public key
+        {
+            bCallerFreeProv = TRUE;
 
             //  Acquire a CSP context.
-            if(::CryptAcquireContext(
-               &hCryptProv,
-               "J2SE",
-               NULL,
-               PROV_RSA_FULL,
-               0) == FALSE)
+            if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+                    PROV_RSA_FULL, 0) == FALSE)
             {
                 // If CSP context hasn't been created, create one.
                 //
-                if (::CryptAcquireContext(
-                    &hCryptProv,
-                    "J2SE",
-                    NULL,
-                    PROV_RSA_FULL,
-                    CRYPT_NEWKEYSET) == FALSE)
+                if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+                        PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE)
                 {
                     ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
                     __leave;
@@ -1411,10 +1437,10 @@
             }
 
             // Import the certificate's public key into the key container
-            if (!(::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
-                &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
-                &hKey))) {
-
+            if (::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
+                    &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
+                    &hKey) == FALSE)
+            {
                 ThrowException(env, KEY_EXCEPTION, GetLastError());
                 __leave;
             }
@@ -1425,7 +1451,7 @@
         //--------------------------------------------------------------------
         // Clean up.
 
-        if (hCryptProv)
+        if (bCallerFreeProv == TRUE && hCryptProv != NULL)
             ::CryptReleaseContext(hCryptProv, 0);
     }
 
--- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Key.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Key.java	Mon Aug 22 10:02:10 2016 -0700
@@ -340,25 +340,33 @@
         } else {
             switch (algorithm) {
                 case "RSA":
-                    // XXX better test for RSA CRT keys (single getAttributes() call)
-                    // we need to determine whether this is a CRT key
-                    // see if we can obtain the public exponent
-                    // this should also be readable for sensitive/extractable keys
+                    // In order to decide if this is RSA CRT key, we first query
+                    // and see if all extra CRT attributes are available.
                     CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
                         new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
+                        new CK_ATTRIBUTE(CKA_PRIME_1),
+                        new CK_ATTRIBUTE(CKA_PRIME_2),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_1),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_2),
+                        new CK_ATTRIBUTE(CKA_COEFFICIENT),
                     };
                     boolean crtKey;
                     try {
                         session.token.p11.C_GetAttributeValue
                             (session.id(), keyID, attrs2);
-                        crtKey = (attrs2[0].pValue instanceof byte[]);
+                        crtKey = ((attrs2[0].pValue instanceof byte[]) &&
+                                  (attrs2[1].pValue instanceof byte[]) &&
+                                  (attrs2[2].pValue instanceof byte[]) &&
+                                  (attrs2[3].pValue instanceof byte[]) &&
+                                  (attrs2[4].pValue instanceof byte[]) &&
+                                  (attrs2[5].pValue instanceof byte[])) ;
                     } catch (PKCS11Exception e) {
                         // ignore, assume not available
                         crtKey = false;
                     }
                     if (crtKey) {
                         return new P11RSAPrivateKey
-                                (session, keyID, algorithm, keyLength, attributes);
+                                (session, keyID, algorithm, keyLength, attributes, attrs2);
                     } else {
                         return new P11RSAPrivateNonCRTKey
                                 (session, keyID, algorithm, keyLength, attributes);
@@ -475,8 +483,24 @@
         private BigInteger n, e, d, p, q, pe, qe, coeff;
         private byte[] encoded;
         P11RSAPrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attrs);
+
+            for (CK_ATTRIBUTE a : crtAttrs) {
+                if (a.type == CKA_PUBLIC_EXPONENT) {
+                    e = a.getBigInteger();
+                } else if (a.type == CKA_PRIME_1) {
+                    p = a.getBigInteger();
+                } else if (a.type == CKA_PRIME_2) {
+                    q = a.getBigInteger();
+                } else if (a.type == CKA_EXPONENT_1) {
+                    pe = a.getBigInteger();
+                } else if (a.type == CKA_EXPONENT_2) {
+                    qe = a.getBigInteger();
+                } else if (a.type == CKA_COEFFICIENT) {
+                    coeff = a.getBigInteger();
+                }
+            }
         }
         private synchronized void fetchValues() {
             token.ensureValid();
@@ -485,24 +509,13 @@
             }
             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_MODULUS),
-                new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
                 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
-                new CK_ATTRIBUTE(CKA_PRIME_1),
-                new CK_ATTRIBUTE(CKA_PRIME_2),
-                new CK_ATTRIBUTE(CKA_EXPONENT_1),
-                new CK_ATTRIBUTE(CKA_EXPONENT_2),
-                new CK_ATTRIBUTE(CKA_COEFFICIENT),
             };
             fetchAttributes(attributes);
             n = attributes[0].getBigInteger();
-            e = attributes[1].getBigInteger();
-            d = attributes[2].getBigInteger();
-            p = attributes[3].getBigInteger();
-            q = attributes[4].getBigInteger();
-            pe = attributes[5].getBigInteger();
-            qe = attributes[6].getBigInteger();
-            coeff = attributes[7].getBigInteger();
+            d = attributes[1].getBigInteger();
         }
+
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
@@ -529,7 +542,6 @@
             return n;
         }
         public BigInteger getPublicExponent() {
-            fetchValues();
             return e;
         }
         public BigInteger getPrivateExponent() {
@@ -537,23 +549,18 @@
             return d;
         }
         public BigInteger getPrimeP() {
-            fetchValues();
             return p;
         }
         public BigInteger getPrimeQ() {
-            fetchValues();
             return q;
         }
         public BigInteger getPrimeExponentP() {
-            fetchValues();
             return pe;
         }
         public BigInteger getPrimeExponentQ() {
-            fetchValues();
             return qe;
         }
         public BigInteger getCrtCoefficient() {
-            fetchValues();
             return coeff;
         }
     }
--- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java	Mon Aug 22 10:02:10 2016 -0700
@@ -44,6 +44,7 @@
 
 import sun.security.util.Debug;
 import sun.security.util.ResourcesMgr;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
 
 import sun.security.pkcs11.Secmod.*;
 
@@ -89,7 +90,8 @@
     }
 
     public SunPKCS11() {
-        super("SunPKCS11", 9.0d, "Unconfigured and unusable PKCS11 provider");
+        super("SunPKCS11", PROVIDER_VER,
+            "Unconfigured and unusable PKCS11 provider");
         p11 = null;
         config = null;
         slotID = 0;
@@ -132,7 +134,7 @@
 
     // Used by Secmod
     SunPKCS11(Config c) {
-        super("SunPKCS11-" + c.getName(), 9.0d, c.getDescription());
+        super("SunPKCS11-" + c.getName(), PROVIDER_VER, c.getDescription());
         this.config = c;
 
         if (debug != null) {
@@ -816,6 +818,7 @@
         }
         final TokenPoller poller = new TokenPoller(this);
         Thread t = new Thread(null, poller, "Poller " + getName(), 0, false);
+        t.setContextClassLoader(null);
         t.setDaemon(true);
         t.setPriority(Thread.MIN_PRIORITY);
         t.start();
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -30,6 +30,8 @@
 import java.lang.reflect.Constructor;
 import java.util.*;
 import java.security.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
+
 
 /**
  * OracleUcrypto provider main class.
@@ -196,7 +198,7 @@
     }
 
     public UcryptoProvider() {
-        super("OracleUcrypto", 9.0d, "Provider using Oracle Ucrypto API");
+        super("OracleUcrypto", PROVIDER_VER, "Provider using Oracle Ucrypto API");
 
         AccessController.doPrivileged(new PrivilegedAction<>() {
             public Void run() {
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Mon Aug 22 10:02:10 2016 -0700
@@ -55,7 +55,7 @@
 
     private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
 
-    private static final String DMH = "java/lang/invoke/DirectMethodHandle$Holder";
+    private static final String DIRECT_METHOD_HANDLE = "java/lang/invoke/DirectMethodHandle$Holder";
     private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual";
     private static final String DMH_INVOKE_STATIC = "invokeStatic";
     private static final String DMH_INVOKE_SPECIAL = "invokeSpecial";
@@ -63,6 +63,10 @@
     private static final String DMH_INVOKE_INTERFACE = "invokeInterface";
     private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit";
 
+    private static final String DELEGATING_METHOD_HANDLE = "java/lang/invoke/DelegatingMethodHandle$Holder";
+
+    private static final String BASIC_FORMS_HANDLE = "java/lang/invoke/LambdaForm$Holder";
+
     private static final JavaLangInvokeAccess JLIA
             = SharedSecrets.getJavaLangInvokeAccess();
 
@@ -222,9 +226,18 @@
     @Override
     public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         // Copy all but DMH_ENTRY to out
-        in.transformAndCopy(entry -> entry.path().equals(DMH_ENTRY) ? null : entry, out);
+        in.transformAndCopy(entry -> {
+                // filter out placeholder entries
+                if (entry.path().equals(DIRECT_METHOD_HANDLE_ENTRY) ||
+                    entry.path().equals(DELEGATING_METHOD_HANDLE_ENTRY) ||
+                    entry.path().equals(BASIC_FORMS_HANDLE_ENTRY)) {
+                    return null;
+                } else {
+                    return entry;
+                }
+            }, out);
         speciesTypes.forEach(types -> generateBMHClass(types, out));
-        generateDMHClass(out);
+        generateHolderClasses(out);
         return out.build();
     }
 
@@ -247,7 +260,7 @@
         }
     }
 
-    private void generateDMHClass(ResourcePoolBuilder out) {
+    private void generateHolderClasses(ResourcePoolBuilder out) {
         int count = 0;
         for (List<String> entry : dmhMethods.values()) {
             count += entry.size();
@@ -264,15 +277,30 @@
             }
         }
         try {
-            byte[] bytes =
-                    JLIA.generateDMHClassBytes(DMH, methodTypes, dmhTypes);
-            ResourcePoolEntry ndata = ResourcePoolEntry.create(DMH_ENTRY, bytes);
+            byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
+                    DIRECT_METHOD_HANDLE, methodTypes, dmhTypes);
+            ResourcePoolEntry ndata = ResourcePoolEntry
+                    .create(DIRECT_METHOD_HANDLE_ENTRY, bytes);
+            out.add(ndata);
+
+            bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes(
+                    DELEGATING_METHOD_HANDLE, methodTypes);
+            ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HANDLE_ENTRY, bytes);
+            out.add(ndata);
+
+            bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HANDLE);
+            ndata = ResourcePoolEntry.create(BASIC_FORMS_HANDLE_ENTRY, bytes);
             out.add(ndata);
         } catch (Exception ex) {
             throw new PluginException(ex);
         }
     }
-    private static final String DMH_ENTRY = "/java.base/" + DMH + ".class";
+    private static final String DIRECT_METHOD_HANDLE_ENTRY =
+            "/java.base/" + DIRECT_METHOD_HANDLE + ".class";
+    private static final String DELEGATING_METHOD_HANDLE_ENTRY =
+            "/java.base/" + DELEGATING_METHOD_HANDLE + ".class";
+    private static final String BASIC_FORMS_HANDLE_ENTRY =
+            "/java.base/" + BASIC_FORMS_HANDLE + ".class";
 
     // Convert LL -> LL, L3 -> LLL
     private static String expandSignature(String signature) {
@@ -310,15 +338,19 @@
         assert(parts.length == 2);
         assert(parts[1].length() == 1);
         String parameters = expandSignature(parts[0]);
-        Class<?> rtype = primitiveType(parts[1].charAt(0));
-        Class<?>[] ptypes = new Class<?>[parameters.length()];
-        for (int i = 0; i < ptypes.length; i++) {
-            ptypes[i] = primitiveType(parameters.charAt(i));
+        Class<?> rtype = simpleType(parts[1].charAt(0));
+        if (parameters.isEmpty()) {
+            return MethodType.methodType(rtype);
+        } else {
+            Class<?>[] ptypes = new Class<?>[parameters.length()];
+            for (int i = 0; i < ptypes.length; i++) {
+                ptypes[i] = simpleType(parameters.charAt(i));
+            }
+            return MethodType.methodType(rtype, ptypes);
         }
-        return MethodType.methodType(rtype, ptypes);
     }
 
-    private static Class<?> primitiveType(char c) {
+    private static Class<?> simpleType(char c) {
         switch (c) {
             case 'F':
                 return float.class;
--- a/src/jdk.security.auth/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.security.auth/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  * questions.
  */
 
+/**
+ * Contains the implementation of the javax.security.auth.* interfaces and
+ * various authentication modules.
+ */
 module jdk.security.auth {
     requires public java.naming;
     requires java.security.jgss;
--- a/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/JdkSASL.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/JdkSASL.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,8 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.InvalidParameterException;
 import java.security.ProviderException;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
+
 
 /**
  * The JdkSASL provider class -
@@ -73,7 +75,7 @@
     }
 
     public JdkSASL() {
-        super("JdkSASL", 9.0d, info);
+        super("JdkSASL", PROVIDER_VER, info);
 
         final Provider p = this;
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
--- a/src/jdk.security.jgss/share/classes/module-info.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/src/jdk.security.jgss/share/classes/module-info.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  * questions.
  */
 
+/**
+ * Defines Java extensions to the GSS-API and an implementation of the SASL
+ * GSSAPI mechanism.
+ */
 module jdk.security.jgss {
     requires public java.security.jgss;
     requires java.logging;
--- a/test/Makefile	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/Makefile	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -185,6 +185,9 @@
 ( \
   jtregExitCode=$$? && \
   _summary="$(SUMMARY_TXT)"; \
+  if [ $${jtregExitCode} = 1 ] ; then \
+    jtregExitCode=0; \
+  fi; \
   $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
   $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
   if [ -r "$${_summary}" ] ; then \
--- a/test/ProblemList.txt	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/ProblemList.txt	Mon Aug 22 10:02:10 2016 -0700
@@ -211,6 +211,8 @@
 
 java/rmi/transport/dgcDeadLock/DGCDeadLock.java                 8029360 macosx-all
 
+sun/rmi/runtime/Log/6409194/NoConsoleOutput.java                8164124 windows-all
+
 ############################################################################
 
 # jdk_security
--- a/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,20 @@
     // or throws out TimeoutException.
     private static final int RESERVATION = 3;
     // The maximum time, 5 seconds, to wait for each iteration.
-    private static final int TIME_OUT = 5;
+    private static final int TIME_OUT;
+    static {
+        int timeout = 5;
+        try {
+            double timeoutFactor = Double.parseDouble(
+                    System.getProperty("test.timeout.factor", "1.0"));
+            timeout = (int) (timeout * timeoutFactor);
+        } catch (Exception e) {
+            System.out.println("Warning: " + e);
+        }
+        TIME_OUT = timeout;
+        System.out.println("Timeout for each iteration is "
+                + TIME_OUT + " seconds");
+    }
 
     private static Deque<byte []> eatupMemory() throws Exception {
         dumpMemoryStats("Before memory allocation");
--- a/test/com/sun/net/ssl/SSLSecurity/ProviderTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/com/sun/net/ssl/SSLSecurity/ProviderTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4667976
+ * @bug 4667976 8130181
  * @modules java.base/com.sun.net.ssl
  * @compile JavaxSSLContextImpl.java ComSSLContextImpl.java
  *      JavaxTrustManagerFactoryImpl.java ComTrustManagerFactoryImpl.java
@@ -85,7 +85,7 @@
 
     public MyProvider()
     {
-        super("BRAD", 1.0, info);
+        super("BRAD", "1.0", info);
 
         AccessController.doPrivileged(new java.security.PrivilegedAction() {
             public Object run() {
--- a/test/java/lang/StackWalker/VerifyStackTrace.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/lang/StackWalker/VerifyStackTrace.java	Mon Aug 22 10:02:10 2016 -0700
@@ -205,8 +205,12 @@
                     .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/")
                     .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
                     .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
+                    // DMHs may or may not be pre-generated, making frames differ
                     .replaceAll("DirectMethodHandle\\$Holder", "LambdaForm\\$DMH")
                     .replaceAll("DMH\\.invoke", "DMH/xxxxxxxx.invoke")
+                    // invoke frames may or may not have basic method type
+                    // information encoded for diagnostic purposes
+                    .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z]+_[A-Z]", "xx.invoke$1")
                     .replaceAll("\\$[0-9]+", "\\$??");
         } else {
             return produced;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/CountedLoopIterationCountsTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8164102
+ * @run main/othervm -ea -esa test.java.lang.invoke.CountedLoopIterationCountsTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class CountedLoopIterationCountsTest {
+
+    public static void main(String[] args) throws Throwable {
+        run(1, -10, 0);
+        run(1, 0, 0);
+        run(Integer.MAX_VALUE - 1, Integer.MIN_VALUE + 10, 0);
+        run(Integer.MIN_VALUE, Integer.MIN_VALUE + 4, 4);
+        run(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, 1);
+        run(Integer.MAX_VALUE - 1, 0, 0);
+        run(Integer.MAX_VALUE - 1, 10, 0);
+        run(Integer.MAX_VALUE - 1, -10, 0);
+        run(Integer.MAX_VALUE, Integer.MIN_VALUE + 10, 0);
+        run(Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 1);
+        run(Integer.MAX_VALUE, Integer.MAX_VALUE, 0);
+
+        if (failed) {
+            throw new AssertionError("one or more tests failed");
+        }
+    }
+
+    static boolean failed = false;
+
+    private static void run(int start, int end, int expectedIterations) throws Throwable {
+        System.out.println("run from " + start + " to " + end);
+        MethodHandle loop = MethodHandles.countedLoop(
+                MethodHandles.constant(int.class, start), // iterate from given start (inclusive) ...
+                MethodHandles.constant(int.class, end),   // ... to given end (exclusive)
+                MH_m1,                                    // initialise loop variable to -1
+                MH_step);                                 // increment loop counter by one in each iteration
+        // The loop variable's value, and hence the loop result, will be "number of iterations" minus one.
+        int r = (int) loop.invoke();
+        if (r + 1 != expectedIterations) {
+            System.out.println("expected " + expectedIterations + " iterations, but got " + r);
+            failed = true;
+        }
+    }
+
+    static int step(int counter, int stepCount) {
+        return stepCount + 1;
+    }
+
+    static final MethodHandle MH_m1;
+    static final MethodHandle MH_step;
+    static {
+        try {
+            MH_m1 = MethodHandles.constant(int.class, -1);
+            MH_step = MethodHandles.lookup().findStatic(CountedLoopIterationCountsTest.class, "step",
+                    MethodType.methodType(int.class, int.class, int.class));
+        } catch (Throwable t) {
+            throw new ExceptionInInitializerError(t);
+        }
+    }
+
+}
--- a/test/java/lang/reflect/ClassLoaderValue/Driver.java	Mon Aug 22 10:35:16 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8152115
- * @summary functional and concurrency test for ClassLoaderValue
- * @build java.base/java.lang.reflect.ClassLoaderValueTest
- * @run main Driver
- */
-public class Driver {
-    public static void main(String[] args) throws Exception {
-        java.lang.reflect.ClassLoaderValueTest.main(args);
-    }
-}
--- a/test/java/lang/reflect/ClassLoaderValue/java.base/java/lang/reflect/ClassLoaderValueTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang.reflect;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Functional and concurrency test for ClassLoaderValue
- *
- * @author Peter Levart
- */
-public class ClassLoaderValueTest {
-
-    @SuppressWarnings("unchecked")
-    public static void main(String[] args) throws Exception {
-
-        ClassLoaderValue[] clvs = {new ClassLoaderValue<>(),
-                                   new ClassLoaderValue<>()};
-
-        ClassLoader[] lds = {ClassLoader.getSystemClassLoader(),
-                             ClassLoader.getPlatformClassLoader(),
-                             null /* bootstrap class loader */};
-
-        Integer[] keys = new Integer[32];
-        for (int i = 0; i < keys.length; i++) {
-            keys[i] = i + 128;
-        }
-
-        try (AutoCloseable cleanup = () -> {
-            for (ClassLoaderValue<Integer> clv : clvs) {
-                for (ClassLoader ld : lds) {
-                    clv.removeAll(ld);
-                }
-            }
-        }) {
-            // 1st just one sequential pass of single-threaded validation
-            // which is easier to debug if it fails...
-            for (ClassLoaderValue<Integer> clv : clvs) {
-                for (ClassLoader ld : lds) {
-                    writeValidateOps(clv, ld, keys);
-                }
-            }
-            for (ClassLoaderValue<Integer> clv : clvs) {
-                for (ClassLoader ld : lds) {
-                    readValidateOps(clv, ld, keys);
-                }
-            }
-
-            // 2nd the same in concurrent setting that also validates
-            // failure-isolation between threads and data-isolation between
-            // regions - (ClassLoader, ClassLoaderValue) pairs - of the storage
-            testConcurrentIsolation(clvs, lds, keys, TimeUnit.SECONDS.toMillis(3));
-        }
-    }
-
-    static void writeValidateOps(ClassLoaderValue<Integer> clv,
-                                 ClassLoader ld,
-                                 Object[] keys) {
-        for (int i = 0; i < keys.length; i++) {
-            Object k = keys[i];
-            Integer v1 = i;
-            Integer v2 = i + 333;
-            Integer pv;
-            boolean success;
-
-            pv = clv.sub(k).putIfAbsent(ld, v1);
-            assertEquals(pv, null);
-            assertEquals(clv.sub(k).get(ld), v1);
-
-            pv = clv.sub(k).putIfAbsent(ld, v2);
-            assertEquals(pv, v1);
-            assertEquals(clv.sub(k).get(ld), v1);
-
-            success = clv.sub(k).remove(ld, v2);
-            assertEquals(success, false);
-            assertEquals(clv.sub(k).get(ld), v1);
-
-            success = clv.sub(k).remove(ld, v1);
-            assertEquals(success, true);
-            assertEquals(clv.sub(k).get(ld), null);
-
-            pv = clv.sub(k).putIfAbsent(ld, v2);
-            assertEquals(pv, null);
-            assertEquals(clv.sub(k).get(ld), v2);
-
-            pv = clv.sub(k).computeIfAbsent(ld, (_ld, _clv) -> v1);
-            assertEquals(pv, v2);
-            assertEquals(clv.sub(k).get(ld), v2);
-
-            success = clv.sub(k).remove(ld, v1);
-            assertEquals(success, false);
-            assertEquals(clv.sub(k).get(ld), v2);
-
-            success = clv.sub(k).remove(ld, v2);
-            assertEquals(success, true);
-            assertEquals(clv.sub(k).get(ld), null);
-
-            pv = clv.sub(k).computeIfAbsent(ld, (_ld, clv_k) -> {
-                try {
-                    // nested get for same key should throw
-                    clv_k.get(_ld);
-                    throw new AssertionError("Unexpected code path");
-                } catch (IllegalStateException e) {
-                    // expected
-                }
-                try {
-                    // nested putIfAbsent for same key should throw
-                    clv_k.putIfAbsent(_ld, v1);
-                    throw new AssertionError("Unexpected code path");
-                } catch (IllegalStateException e) {
-                    // expected
-                }
-                // nested remove for for same key and any value (even null)
-                // should return false
-                assertEquals(clv_k.remove(_ld, null), false);
-                assertEquals(clv_k.remove(_ld, v1), false);
-                assertEquals(clv_k.remove(_ld, v2), false);
-                try {
-                    // nested computeIfAbsent for same key should throw
-                    clv_k.computeIfAbsent(_ld, (__ld, _clv_k) -> v1);
-                    throw new AssertionError("Unexpected code path");
-                } catch (IllegalStateException e) {
-                    // expected
-                }
-                // if everything above has been handled, we should succeed...
-                return v2;
-            });
-            // ... and the result should be reflected in the CLV
-            assertEquals(pv, v2);
-            assertEquals(clv.sub(k).get(ld), v2);
-
-            success = clv.sub(k).remove(ld, v2);
-            assertEquals(success, true);
-            assertEquals(clv.sub(k).get(ld), null);
-
-            try {
-                clv.sub(k).computeIfAbsent(ld, (_ld, clv_k) -> {
-                    throw new UnsupportedOperationException();
-                });
-                throw new AssertionError("Unexpected code path");
-            } catch (UnsupportedOperationException e) {
-                // expected
-            }
-            assertEquals(clv.sub(k).get(ld), null);
-        }
-    }
-
-    static void readValidateOps(ClassLoaderValue<Integer> clv,
-                                ClassLoader ld,
-                                Object[] keys) {
-        for (int i = 0; i < keys.length; i++) {
-            Object k = keys[i];
-            Integer v1 = i;
-            Integer v2 = i + 333;
-            Integer rv = clv.sub(k).get(ld);
-            if (!(rv == null || rv.equals(v1) || rv.equals(v2))) {
-                throw new AssertionError("Unexpected value: " + rv +
-                                         ", expected one of: null, " + v1 + ", " + v2);
-            }
-        }
-    }
-
-    static void testConcurrentIsolation(ClassLoaderValue<Integer>[] clvs,
-                                        ClassLoader[] lds,
-                                        Object[] keys,
-                                        long millisRuntime) {
-        ExecutorService exe = Executors.newCachedThreadPool();
-        List<Future<?>> futures = new ArrayList<>();
-        AtomicBoolean stop = new AtomicBoolean();
-        for (ClassLoaderValue<Integer> clv : clvs) {
-            for (ClassLoader ld : lds) {
-                // submit a task that exercises a mix of modifying
-                // and reading-validating operations in an isolated
-                // part of the storage. If isolation is violated,
-                // validation operations are expected to fail.
-                futures.add(exe.submit(() -> {
-                    do {
-                        writeValidateOps(clv, ld, keys);
-                    } while (!stop.get());
-                }));
-                // submit a task that just reads from the same part of
-                // the storage as above task. It should not disturb
-                // above task in any way and this task should never
-                // exhibit any failure although above task produces
-                // regular failures during lazy computation
-                futures.add(exe.submit(() -> {
-                    do {
-                        readValidateOps(clv, ld, keys);
-                    } while (!stop.get());
-                }));
-            }
-        }
-        // wait for some time
-        try {
-            Thread.sleep(millisRuntime);
-        } catch (InterruptedException e) {
-            throw new AssertionError(e);
-        }
-        // stop tasks
-        stop.set(true);
-        // collect results
-        AssertionError error = null;
-        for (Future<?> future : futures) {
-            try {
-                future.get();
-            } catch (InterruptedException | ExecutionException e) {
-                if (error == null) error = new AssertionError("Failure");
-                error.addSuppressed(e);
-            }
-        }
-        exe.shutdown();
-        if (error != null) throw error;
-    }
-
-    static void assertEquals(Object actual, Object expected) {
-        if (!Objects.equals(actual, expected)) {
-            throw new AssertionError("Expected: " + expected + ", actual: " + actual);
-        }
-    }
-}
--- a/test/java/nio/file/Files/probeContentType/Basic.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/nio/file/Files/probeContentType/Basic.java	Mon Aug 22 10:02:10 2016 -0700
@@ -184,7 +184,7 @@
             "webm"
         };
         String[][] expectedTypes = new String[][] {
-            {"audio/aac", "audio/x-aac"},
+            {"audio/aac", "audio/x-aac", "audio/vnd.dlna.adts"},
             {"audio/flac", "audio/x-flac"},
             {"image/jpeg"},
             {"audio/mpeg"},
--- a/test/java/security/KeyFactory/Failover.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/KeyFactory/Failover.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4894125 7054918
+ * @bug 4894125 7054918 8130181
  * @library ../testlibrary
  * @summary test that failover for KeyFactory works
  * @author Andreas Sterbenz
@@ -96,14 +96,14 @@
 
     private static class ProviderPass extends Provider {
         ProviderPass() {
-            super("Pass", 1.0d, "Pass");
+            super("Pass", "1.0", "Pass");
             put("KeyFactory.FOO" , "Failover$KeyFactoryPass");
         }
     }
 
     private static class ProviderFail extends Provider {
         ProviderFail() {
-            super("Fail", 1.0d, "Fail");
+            super("Fail", "1.0", "Fail");
             put("KeyFactory.FOO" , "Failover$KeyFactoryFail");
             put("KeyFactory.DSA" , "Failover$KeyFactoryFail");
         }
--- a/test/java/security/KeyPairGenerator/Failover.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/KeyPairGenerator/Failover.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4894125 7054918
+ * @bug 4894125 7054918 8130181
  * @library ../testlibrary
  * @summary test that failover for KeyPairGenerator works
  * @author Andreas Sterbenz
@@ -110,14 +110,14 @@
 
     private static class ProviderPass extends Provider {
         ProviderPass() {
-            super("Pass", 1.0d, "Pass");
+            super("Pass", "1.0", "Pass");
             put("KeyPairGenerator.FOO" , "Failover$KeyPairGeneratorPass");
         }
     }
 
     private static class ProviderFail extends Provider {
         ProviderFail() {
-            super("Fail", 1.0d, "Fail");
+            super("Fail", "1.0", "Fail");
             put("KeyPairGenerator.FOO" , "Failover$KeyPairGeneratorFail");
             put("KeyPairGenerator.DSA" , "Failover$KeyPairGeneratorFail");
             put("KeyPairGenerator.RSA" , "Failover$KeyPairGeneratorFail");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/KeyPairGenerator/FinalizeHalf.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8163896
+ * @summary Finalizing one key of a KeyPair invalidates the other key
+ */
+
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.ProviderException;
+import java.security.Security;
+import java.util.function.Consumer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FinalizeHalf {
+
+    static int failures = 0;
+
+    public static void main(String[] args) throws Throwable {
+        List<Consumer<Key>> methods = new ArrayList<>();
+        methods.add((Key k) -> k.getEncoded());
+        methods.add((Key k) -> k.toString());
+
+        for (String algo : new String[] {"DiffieHellman", "DSA", "RSA"}) {
+            for (Provider provider : Security.getProviders()) {
+                for (boolean priv : new boolean[] {true, false}) {
+                    for (Consumer<Key> method : methods) {
+                        test(algo, provider, priv, method);
+                    }
+                }
+            }
+        }
+
+        if (failures > 0) {
+            throw new RuntimeException(failures + " test(s) failed.");
+        }
+    }
+
+    static void test(String algo, Provider provider, boolean priv,
+            Consumer<Key> method) throws Exception {
+        KeyPairGenerator generator;
+        try {
+            generator = KeyPairGenerator.getInstance(algo, provider);
+        } catch (NoSuchAlgorithmException nsae) {
+            return;
+        }
+
+        System.out.println("Checking " + provider.getName() + ", " + algo);
+
+        KeyPair pair = generator.generateKeyPair();
+        Key key = priv ? pair.getPrivate() : pair.getPublic();
+
+        pair = null;
+        for (int i = 0; i < 32; ++i) {
+            System.gc();
+        }
+
+        try {
+            method.accept(key);
+        } catch (ProviderException pe) {
+            failures++;
+        }
+    }
+}
--- a/test/java/security/KeyStore/EntryMethods.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/KeyStore/EntryMethods.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test 1.5, 03/06/24
- * @bug 4850376 8130850
+ * @bug 4850376 8130850 8130181
  * @summary Provide generic storage KeyStore storage facilities
  */
 
@@ -65,7 +65,7 @@
     public static class FooEntry implements KeyStore.Entry { }
 
     public EntryMethods() throws Exception {
-        super("EntryMethods", 0.0, "EntryMethods");
+        super("EntryMethods", "0.0", "EntryMethods");
 
         pre15fis = new FileInputStream
             (System.getProperty("test.src") + "/EntryMethods.pre15.keystore");
--- a/test/java/security/KeyStore/KeyStoreBuilder.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/KeyStore/KeyStoreBuilder.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4938922 4961104 5071293 6236533
+ * @bug 4938922 4961104 5071293 6236533 8130181
  * @summary verify that the KeyStore.Builder API works
  * @author Andreas Sterbenz
  */
@@ -219,7 +219,7 @@
 
     private static class MyProvider extends Provider {
         MyProvider() {
-            super("My", 1.0d, null);
+            super("My", "1.0", null);
             put("KeyStore.My", "KeyStoreBuilder$MyKeyStoreSpi");
         }
     }
--- a/test/java/security/Policy/GetInstance/GetInstanceProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Policy/GetInstance/GetInstanceProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 
     public GetInstanceProvider() {
         super("GetInstanceProvider",
-                1,
+                "1",
                 "GetInstanceProvider: Policy.GetInstancePolicySpi");
 
         AccessController.doPrivileged(new PrivilegedAction() {
--- a/test/java/security/Provider/CaseSensitiveServices.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/CaseSensitiveServices.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5097015
+ * @bug 5097015 8130181
  * @summary make sure we correctly treat Provider string entries as case insensitive
  * @author Andreas Sterbenz
  */
@@ -33,7 +33,7 @@
 
 public class CaseSensitiveServices extends Provider {
     CaseSensitiveServices() {
-        super("Foo", 1.0d, null);
+        super("Foo", "1.0", null);
         put("MessageDigest.Foo", "com.Foo");
         put("mESSAGEdIGEST.fOO xYz", "aBc");
         put("ALg.aliaS.MESSAGEdigest.Fu", "FoO");
--- a/test/java/security/Provider/ChangeProviders.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/ChangeProviders.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4856968 7054918
+ * @bug 4856968 7054918 8130181
  * @library ../testlibrary
  * @summary make sure add/insert/removeProvider() work correctly
  * @author Andreas Sterbenz
@@ -36,7 +36,7 @@
 public class ChangeProviders extends Provider {
 
     private ChangeProviders() {
-        super("Foo", 47.23d, "none");
+        super("Foo", "47.23", "none");
     }
 
     private static int plen() {
--- a/test/java/security/Provider/Equals.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/Equals.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4918769
+ * @bug 4918769 8130181
  * @summary make sure Provider.equals() behaves as expected with the id attributes
  * @author Andreas Sterbenz
  */
@@ -33,9 +33,9 @@
 public class Equals {
 
     public static void main(String[] args) throws Exception {
-        Provider p1 = new P1("foo", 1.0d, "foo");
-        Provider p1b = new P1("foo", 1.0d, "foo");
-        Provider p2 = new P2("foo", 1.0d, "foo");
+        Provider p1 = new P1("foo", "1.0", "foo");
+        Provider p1b = new P1("foo", "1.0", "foo");
+        Provider p2 = new P2("foo", "1.0", "foo");
         System.out.println(p1.entrySet());
         if (p1.equals(p2)) {
             throw new Exception("Objects are equal");
@@ -55,13 +55,13 @@
     }
 
     private static class P1 extends Provider {
-        P1(String name, double version, String info) {
+        P1(String name, String version, String info) {
             super(name, version, info);
         }
     }
 
     private static class P2 extends Provider {
-        P2(String name, double version, String info) {
+        P2(String name, String version, String info) {
             super(name, version, info);
         }
     }
--- a/test/java/security/Provider/GetInstance.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/GetInstance.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4856968 7054918
+ * @bug 4856968 7054918 8130181
  * @library ../testlibrary
  * @summary make sure getInstance() works correctly, including failover
  *   and delayed provider selection for Signatures
@@ -137,7 +137,7 @@
 
     public static class FooProvider extends Provider {
         FooProvider() {
-            super("foo", 1.0d, "none");
+            super("foo", "1.0", "none");
             put("MessageDigest.foo", "GetInstance$FooDigest");
             put("CertStore.foo",     "GetInstance$FooStore");
             put("Signature.foo",     "GetInstance$FooSignatureSpi");
@@ -151,7 +151,7 @@
 
     public static class BarProvider extends Provider {
         BarProvider() {
-            super("bar", 1.0d, "none");
+            super("bar", "1.0", "none");
             // all entries invalid for failover
             put("MessageDigest.bar", "GetInstance$FooKey");
             put("Signature.bar",     "GetInstance$FooKey");
@@ -164,7 +164,7 @@
 
     public static class BazProvider extends Provider {
         BazProvider() {
-            super("baz", 1.0d, "none");
+            super("baz", "1.0", "none");
             put("MessageDigest.bar", "GetInstance$FooDigest");
             put("CertStore.bar",     "GetInstance$FooStore");
             put("Signature.bar",     "GetInstance$FooSignatureSpi");
--- a/test/java/security/Provider/ProviderInfoCheck.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/ProviderInfoCheck.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6455351
+ * @bug 6455351 8130181
  * @summary Make sure the Provider.info entries have the correct values
  * after going through serialization/deserialization.
  * @author Valerie Peng
@@ -68,18 +68,17 @@
         if (!p.getClass().getName().equalsIgnoreCase(value)) {
             throw new Exception("Test Failed: incorrect className!");
         }
-        double dvalue =
-            Double.parseDouble((String) p.get("Provider.id version"));
-        if ((SampleProvider.VERSION != dvalue) ||
-            p.getVersion() != dvalue) {
-            throw new Exception("Test Failed: incorrect version!");
+        value = (String) p.get("Provider.id version");
+        if (!SampleProvider.VERSION.equalsIgnoreCase(value) ||
+            p.getVersionStr() != value) {
+            throw new Exception("Test Failed: incorrect versionStr!");
         }
         System.out.println("Test Passed");
     }
 
     private static class SampleProvider extends Provider {
         static String NAME = "Sample";
-        static double VERSION = 1.1d;
+        static String VERSION = "1.1";
         static String INFO = "Good for nothing";
         SampleProvider() {
             super(NAME, VERSION, INFO);
--- a/test/java/security/Provider/RemoveProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/RemoveProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4190873 7054918
+ * @bug 4190873 7054918 8130181
  * @library ../testlibrary
  * @summary Make sure provider instance can be removed from list of registered
  * providers, and "entrySet", "keySet", and "values" methods don't loop
@@ -46,11 +46,11 @@
     public static void main0(String[] args) throws Exception {
 
         // Add provider 1
-        Provider p1 = new MyProvider("name1",1,"");
+        Provider p1 = new MyProvider("name1","1","");
         Security.addProvider(p1);
 
         // Add provider 2
-        Provider p2 = new MyProvider("name2",1,"");
+        Provider p2 = new MyProvider("name2","1","");
         Security.addProvider(p2);
 
         // List all providers
@@ -183,7 +183,7 @@
 }
 
 class MyProvider extends Provider {
-    public MyProvider(String name, double version, String info) {
+    public MyProvider(String name, String version, String info) {
         super(name, version, info);
         put("Signature", name+".signature");
         put("Digest", name+".digest");
--- a/test/java/security/Provider/SupportsParameter.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/SupportsParameter.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4911081
+ * @bug 4911081 8130181
  * @summary verify that Provider.Service.supportsParameter() works
  * @author Andreas Sterbenz
  */
@@ -104,7 +104,7 @@
 
     private static class MyProvider extends Provider {
         MyProvider() {
-            super("MyProvider", 1.0d, "MyProvider");
+            super("MyProvider", "1.0", "MyProvider");
 
             put("Signature.DSA0", "foo.DSA0");
 
--- a/test/java/security/Provider/TestSecurityProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/TestSecurityProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 public final class TestSecurityProvider extends Provider {
 
     public TestSecurityProvider() {
-        super("TEST", 1.0d, "Test Security provider");
+        super("TEST", "1.0", "Test Security provider");
         System.out.println(String.format("TEST Security provider loaded"
                 + " successfully : %s", this.toString()));
     }
@@ -38,7 +38,7 @@
     @Override
     public String toString() {
         return "TestSecurityProvider [getName()=" + getName()
-                + ", getVersion()=" + getVersion() + ", getInfo()="
+                + ", getVersion()=" + getVersionStr() + ", getInfo()="
                 + getInfo() + ", toString()=" + super.toString() + "]";
     }
 
--- a/test/java/security/Provider/Turkish.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Provider/Turkish.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6220064 7054918
+ * @bug 6220064 7054918 8130181
  * @summary make sure everything works ok in the Turkish local (dotted/dotless i problem)
  * @author Andreas Sterbenz
  */
@@ -107,7 +107,7 @@
 
     private static class TProvider extends Provider {
         TProvider(String name) {
-            super(name, 1.0d, null);
+            super(name, "1.0", null);
             put("Signature.MD5withRSA", "com.foo.Sig");
             put("Alg.Alias.Signature.MD5RSA", "MD5withRSA");
             put("sIGNATURE.shaWITHrsa", "com.foo.Sig");
--- a/test/java/security/SecureClassLoader/DefineClass.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/SecureClassLoader/DefineClass.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
 
 /*
  * @test
- * @bug 6826789 8131486
+ * @bug 6826789 8131486 8130181
  * @summary Make sure equivalent ProtectionDomains are granted the same
  *          permissions when the CodeSource URLs are different but resolve
  *          to the same ip address after name service resolution.
@@ -194,7 +194,7 @@
 
     private static class TestProvider extends Provider {
         TestProvider() {
-            super("Test8131486", 0.0, "For testing only");
+            super("Test8131486", "0.0", "For testing only");
             putService(new Provider.Service(this, "KeyStore", "Test8131486",
                        "DefineClass$TestKeyStore", null, null));
         }
--- a/test/java/security/Security/AddProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Security/AddProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8001319
+ * @bug 8001319 8130181
  * @summary check that SecurityPermission insertProvider permission is enforced
  *          correctly
  * @run main/othervm/policy=AddProvider.policy.1 AddProvider 1
@@ -53,7 +53,7 @@
 
     private static class TestProvider extends Provider {
         TestProvider(String name) {
-            super(name, 0.0, "Not for use in production systems!");
+            super(name, "0.0", "Not for use in production systems!");
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/Security/ClassLoader/DeprivilegedModuleLoaderTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import javax.security.auth.kerberos.KeyTab;
+import javax.xml.crypto.KeySelectorException;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import com.sun.security.auth.callback.TextCallbackHandler;
+import com.sun.security.jgss.AuthorizationDataEntry;
+
+/*
+ * @test
+ * @bug 8159964
+ * @summary Classes from deprivileged modules should get loaded through
+ *          Platform Classloader.
+ * @run main DeprivilegedModuleLoaderTest
+ */
+public class DeprivilegedModuleLoaderTest {
+
+    public static void main(String[] args) {
+
+        boolean pass = true;
+        List<Class<?>> classes = getDeprivilegedClasses();
+        for (Class<?> cls : classes) {
+            try {
+                pass &= testPlatformClassLoader(cls);
+            } catch (Exception exc) {
+                exc.printStackTrace(System.out);
+                pass = false;
+            }
+        }
+
+        if (!pass) {
+            throw new RuntimeException("Atleast one test failed.");
+        }
+    }
+
+    private static List<Class<?>> getDeprivilegedClasses() {
+
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+        // Test from java.xml.crypto/javax/xml/crypto/dsig package
+        classes.add(XMLSignatureFactory.class);
+        // Test from java.xml.crypto/javax/xml/crypto package
+        classes.add(KeySelectorException.class);
+        // Test From java.security.jgss/javax/security/auth/kerberos package
+        classes.add(KeyTab.class);
+        // Test from jdk.security.jgss/com/sun/security/jgss package
+        classes.add(AuthorizationDataEntry.class);
+        // Test from jdk.security.auth/com/sun/security/auth/callback package
+        classes.add(TextCallbackHandler.class);
+        return classes;
+    }
+
+    private static boolean testPlatformClassLoader(Class<?> cls) {
+
+        ClassLoader loader = cls.getClassLoader();
+        if (loader == null) {
+            throw new RuntimeException(String.format(
+                    "Loaded through Bootstrap Classloader: '%s'", cls));
+        } else if (!loader.toString().contains("PlatformClassLoader")) {
+            throw new RuntimeException(String.format(
+                    "Not loaded through Platform ClassLoader: '%s'", cls));
+        }
+        System.out.println(String.format(
+                "Pass: '%s' get loaded through PlatformClassLoader", cls));
+        return true;
+    }
+}
--- a/test/java/security/Security/ClassLoaderDeadlock/provider/HashProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Security/ClassLoaderDeadlock/provider/HashProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 
 public final class HashProvider extends Provider {
     public HashProvider() {
-        super("HashProvider", 1.0d, "");
+        super("HashProvider", "1.0", "");
         // register all algorithms from the following providers into this provider
         // the security framework will try to load them via the classloader of this provider
         addAlgorithms("SunRsaSign");
--- a/test/java/security/Security/SynchronizedAccess.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Security/SynchronizedAccess.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4162583 7054918
+ * @bug 4162583 7054918 8130181
  * @library ../testlibrary
  * @summary Make sure Provider api implementations are synchronized properly
  */
@@ -61,7 +61,7 @@
     public void run() {
         Provider[] provs = new Provider[10];
         for (int i=0; i < provs.length; i++)
-            provs[i] = new MyProvider("name"+i, 1, "test");
+            provs[i] = new MyProvider("name"+i, "1", "test");
 
         int rounds = 20;
         while (rounds-- > 0) {
@@ -86,7 +86,7 @@
 }
 
 class MyProvider extends Provider {
-    public MyProvider(String name, double version, String info) {
+    public MyProvider(String name, String version, String info) {
         super(name, version, info);
         put("Signature.sigalg", "sigimpl");
     }
--- a/test/java/security/Security/removing/RemoveProviderByIdentity.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Security/removing/RemoveProviderByIdentity.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4208414
+ * @bug 4208414 8130181
  * @summary Providers should be removed "by-identity" - not "by-value"
  */
 
@@ -34,7 +34,7 @@
     public static void main(String[] args) throws Exception {
         String PROVIDER_NAME = "myprovider";
 
-        Security.addProvider(new MyProvider(PROVIDER_NAME, 1, "test"));
+        Security.addProvider(new MyProvider(PROVIDER_NAME, "1", "test"));
         if (Security.getProvider(PROVIDER_NAME) == null)
             throw new Exception("provider not registered");
 
@@ -45,7 +45,7 @@
 }
 
 class MyProvider extends Provider {
-    public MyProvider(String name, double version, String info) {
+    public MyProvider(String name, String version, String info) {
         super(name, version, info);
         put("Signature.sigalg", "sigimpl");
     }
--- a/test/java/security/Signature/SignatureGetAlgorithm.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/Signature/SignatureGetAlgorithm.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 
 /*
  * @test
- * @bug 8014620
+ * @bug 8014620 8130181
  * @summary Signature.getAlgorithm return null in special case
  * @run main/othervm SignatureGetAlgorithm
  * @author youdwei
@@ -49,7 +49,7 @@
 
     public static class TestProvider extends Provider {
         TestProvider() {
-            super("testSignatureGetAlgorithm", 1.0, "test Signatures");
+            super("testSignatureGetAlgorithm", "1.0", "test Signatures");
             put("Signature.MySignatureAlg",
                 "SignatureGetAlgorithm$MySignatureAlg");
         }
--- a/test/java/security/cert/CertPathBuilder/StubProvider.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/cert/CertPathBuilder/StubProvider.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,14 +23,14 @@
 
 /*
  *
- * @bug 4408997
+ * @bug 4408997 8130181
  * Used by GetInstance test.
  */
 import java.security.Provider;
 
 public class StubProvider extends Provider {
     public StubProvider() {
-        super( "StubProvider", 1.1, "No Info");
+        super( "StubProvider", "1.1", "No Info");
         put("CertPathBuilder.PKIX", "StubProviderImpl");
     }
 }
--- a/test/java/security/testlibrary/SimpleOCSPServer.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/security/testlibrary/SimpleOCSPServer.java	Mon Aug 22 10:02:10 2016 -0700
@@ -64,6 +64,8 @@
     private static final SimpleDateFormat utcDateFmt =
             new SimpleDateFormat("MMM dd yyyy, HH:mm:ss z");
 
+    static final int FREE_PORT = 0;
+
     // CertStatus values
     public static enum CertStatus {
         CERT_STATUS_GOOD,
@@ -88,7 +90,8 @@
     private volatile boolean started = false;
     private volatile boolean serverReady = false;
     private volatile boolean receivedShutdown = false;
-    private long delayMsec = 0;
+    private volatile boolean acceptConnections = true;
+    private volatile long delayMsec = 0;
 
     // Fields used in the generation of responses
     private long nextUpdateInterval = -1;
@@ -116,7 +119,7 @@
      */
     public SimpleOCSPServer(KeyStore ks, String password, String issuerAlias,
             String signerAlias) throws GeneralSecurityException, IOException {
-        this(null, 0, ks, password, issuerAlias, signerAlias);
+        this(null, FREE_PORT, ks, password, issuerAlias, signerAlias);
     }
 
     /**
@@ -230,6 +233,15 @@
                     while (!receivedShutdown) {
                         try {
                             Socket newConnection = servSocket.accept();
+                            if (!acceptConnections) {
+                                try {
+                                    log("Reject connection");
+                                    newConnection.close();
+                                } catch (IOException e) {
+                                    // ignore
+                                }
+                                continue;
+                            }
                             threadPool.submit(new OcspHandler(newConnection));
                         } catch (SocketTimeoutException timeout) {
                             // Nothing to do here.  If receivedShutdown
@@ -257,6 +269,23 @@
     }
 
     /**
+     * Make the OCSP server reject incoming connections.
+     */
+    public synchronized void rejectConnections() {
+        log("Reject OCSP connections");
+        acceptConnections = false;
+    }
+
+    /**
+     * Make the OCSP server accept incoming connections.
+     */
+    public synchronized void acceptConnections() {
+        log("Accept OCSP connections");
+        acceptConnections = true;
+    }
+
+
+    /**
      * Stop the OCSP server.
      */
     public synchronized void stop() {
@@ -499,13 +528,11 @@
      * on the incoming request.
      */
     public void setDelay(long delayMillis) {
-        if (!started) {
-            delayMsec = delayMillis > 0 ? delayMillis : 0;
-            if (delayMsec > 0) {
-                log("OCSP latency set to " + delayMsec + " milliseconds.");
-            } else {
-                log("OCSP latency disabled");
-            }
+        delayMsec = delayMillis > 0 ? delayMillis : 0;
+        if (delayMsec > 0) {
+            log("OCSP latency set to " + delayMsec + " milliseconds.");
+        } else {
+            log("OCSP latency disabled");
         }
     }
 
--- a/test/java/text/Format/DateFormat/Bug4322313.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/Bug4322313.java	Mon Aug 22 10:02:10 2016 -0700
@@ -158,7 +158,8 @@
 
         try {
             for (int i=0; i < locs.length; i++) {
-                Locale.setDefault(locs[i]);
+                Locale locale = locs[i];
+                Locale.setDefault(locale);
 
                 for (int j=0; j < formats.length; j++) {
                     TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
@@ -174,7 +175,7 @@
                         catch (Exception e) {
                             err = true;
                             System.err.println("\tParse  Error [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale + ", " + formats[j] +
                                 "/\"" + valids[k][0] +
                                 "\"] Unexpected Exception occurred: " + e);
                             continue;
@@ -184,7 +185,7 @@
                         if (offset != ((Integer)valids[k][4]).intValue()) {
                             err = true;
                             System.err.println("\tParse  Error [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale + ", " + formats[j] +
                                 "/\"" + valids[k][0] +
                                 "\"] invalid index: expected:" + valids[k][4] +
                                 ", got:" + offset);
@@ -193,14 +194,14 @@
                         if (date.getTime() != ((Long)valids[k][1]).longValue()) {
                             err = true;
                             System.err.println("\tParse  Error [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale + ", " + formats[j] +
                                 "/\"" + valids[k][0] +
                                 "\"] expected:" + valids[k][1] +
                                 ", got:" + date.getTime() + ", " + date);
                         } else {
 /*
                             logln("\tParse  Okay  [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale) + ", " + formats[j] +
                                 "/\"" + valids[k][0] +
                                 "\"] expected:" + valids[k][1] +
                                 ", got:" + date.getTime() + ", " + date);
@@ -212,7 +213,7 @@
                             catch (Exception e) {
                                 err = true;
                                 System.err.println("\tParse  Error [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + valids[k][0] +
                                     "\"] Unexpected Exception occurred: " + e);
                                 continue;
@@ -245,14 +246,14 @@
                                   expected.equals("GMT+00:00"))) {
                                 err = true;
                                 System.err.println("\tFormat Error [Locale=" +
-                                    Locale.getDefault() + ", " +
+                                    locale + ", " +
                                     formats[j] + "/\"" + valids[k][0] +
                                     "\"] expected:" + valids[k][2+j] +
                                     ", got:" + s + ", " + date);
                             } else {
 /*
                                 logln("\tFormat Okay  [Locale=" +
-                                    Locale.getDefault() + ", " +
+                                    locale + ", " +
                                     formats[j] + "/\"" + valids[k][0] +
                                     "\"] expected:" + valids[k][2+j] +
                                     ", got:" + s + ", " + date);
@@ -271,7 +272,7 @@
                             if (date != null) {
                                 err = true;
                                 System.err.println("\tParse  Error [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] expected:null , got:" + date);
                             }
@@ -279,14 +280,14 @@
                             if (offset != ((Integer)invalids[k][1]).intValue()) {
                                 err = true;
                                 System.err.println("\tParse  Error [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] incorrect offset. expected:" +
                                     invalids[k][1] + ", got: " + offset);
                             } else {
 /*
                                 logln("\tParse  Okay  [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] correct offset: " + offset);
 */
@@ -295,7 +296,7 @@
                         catch (Exception e) {
                             err = true;
                             System.err.println("\tParse  Error [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale + ", " + formats[j] +
                                 "/\"" + invalids[k][0] +
                                 "\"] Unexpected Exception occurred: " + e);
                         }
@@ -315,14 +316,14 @@
                             if (offset != ((Integer)invalids[k][1]).intValue()) {
                                 err = true;
                                 System.err.println("\tParse  Error [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] Expected exception occurred with an incorrect offset. expected:" +
                                     invalids[k][1] + ", got: " + offset);
                             } else {
 /*
                                 logln("\tParse  Okay  [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] Expected exception occurred with an correct offset: "
                                     + offset);
@@ -332,7 +333,7 @@
                         catch (Exception e) {
                             err = true;
                             System.err.println("\tParse  Error [Locale=" +
-                                Locale.getDefault() + ", " + formats[j] +
+                                locale + ", " + formats[j] +
                                 "/\"" + invalids[k][0] +
                                 "\"] Invalid exception occurred: " + e);
                         }
@@ -340,7 +341,7 @@
                             if (!correctParseException) {
                                 err = true;
                                 System.err.println("\tParse  Error: [Locale=" +
-                                    Locale.getDefault() + ", " + formats[j] +
+                                    locale + ", " + formats[j] +
                                     "/\"" + invalids[k][0] +
                                     "\"] Expected exception didn't occur.");
                             }
--- a/test/java/text/Format/DateFormat/Bug4407042.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/Bug4407042.java	Mon Aug 22 10:02:10 2016 -0700
@@ -26,6 +26,7 @@
  * @bug 4407042
  * @summary Make sure that cloned SimpleDateFormat objects work
  * independently in multiple threads.
+ * @library /java/text/testlib
  * @run main Bug4407042 10
  */
 
@@ -44,8 +45,9 @@
 
     void test() {
         Locale locale = Locale.getDefault();
-        if (locale.equals(new Locale("th", "TH")) ||
-            locale.equals(new Locale("hi", "IN"))) {
+        if (!TestUtils.usesAsciiDigits(locale)
+                || !TestUtils.usesGregorianCalendar(locale)) {
+            System.out.println("Skipping this test because locale is " + locale);
             return;
         }
 
--- a/test/java/text/Format/DateFormat/Bug4845901.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/Bug4845901.java	Mon Aug 22 10:02:10 2016 -0700
@@ -27,6 +27,8 @@
  * @summary Make sure that SimpleDateFormat.parse() can distinguish
  * the same time zone abbreviation for standard and daylight saving
  * time.
+ * @library /java/text/testlib
+ * @run main Bug4845901
  */
 
 import java.util.*;
@@ -34,6 +36,12 @@
 
 public class Bug4845901 {
     public static void main (String args[]) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            System.out.println("Skipping this test because locale is " + locale);
+            return;
+        }
+
         TimeZone savedTZ = TimeZone.getDefault();
         TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney"));
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z");
--- a/test/java/text/Format/DateFormat/Bug6530336.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/Bug6530336.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6530336 6537997 8008577
+ * @library /java/text/testlib
  * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336
  */
 
@@ -43,7 +44,6 @@
 
         try {
             Locale locales[] = Locale.getAvailableLocales();
-            Locale locale_Japan = new Locale("ja", "JP", "JP");
             TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles");
             TimeZone.setDefault(timezone_LA);
 
@@ -60,12 +60,12 @@
             Date[] dates = new Date[2];
 
             for (int i = 0; i < locales.length; i++) {
-                if (locales[i].getLanguage().equals("th") ||
-                    locales[i].equals(locale_Japan)) {
+                Locale locale = locales[i];
+                if (!TestUtils.usesGregorianCalendar(locale)) {
                     continue;
                 }
 
-                Locale.setDefault(locales[i]);
+                Locale.setDefault(locale);
 
                 for (int j = 0; j < timezones.length; j++) {
                     Calendar cal = Calendar.getInstance(timezones[j]);
@@ -83,7 +83,7 @@
 
                     if (!expected[j].equals(date_LA)) {
                         System.err.println("Got wrong Pacific time (" +
-                            date_LA + ") for (" + date + ") in " + locales[i] +
+                            date_LA + ") for (" + date + ") in " + locale +
                             " in " + timezones[j] +
                             ".\nExpected=" + expected[j]);
                         err = true;
--- a/test/java/text/Format/DateFormat/DateFormatRegression.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/DateFormatRegression.java	Mon Aug 22 10:02:10 2016 -0700
@@ -72,7 +72,6 @@
     }
 
     public void Test4052408() {
-
         DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
                                                         DateFormat.SHORT, Locale.US);
         Date date = new Date(97, Calendar.MAY, 3, 8, 55);
@@ -164,7 +163,9 @@
     }
 
     public void Test4059917() {
-        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesAsciiDigits(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -621,25 +622,6 @@
         }
     }
 
-    /*
-      Synopsis: Chinese time zone CTT is not recogonized correctly.
-      Description: Platform Chinese Windows 95 - ** Time zone set to CST **
-      */
-    public void Test4108407() {
-
-        long l = System.currentTimeMillis();
-        logln("user.timezone = " + System.getProperty("user.timezone", "?"));
-        logln("Time Zone :" +
-                           DateFormat.getDateInstance().getTimeZone().getID());
-        logln("Default format :" +
-                           DateFormat.getDateInstance().format(new Date(l)));
-        logln("Full format :" +
-                           DateFormat.getDateInstance(DateFormat.FULL).format(new
-                                                                              Date(l)));
-        logln("*** Set host TZ to CST ***");
-        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
-    }
-
     /**
      * SimpleDateFormat won't parse "GMT"
      */
--- a/test/java/text/Format/DateFormat/bug4358730.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/DateFormat/bug4358730.java	Mon Aug 22 10:02:10 2016 -0700
@@ -47,23 +47,17 @@
     };
     int[] year = {2, 20, 200, 2000};
 
-    SimpleDateFormat sdf = new SimpleDateFormat();
     int datasize = data.length;
     int nPatterns = data[0].length;
 
     public void Test4358730() {
-        Locale locale = Locale.getDefault();
-        if (locale.equals(new Locale("th", "TH")) ||
-            locale.equals(new Locale("hi", "IN"))) {
-            return;
-        }
-
         TimeZone saveZone = TimeZone.getDefault();
         Locale saveLocale = Locale.getDefault();
 
         try {
             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
             Locale.setDefault(new Locale("en", "US"));
+            SimpleDateFormat sdf = new SimpleDateFormat();
 
             for (int i = 0; i < datasize; i++) {
                 Date d = new Date(year[i]-1900, 10, 15);
--- a/test/java/text/Format/MessageFormat/MessageRegression.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/MessageFormat/MessageRegression.java	Mon Aug 22 10:02:10 2016 -0700
@@ -28,6 +28,7 @@
  * 4142938 4169959 4232154 4293229
  * @summary Regression tests for MessageFormat and associated classes
  * @library /java/text/testlib
+ * @run main MessageRegression
  */
 /*
 (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
@@ -121,14 +122,15 @@
      * More robust message formats.
      */
     public void Test4031438() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesAsciiDigits(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}.";
         String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.";
 
-        // If the current locale is hi_IN, skip this test case.
-        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
-            return;
-        }
-
         MessageFormat messageFormatter = new MessageFormat("");
 
         try {
--- a/test/java/text/Format/NumberFormat/NumberRegression.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/text/Format/NumberFormat/NumberRegression.java	Mon Aug 22 10:02:10 2016 -0700
@@ -32,7 +32,7 @@
  * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577
  * @summary Regression tests for NumberFormat and associated classes
  * @library /java/text/testlib
- * @build IntlTest HexDumpReader
+ * @build IntlTest HexDumpReader TestUtils
  * @modules java.base/sun.util.resources
  * @compile -XDignore.symbol.file NumberRegression.java
  * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression
@@ -100,6 +100,12 @@
      */
 
     public void Test4088161 (){
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesAsciiDigits(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         DecimalFormat df = new DecimalFormat();
         double d = 100;
         df.setMinimumFractionDigits(0);
@@ -114,8 +120,7 @@
         FieldPosition fp2 = new FieldPosition(0);
         logln("maxFractionDigits = " + df.getMaximumFractionDigits());
         df.format(d, sBuf2, fp2);
-        String expected = Locale.getDefault().equals(new Locale("hi", "IN")) ?
-                              "\u0967\u0966\u0966" : "100";
+        String expected = "100";
         if (!sBuf2.toString().equals(expected))
             errln(" format(d) = '" + sBuf2 + "'");
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/text/testlib/TestUtils.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.text.DecimalFormatSymbols;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+import java.util.Locale.Builder;
+
+/**
+ * TestUtils provides utility methods to get a locale-dependent attribute.
+ * For example,
+ *   - whether or not a non-Gregorian calendar is used
+ *   - whether or not non-ASCII digits are used
+ *
+ * This class was developed to help testing for internationalization &
+ * localization and is not versatile.
+ */
+public class TestUtils {
+
+    /**
+     * Returns true if the give locale uses Gregorian calendar.
+     */
+    public static boolean usesGregorianCalendar(Locale locale) {
+        return Calendar.getInstance(locale).getClass() == GregorianCalendar.class;
+    }
+
+    /**
+     * Returns true if the given locale uses ASCII digits.
+     */
+    public static boolean usesAsciiDigits(Locale locale) {
+        return DecimalFormatSymbols.getInstance(locale).getZeroDigit() == '0';
+    }
+
+    /**
+     * Returns true if the given locale has a special variant which is treated
+     * as ill-formed in BCP 47.
+     *
+     * BCP 47 requires a variant subtag to be 5 to 8 alphanumerics or a
+     * single numeric followed by 3 alphanumerics.
+     * However, note that this methods doesn't check a variant so rigorously
+     * because this is a utility method for testing. Intended special variants
+     * are: JP, NY, and TH, which can be commonly provided by
+     * Locale.getAvailableLocales().
+     *
+     */
+    public static boolean hasSpecialVariant(Locale locale) {
+        String variant = locale.getVariant();
+        return !variant.isEmpty()
+                   && "JP".equals(variant) || "NY".equals(variant) || "TH".equals(variant);
+    }
+
+}
--- a/test/java/util/Calendar/CalendarLimitTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Calendar/CalendarLimitTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,8 +24,8 @@
 /**
  * @test
  * @bug 4033662
+ * @summary test for limit on Calendar
  * @library /java/text/testlib
- * @summary test for limit on Calendar
  * @run main CalendarLimitTest -verbose
  */
 
@@ -62,6 +62,12 @@
     static long ORIGIN; // This is the *approximate* point at which BC switches to AD
 
     public static void main(String argv[]) throws Exception {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            System.out.println("Skipping this test because locale is " + locale);
+            return;
+        }
+
         new CalendarLimitTest().run(argv);
     }
 
--- a/test/java/util/Calendar/CalendarRegression.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Calendar/CalendarRegression.java	Mon Aug 22 10:02:10 2016 -0700
@@ -32,6 +32,7 @@
  * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642
  * 4973919 4980088 4965624 5013094 5006864 8152077
  * @library /java/text/testlib
+ * @run main CalendarRegression
  */
 
 import java.lang.reflect.*;
@@ -531,6 +532,12 @@
     }
 
     public void Test4100311() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
         cal.set(Calendar.YEAR, 1997);
         cal.set(Calendar.DAY_OF_YEAR, 1);
@@ -541,7 +548,9 @@
     }
 
     public void Test4103271() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -768,6 +777,12 @@
     }
 
     public void Test4114578() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         int ONE_HOUR = 60*60*1000;
         TimeZone saveZone = TimeZone.getDefault();
         boolean fail = false;
@@ -847,6 +862,12 @@
      * Check isLeapYear for BC years.
      */
     public void Test4125881() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
         DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
         cal.clear();
@@ -865,7 +886,9 @@
      * at 45 BC, and not have leap years before then).
      */
     public void Test4125892() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -1276,7 +1299,9 @@
      * This bug relies on the TimeZone bug 4173604 to also be fixed.
      */
     public void Test4173516() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -1755,7 +1780,10 @@
      * get(int) changes internal states of a Calendar.
      */
     public void Test4685354() {
-        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesAsciiDigits(locale)
+                || !TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -1860,8 +1888,9 @@
      * get(int) changes internal states of a Calendar.
      */
     public void Test4655637() {
-        // Skip this test case if it's Thai locale
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
--- a/test/java/util/Calendar/CalendarTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Calendar/CalendarTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -24,8 +24,9 @@
 /**
  * @test
  * @bug 4064654 4374886 4984320 4984574 4944795
+ * @summary test for Calendar
  * @library /java/text/testlib
- * @summary test for Calendar
+ * @run main CalendarTest
  * @key randomness
  */
 
@@ -203,7 +204,9 @@
     }
 
     public void TestGenericAPI() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -559,7 +562,9 @@
 
     // Test the behavior of GMT vs. local time
     public void TestGMTvsLocal4064654() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
@@ -875,10 +880,6 @@
     // Verify that the fields are as expected (mostly zero) at the epoch start.
     // Note that we adjust for the default timezone to get most things to zero.
     public void TestEpochStartFields() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
-            return;
-        }
-
         String[][] lt = {
           {"en", "US", "US/Pacific"},        /* First day = 1, Minimum day = 1 */
           {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */
--- a/test/java/util/Calendar/bug4409072.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Calendar/bug4409072.java	Mon Aug 22 10:02:10 2016 -0700
@@ -26,6 +26,7 @@
  * @bug 4409072
  * @summary tests for set(), add(), and roll() with various week parameters.
  * @library /java/text/testlib
+ * @run main bug4409072
  */
 
 import  java.util.*;
@@ -41,7 +42,9 @@
      * (e.g. add(), roll(), set())
      */
     public void Test4409072() {
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Date/Bug8135055.java	Mon Aug 22 10:02:10 2016 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8135055
+ * @summary Test java.sql.TimeStamp instance should come after java.util.Date
+ * if Nanos component of TimeStamp is not equal to 0 milliseconds.
+*/
+import java.sql.Timestamp;
+import java.util.Date;
+
+public class Bug8135055 {
+
+    public static void main(String[] args) throws InterruptedException {
+        for (int i = 0; i < 1000; i++) {
+            Date d = new Date();
+            Timestamp ts = new Timestamp(d.getTime());
+            if (d.after(ts)) {
+                throw new RuntimeException("date with time " + d.getTime()
+                        + " should not be after TimeStamp , Nanos component of "
+                                + "TimeStamp is " +ts.getNanos());
+            }
+            Thread.sleep(1);
+        }
+    }
+}
--- a/test/java/util/Locale/LocaleCategory.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Locale/LocaleCategory.java	Mon Aug 22 10:02:10 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,11 @@
 
     public static void main(String[] args) {
         Locale reservedLocale = Locale.getDefault();
+        if (TestUtils.hasSpecialVariant(reservedLocale)) {
+            System.out.println("Skipping this test because locale is " + reservedLocale);
+            return;
+        }
+
         try {
             Locale.Builder builder = new Locale.Builder();
 
--- a/test/java/util/Locale/LocaleCategory.sh	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/Locale/LocaleCategory.sh	Mon Aug 22 10:02:10 2016 -0700
@@ -26,7 +26,8 @@
 # @bug 4700857 6997928 7079486
 # @summary tests for Locale.getDefault(Locale.Category) and
 #    Locale.setDefault(Locale.Category, Locale)
-# @build LocaleCategory
+# @library /java/text/testlib
+# @build LocaleCategory TestUtils
 # @run shell/timeout=600 LocaleCategory.sh
 
 if [ "${TESTSRC}" = "" ]
@@ -46,7 +47,9 @@
   echo "TESTCLASSES not set.  Test cannot execute.  Failed."
   exit 1
 fi
+
 echo "TESTCLASSES=${TESTCLASSES}"
+echo "TESTCLASSPATH=${TESTCLASSPATH}"
 echo "CLASSPATH=${CLASSPATH}"
 
 # set platform-dependent variables
@@ -69,7 +72,7 @@
 # test user.xxx.display user.xxx.format properties
 
 # run
-RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
+RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSPATH} -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
 
 echo ${RUNCMD}
 ${RUNCMD}
@@ -85,7 +88,7 @@
 # test user.xxx properties overriding user.xxx.display/format
 
 # run
-RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Duser.language=en -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
+RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSPATH} -Duser.language=en -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
 
 echo ${RUNCMD}
 ${RUNCMD}
--- a/test/java/util/TimeZone/Bug4322313.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/TimeZone/Bug4322313.java	Mon Aug 22 10:02:10 2016 -0700
@@ -90,7 +90,9 @@
             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
 
             for (int i = 0; i < locs.length; i++) {
-                Locale.setDefault(locs[i]);
+                Locale locale = locs[i];
+                Locale.setDefault(locale);
+
 
                 /* Okay case */
                 for (int k = 0; k < VALIDS.length; k++) {
@@ -100,12 +102,12 @@
                     if (!tz.getID().equals(VALIDS[k][2])) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           locale + ", \"" + VALIDS[k][0] +
                                            "\"] Invalid TimeZone ID, expected:" +
                                            VALIDS[k][2] + ", got:" + tz.getID() + ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              locale + ", \"" + VALIDS[k][0] +
                               "\"] Valid TimeZone ID, got:" + VALIDS[k][2]);
                     }
 
@@ -113,12 +115,12 @@
                     if (offset != (int)VALIDS[k][1]) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           locale + ", \"" + VALIDS[k][0] +
                                            "\"] Invalid RawOffset, expected:" + VALIDS[k][1] +
                                            ", got:" + offset + ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              locale + ", \"" + VALIDS[k][0] +
                               "\"] Vaild RawOffset, got:" + offset);
                     }
 
@@ -126,12 +128,12 @@
                     if (offset != 0) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           locale + ", \"" + VALIDS[k][0] +
                                            "\"] DSTSavings should be zero, got:" + offset +
                                            ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              locale + ", \"" + VALIDS[k][0] +
                               "\"] DSTSavings is zero.");
                     }
                 }
@@ -144,12 +146,12 @@
                     if (!tz.getID().equals("GMT")) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           locale + ", \"" + INVALIDS[k] +
                                            "\"] Invalid TimeZone ID, expected:GMT, got:" +
                                            tz.getID() + ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              locale + ", \"" + INVALIDS[k] +
                               "\"] Valid TimeZone ID, got:" + tz.getID());
                     }
 
@@ -157,12 +159,12 @@
                     if (offset != 0) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           locale + ", \"" + INVALIDS[k] +
                                            "\"] RawOffset should be zero, got:" + offset +
                                            ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              locale + ", \"" + INVALIDS[k] +
                               "\"] RawOffset is zero.");
                     }
 
@@ -170,12 +172,12 @@
                     if (offset != 0) {
                         err = true;
                         System.err.println("\tFailed [Locale=" +
-                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           locale + ", \"" + INVALIDS[k] +
                                            "\"] DSTSavings should be zero, got:" + offset +
                                            ", " + tz);
                     } else {
                         logln("\tPassed [Locale=" +
-                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              locale + ", \"" + INVALIDS[k] +
                               "\"] DSTSavings is zero.");
                     }
                 }
@@ -189,25 +191,25 @@
                     if (!normalizedID.equals(s)) {
                         err = true;
                         System.err.println("getDisplayName returned unexpected name: " + s +
-                                           " in " + Locale.getDefault());
+                                           " in " + locale);
                     }
                     s = tz.getDisplayName(true, tz.SHORT);
                     if (!normalizedID.equals(s)) {
                         err = true;
                         System.err.println("getDisplayName returned unexpected name: " + s +
-                                           " in " + Locale.getDefault());
+                                           " in " + locale);
                     }
                     s = tz.getDisplayName(false, tz.LONG);
                     if (!normalizedID.equals(s)) {
                         err = true;
                         System.err.println("getDisplayName returned unexpected name: " + s +
-                                           " in " + Locale.getDefault());
+                                           " in " + locale);
                     }
                     s = tz.getDisplayName(false, tz.SHORT);
                     if (!normalizedID.equals(s)) {
                         err = true;
                         System.err.println("getDisplayName returned unexpected name: " + s +
-                                           " in " + Locale.getDefault());
+                                           " in " + locale);
                     }
                 }
             }
--- a/test/java/util/TimeZone/TimeZoneRegression.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/TimeZone/TimeZoneRegression.java	Mon Aug 22 10:02:10 2016 -0700
@@ -40,15 +40,6 @@
         new TimeZoneRegression().run(args);
     }
 
-    public void Test4052967() {
-        logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
-        String id = TimeZone.getDefault().getID();
-        logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));
-        logln("TimeZone.getDefault().getID(): " + id);
-        logln(new Date().toString());
-        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
-    }
-
     public void Test4073209() {
         TimeZone z1 = TimeZone.getTimeZone("PST");
         TimeZone z2 = TimeZone.getTimeZone("PST");
@@ -167,11 +158,14 @@
     }
 
     public void Test4109314() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         // test both SimpleTimeZone and ZoneInfo objects.
         // @since 1.4
-        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
-            return;
-        }
         sub4109314(getPST());
         sub4109314(TimeZone.getTimeZone("PST"));
     }
@@ -291,6 +285,12 @@
      * When you fix these two problems, the test passes, as expected.
      */
     public void Test4126678() {
+        Locale locale = Locale.getDefault();
+        if (!TestUtils.usesGregorianCalendar(locale)) {
+            logln("Skipping this test because locale is " + locale);
+            return;
+        }
+
         // Note: this test depends on the PST time zone.
         TimeZone initialZone = TimeZone.getDefault();
 
--- a/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Mon Aug 22 10:02:10 2016 -0700
@@ -26,43 +26,133 @@
  * However, the following notice accompanied the original version of this
  * file:
  *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /*
  * @test
  * @bug 6236036 6264015
- * @compile PollMemoryLeak.java
- * @run main/othervm -Xmx8m PollMemoryLeak
- * @summary  Checks for OutOfMemoryError when an unbounded
- * number of aborted timed waits occur without a signal.
+ * @summary Checks for a memory leak when a sequence of aborted timed
+ * waits occur without a signal.  Uses the strategy of detecting
+ * changes in the size of the object graph retained by a root object.
  */
 
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Set;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.PriorityBlockingQueue;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
 public class PollMemoryLeak {
-    public static void main(String[] args) throws InterruptedException {
-        final BlockingQueue[] qs = {
-            new LinkedBlockingDeque(10),
-            new LinkedBlockingQueue(10),
-            new LinkedTransferQueue(),
-            new ArrayBlockingQueue(10),
-            new ArrayBlockingQueue(10, true),
-            new SynchronousQueue(),
-            new SynchronousQueue(true),
-        };
-        final long start = System.currentTimeMillis();
-        final long end = start + 10 * 1000;
-        while (System.currentTimeMillis() < end)
-            for (BlockingQueue q : qs)
-                q.poll(1, TimeUnit.NANOSECONDS);
+    public static void main(String[] args) throws Throwable {
+        new PollMemoryLeak().main();
+    }
+
+    void main() throws Throwable {
+        test(new LinkedBlockingDeque(10));
+        test(new LinkedBlockingQueue(10));
+        test(new LinkedTransferQueue());
+        test(new ArrayBlockingQueue(10));
+        test(new PriorityBlockingQueue());
+        test(new SynchronousQueue());
+        test(new SynchronousQueue(true));
+    }
+
+    void test(BlockingQueue q) throws Throwable {
+        assertNoLeak(q, () -> timedPoll(q));
+
+        // A demo that the leak detection infrastructure works
+        // assertNoLeak(q, () -> q.add(1));
+        // printRetainedObjects(q);
+    }
+
+    static void timedPoll(BlockingQueue q) {
+        try { q.poll(1, TimeUnit.NANOSECONDS); }
+        catch (InterruptedException ex) { throw new AssertionError(ex); }
+    }
+
+    // -------- leak detection infrastructure ---------------
+    void assertNoLeak(Object root, Runnable r) {
+        int prev = retainedObjects(root).size();
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) r.run();
+            int next = retainedObjects(root).size();
+            if (next <= prev)
+                return;
+            prev = next;
+        }
+        throw new AssertionError(
+            String.format("probable memory leak in %s: %s",
+                          root.getClass().getSimpleName(), root));
+    }
+
+    ConcurrentHashMap<Class<?>, Collection<Field>> classFields
+        = new ConcurrentHashMap<Class<?>, Collection<Field>>();
+
+    Collection<Field> referenceFieldsOf(Class<?> k) {
+        Collection<Field> fields = classFields.get(k);
+        if (fields == null) {
+            fields = new ArrayDeque<Field>();
+            ArrayDeque<Field> allFields = new ArrayDeque<Field>();
+            for (Class<?> c = k; c != null; c = c.getSuperclass())
+                for (Field field : c.getDeclaredFields())
+                    if (!Modifier.isStatic(field.getModifiers())
+                        && !field.getType().isPrimitive())
+                        fields.add(field);
+            AccessibleObject.setAccessible(
+                fields.toArray(new AccessibleObject[0]), true);
+            classFields.put(k, fields);
+        }
+        return fields;
+    }
+
+    static Object get(Field field, Object x) {
+        try { return field.get(x); }
+        catch (IllegalAccessException ex) { throw new AssertionError(ex); }
+    }
+
+    Set<Object> retainedObjects(Object x) {
+        ArrayDeque<Object> todo = new ArrayDeque<Object>() {
+            public void push(Object x) { if (x != null) super.push(x); }};
+        Set<Object> uniqueObjects = Collections.newSetFromMap(
+            new IdentityHashMap<Object, Boolean>());
+        todo.push(x);
+        while (!todo.isEmpty()) {
+            Object y = todo.pop();
+            if (uniqueObjects.contains(y))
+                continue;
+            uniqueObjects.add(y);
+            Class<?> k = y.getClass();
+            if (k.isArray() && !k.getComponentType().isPrimitive()) {
+                for (int i = 0, len = Array.getLength(y); i < len; i++)
+                    todo.push(Array.get(y, i));
+            } else {
+                for (Field field : referenceFieldsOf(k))
+                    todo.push(get(field, y));
+            }
+        }
+        return uniqueObjects;
+    }
+
+    /** for debugging the retained object graph */
+    void printRetainedObjects(Object x) {
+        for (Object y : retainedObjects(x))
+            System.out.printf("%s : %s%n", y.getClass().getSimpleName(), y);
     }
 }
--- a/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java	Mon Aug 22 10:02:10 2016 -0700
@@ -35,26 +35,120 @@
  * @test
  * @bug 8054446 8137184 8137185
  * @summary Regression test for memory leak in remove(Object)
- * @run main/othervm -Xmx2200k RemoveLeak
  */
 
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Set;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.PriorityBlockingQueue;
 
 public class RemoveLeak {
-    public static void main(String[] args) {
-        int i = 0;
-        // Without bug fix, OutOfMemoryError was observed at iteration 65120
-        int iterations = 10 * 65120;
-        try {
-            ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<>();
-            queue.add(0L);
-            while (i++ < iterations) {
-                queue.add(1L);
-                queue.remove(1L);
+    public static void main(String[] args) throws Throwable {
+        new RemoveLeak().main();
+    }
+
+    void main() throws Throwable {
+        test(new ConcurrentLinkedDeque());
+        test(new ConcurrentLinkedQueue());
+        test(new LinkedBlockingDeque(10));
+        test(new LinkedBlockingQueue(10));
+        test(new LinkedTransferQueue());
+        test(new ArrayBlockingQueue(10));
+        test(new PriorityBlockingQueue());
+    }
+
+    void test(Collection c) throws Throwable {
+        assertNoLeak(c, () -> addRemove(c));
+
+        // A demo that the leak detection infrastructure works
+        // assertNoLeak(c, () -> c.add(1));
+        // printRetainedObjects(c);
+    }
+
+    static void addRemove(Collection c) {
+        c.add(1);
+        c.remove(1);
+    }
+
+    // -------- leak detection infrastructure ---------------
+    void assertNoLeak(Object root, Runnable r) {
+        int prev = retainedObjects(root).size();
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) r.run();
+            int next = retainedObjects(root).size();
+            if (next <= prev)
+                return;
+            prev = next;
+        }
+        throw new AssertionError(
+            String.format("probable memory leak in %s: %s",
+                          root.getClass().getSimpleName(), root));
+    }
+
+    ConcurrentHashMap<Class<?>, Collection<Field>> classFields
+        = new ConcurrentHashMap<Class<?>, Collection<Field>>();
+
+    Collection<Field> referenceFieldsOf(Class<?> k) {
+        Collection<Field> fields = classFields.get(k);
+        if (fields == null) {
+            fields = new ArrayDeque<Field>();
+            ArrayDeque<Field> allFields = new ArrayDeque<Field>();
+            for (Class<?> c = k; c != null; c = c.getSuperclass())
+                for (Field field : c.getDeclaredFields())
+                    if (!Modifier.isStatic(field.getModifiers())
+                        && !field.getType().isPrimitive())
+                        fields.add(field);
+            AccessibleObject.setAccessible(
+                fields.toArray(new AccessibleObject[0]), true);
+            classFields.put(k, fields);
+        }
+        return fields;
+    }
+
+    static Object get(Field field, Object x) {
+        try { return field.get(x); }
+        catch (IllegalAccessException ex) { throw new AssertionError(ex); }
+    }
+
+    Set<Object> retainedObjects(Object x) {
+        ArrayDeque<Object> todo = new ArrayDeque<Object>() {
+            public void push(Object x) { if (x != null) super.push(x); }};
+        Set<Object> uniqueObjects = Collections.newSetFromMap(
+            new IdentityHashMap<Object, Boolean>());
+        todo.push(x);
+        while (!todo.isEmpty()) {
+            Object y = todo.pop();
+            if (uniqueObjects.contains(y))
+                continue;
+            uniqueObjects.add(y);
+            Class<?> k = y.getClass();
+            if (k.isArray() && !k.getComponentType().isPrimitive()) {
+                for (int i = 0, len = Array.getLength(y); i < len; i++)
+                    todo.push(Array.get(y, i));
+            } else {
+                for (Field field : referenceFieldsOf(k))
+                    todo.push(get(field, y));
             }
-        } catch (Error t) {
-            System.err.printf("failed at iteration %d/%d%n", i, iterations);
-            throw t;
         }
+        return uniqueObjects;
+    }
+
+    /** for debugging the retained object graph */
+    void printRetainedObjects(Object x) {
+        for (Object y : retainedObjects(x))
+            System.out.printf("%s : %s%n", y.getClass().getSimpleName(), y);
     }
 }
--- a/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java	Mon Aug 22 10:02:10 2016 -0700
@@ -26,51 +26,117 @@
  * However, the following notice accompanied the original version of this
  * file:
  *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /*
  * @test
- * @author Doug Lea
  * @bug 8004138
- * @key intermittent
- * @summary Check if ForkJoinPool table leaks thrown exceptions.
- * @run main/othervm -Xmx8m -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 FJExceptionTableLeak
+ * @summary Checks that ForkJoinTask thrown exceptions are not leaked.
+ * This whitebox test is sensitive to forkjoin implementation details.
  */
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
 import java.util.concurrent.RecursiveAction;
+import java.util.function.BooleanSupplier;
 
 public class FJExceptionTableLeak {
-    // This test was observed to fail with pre-bug-fix jdk7 -Xmx8m,
-    // using STEPS = 220 and TASKS_PER_STEP = 100
-    static final int PRE_BUG_FIX_FAILURE_STEPS = 220;
-    static final int STEPS = 10 * PRE_BUG_FIX_FAILURE_STEPS;
-    static final int TASKS_PER_STEP = 100;
-
     static class FailingTaskException extends RuntimeException {}
     static class FailingTask extends RecursiveAction {
-        public void compute() {
-            throw new FailingTaskException();
-        }
+        public void compute() { throw new FailingTaskException(); }
     }
 
-    public static void main(String[] args) throws InterruptedException {
-        ForkJoinPool pool = new ForkJoinPool(4);
-        FailingTask[] tasks = new FailingTask[TASKS_PER_STEP];
-        for (int k = 0; k < STEPS; ++k) {
-            for (int i = 0; i < tasks.length; ++i)
-                tasks[i] = new FailingTask();
-            for (int i = 0; i < tasks.length; ++i)
-                pool.execute(tasks[i]);
-            for (int i = 0; i < tasks.length; ++i) {
+    static int bucketsInuse(Object[] exceptionTable) {
+        int count = 0;
+        for (Object x : exceptionTable)
+            if (x != null) count++;
+        return count;
+    }
+
+    public static void main(String[] args) throws Exception {
+        final ForkJoinPool pool = new ForkJoinPool(4);
+        final Field exceptionTableField =
+            ForkJoinTask.class.getDeclaredField("exceptionTable");
+        exceptionTableField.setAccessible(true);
+        final Object[] exceptionTable = (Object[]) exceptionTableField.get(null);
+
+        if (bucketsInuse(exceptionTable) != 0) throw new AssertionError();
+
+        final ArrayList<FailingTask> tasks = new ArrayList<>();
+
+        // Keep submitting failing tasks until most of the exception
+        // table buckets are in use
+        do {
+            for (int i = 0; i < exceptionTable.length; i++) {
+                FailingTask task = new FailingTask();
+                pool.execute(task);
+                tasks.add(task); // retain strong refs to all tasks, for now
+            }
+            for (FailingTask task : tasks) {
                 try {
-                    tasks[i].join();
+                    task.join();
                     throw new AssertionError("should throw");
                 } catch (FailingTaskException success) {}
             }
+        } while (bucketsInuse(exceptionTable) < exceptionTable.length * 3 / 4);
+
+        // Retain a strong ref to one last failing task;
+        // task.join() will trigger exception table expunging.
+        FailingTask lastTask = tasks.get(0);
+
+        // Clear all other strong refs, making exception table cleanable
+        tasks.clear();
+
+        BooleanSupplier exceptionTableIsClean = () -> {
+            try {
+                lastTask.join();
+                throw new AssertionError("should throw");
+            } catch (FailingTaskException expected) {}
+            int count = bucketsInuse(exceptionTable);
+            if (count == 0)
+                throw new AssertionError("expected to find last task");
+            return count == 1;
+        };
+        gcAwait(exceptionTableIsClean);
+    }
+
+    // --------------- GC finalization infrastructure ---------------
+
+    /** No guarantees, but effective in practice. */
+    static void forceFullGc() {
+        CountDownLatch finalizeDone = new CountDownLatch(1);
+        WeakReference<?> ref = new WeakReference<Object>(new Object() {
+            protected void finalize() { finalizeDone.countDown(); }});
+        try {
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+                    System.runFinalization(); // try to pick up stragglers
+                    return;
+                }
+            }
+        } catch (InterruptedException unexpected) {
+            throw new AssertionError("unexpected InterruptedException");
         }
+        throw new AssertionError("failed to do a \"full\" gc");
+    }
+
+    static void gcAwait(BooleanSupplier s) {
+        for (int i = 0; i < 10; i++) {
+            if (s.getAsBoolean())
+                return;
+            forceFullGc();
+        }
+        throw new AssertionError("failed to satisfy condition");
     }
 }
--- a/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -492,7 +492,7 @@
             }});
 
         await(aboutToWait);
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t);
         t.interrupt();
         awaitTermination(t);
         checkEmpty(q);
--- a/test/java/util/concurrent/tck/AtomicBooleanTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/AtomicBooleanTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -136,11 +136,14 @@
      * getAndSet returns previous value and sets to given value
      */
     public void testGetAndSet() {
-        AtomicBoolean ai = new AtomicBoolean(true);
-        assertEquals(true, ai.getAndSet(false));
-        assertEquals(false, ai.getAndSet(false));
-        assertEquals(false, ai.getAndSet(true));
-        assertTrue(ai.get());
+        AtomicBoolean ai = new AtomicBoolean();
+        boolean[] booleans = { false, true };
+        for (boolean before : booleans)
+            for (boolean after : booleans) {
+                ai.set(before);
+                assertEquals(before, ai.getAndSet(after));
+                assertEquals(after, ai.get());
+            }
     }
 
     /**
--- a/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java	Mon Aug 22 10:02:10 2016 -0700
@@ -433,7 +433,7 @@
         Integer[] elements = new Integer[size];
         for (int i = 0; i < size; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         Iterator it = full.iterator();
@@ -523,7 +523,7 @@
         Integer[] elements = new Integer[size];
         for (int i = 0; i < size; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray())));
@@ -553,7 +553,7 @@
         Integer[] elements = new Integer[size];
         for (int i = 0; i < size; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         Arrays.fill(a, 42);
--- a/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -291,7 +291,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedArray(elements);
 
         Iterator it = full.iterator();
@@ -459,7 +459,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedArray(elements);
 
         assertTrue(Arrays.equals(elements, full.toArray()));
@@ -487,7 +487,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedArray(elements);
 
         Arrays.fill(a, 42);
--- a/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -251,7 +251,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         Iterator it = full.iterator();
@@ -338,7 +338,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         assertTrue(Arrays.equals(elements, full.toArray()));
@@ -366,7 +366,7 @@
         Integer[] elements = new Integer[SIZE];
         for (int i = 0; i < SIZE; i++)
             elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
+        shuffle(elements);
         Collection<Integer> full = populatedSet(elements);
 
         Arrays.fill(a, 42);
--- a/test/java/util/concurrent/tck/ForkJoinTask8Test.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/ForkJoinTask8Test.java	Mon Aug 22 10:02:10 2016 -0700
@@ -948,7 +948,7 @@
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks[0], tasks[1]);
                     shouldThrow();
@@ -975,7 +975,7 @@
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks[0], tasks[1], tasks[2]);
                     shouldThrow();
@@ -1002,7 +1002,7 @@
                 AsyncFib g = new AsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(Arrays.asList(tasks));
                     shouldThrow();
--- a/test/java/util/concurrent/tck/ForkJoinTaskTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/ForkJoinTaskTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -924,7 +924,7 @@
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks);
                     shouldThrow();
@@ -962,7 +962,7 @@
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks);
                     shouldThrow();
@@ -983,10 +983,9 @@
                 AsyncFib g = new AsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                List taskList = Arrays.asList(tasks);
-                Collections.shuffle(taskList);
+                shuffle(tasks);
                 try {
-                    invokeAll(taskList);
+                    invokeAll(Arrays.asList(tasks));
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(f, success);
@@ -1594,7 +1593,7 @@
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks);
                     shouldThrow();
@@ -1632,7 +1631,7 @@
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
+                shuffle(tasks);
                 try {
                     invokeAll(tasks);
                     shouldThrow();
@@ -1653,10 +1652,9 @@
                 AsyncFib g = new AsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
                 ForkJoinTask[] tasks = { f, g, h };
-                List taskList = Arrays.asList(tasks);
-                Collections.shuffle(taskList);
+                shuffle(tasks);
                 try {
-                    invokeAll(taskList);
+                    invokeAll(Arrays.asList(tasks));
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(f, success);
--- a/test/java/util/concurrent/tck/JSR166TestCase.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/JSR166TestCase.java	Mon Aug 22 10:02:10 2016 -0700
@@ -68,6 +68,7 @@
 import java.security.SecurityPermission;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -89,6 +90,7 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -1278,7 +1280,7 @@
      * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
      */
     void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
-        long startTime = System.nanoTime();
+        long startTime = 0L;
         for (;;) {
             Thread.State s = thread.getState();
             if (s == Thread.State.BLOCKED ||
@@ -1287,6 +1289,8 @@
                 return;
             else if (s == Thread.State.TERMINATED)
                 fail("Unexpected thread termination");
+            else if (startTime == 0L)
+                startTime = System.nanoTime();
             else if (millisElapsedSince(startTime) > timeoutMillis) {
                 threadAssertTrue(thread.isAlive());
                 return;
@@ -1900,4 +1904,7 @@
                                1000L, MILLISECONDS,
                                new SynchronousQueue<Runnable>());
 
+    static <T> void shuffle(T[] array) {
+        Collections.shuffle(Arrays.asList(array), ThreadLocalRandom.current());
+    }
 }
--- a/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -792,7 +792,7 @@
             }});
 
         aboutToWait.await();
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t);
         t.interrupt();
         awaitTermination(t);
         checkEmpty(q);
--- a/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -481,7 +481,7 @@
             }});
 
         await(aboutToWait);
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t);
         t.interrupt();
         awaitTermination(t);
         checkEmpty(q);
--- a/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -437,7 +437,7 @@
             }});
 
         aboutToWait.await();
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t);
         t.interrupt();
         awaitTermination(t);
     }
--- a/test/java/util/concurrent/tck/StampedLockTest.java	Mon Aug 22 10:35:16 2016 -0700
+++ b/test/java/util/concurrent/tck/StampedLockTest.java	Mon Aug 22 10:02:10 2016 -0700
@@ -34,10 +34,12 @@
 
 import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.StampedLock;
@@ -57,207 +59,188 @@
     }
 
     /**
-     * A runnable calling writeLockInterruptibly
+     * Releases write lock, checking isWriteLocked before and after
      */
-    class InterruptibleLockRunnable extends CheckedRunnable {
-        final StampedLock lock;
-        InterruptibleLockRunnable(StampedLock l) { lock = l; }
-        public void realRun() throws InterruptedException {
-            lock.writeLockInterruptibly();
-        }
+    void releaseWriteLock(StampedLock lock, long stamp) {
+        assertTrue(lock.isWriteLocked());
+        assertValid(lock, stamp);
+        lock.unlockWrite(stamp);
+        assertFalse(lock.isWriteLocked());
+        assertFalse(lock.validate(stamp));
     }
 
     /**
-     * A runnable calling writeLockInterruptibly that expects to be
-     * interrupted
+     * Releases read lock, checking isReadLocked before and after
      */
-    class InterruptedLockRunnable extends CheckedInterruptedRunnable {
-        final StampedLock lock;
-        InterruptedLockRunnable(StampedLock l) { lock = l; }
-        public void realRun() throws InterruptedException {
-            lock.writeLockInterruptibly();
-        }
+    void releaseReadLock(StampedLock lock, long stamp) {
+        assertTrue(lock.isReadLocked());
+        assertValid(lock, stamp);
+        lock.unlockRead(stamp);
+        assertFalse(lock.isReadLocked());
+        assertTrue(lock.validate(stamp));
     }
 
-    /**
-     * Releases write lock, checking isWriteLocked before and after
-     */
-    void releaseWriteLock(StampedLock lock, long s) {
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
+    long assertNonZero(long v) {
+        assertTrue(v != 0L);
+        return v;
+    }
+
+    long assertValid(StampedLock lock, long stamp) {
+        assertTrue(stamp != 0L);
+        assertTrue(lock.validate(stamp));
+        return stamp;
+    }
+
+    void assertUnlocked(StampedLock lock) {
+        assertFalse(lock.isReadLocked());
         assertFalse(lock.isWriteLocked());
+        assertEquals(0, lock.getReadLockCount());
+        assertValid(lock, lock.tryOptimisticRead());
+    }
+
+    List<Action> lockLockers(Lock lock) {
+        List<Action> lockers = new ArrayList<>();
+        lockers.add(() -> lock.lock());
+        lockers.add(() -> lock.lockInterruptibly());
+        lockers.add(() -> lock.tryLock());
+        lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS));
+        lockers.add(() -> lock.tryLock(0L, DAYS));
+        lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS));
+        return lockers;
+    }
+
+    List<Function<StampedLock, Long>> readLockers() {
+        List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
+        readLockers.add((sl) -> sl.readLock());
+        readLockers.add((sl) -> sl.tryReadLock());
+        readLockers.add((sl) -> readLockInterruptiblyUninterrupted(sl));
+        readLockers.add((sl) -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        readLockers.add((sl) -> tryReadLockUninterrupted(sl, 0L, DAYS));
+        readLockers.add((sl) -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
+        return readLockers;
+    }
+
+    List<BiConsumer<StampedLock, Long>> readUnlockers() {
+        List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>();
+        readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp));
+        readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead()));
+        readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock());
+        readUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+        readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
+        return readUnlockers;
+    }
+
+    List<Function<StampedLock, Long>> writeLockers() {
+        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
+        writeLockers.add((sl) -> sl.writeLock());
+        writeLockers.add((sl) -> sl.tryWriteLock());
+        writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0L, DAYS));
+        writeLockers.add((sl) -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
+        return writeLockers;
+    }
+
+    List<BiConsumer<StampedLock, Long>> writeUnlockers() {
+        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
+        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
+        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
+        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
+        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+        writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
+        return writeUnlockers;
     }
 
     /**
      * Constructed StampedLock is in unlocked state
      */
     public void testConstructor() {
-        StampedLock lock;
-        lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
+        assertUnlocked(new StampedLock());
     }
 
     /**
-     * write-locking and read-locking an unlocked lock succeed
+     * write-locking, then unlocking, an unlocked lock succeed
      */
-    public void testLock() {
+    public void testWriteLock_lockUnlock() {
         StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        lock.unlockWrite(s);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        lock.unlockRead(rs);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers())
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
+            assertFalse(lock.isWriteLocked());
+            assertFalse(lock.isReadLocked());
+            assertEquals(0, lock.getReadLockCount());
+
+            long s = writeLocker.apply(lock);
+            assertValid(lock, s);
+            assertTrue(lock.isWriteLocked());
+            assertFalse(lock.isReadLocked());
+            assertEquals(0, lock.getReadLockCount());
+            writeUnlocker.accept(lock, s);
+            assertUnlocked(lock);
+        }
     }
 
     /**
-     * unlock releases either a read or write lock
+     * read-locking, then unlocking, an unlocked lock succeed
      */
-    public void testUnlock() {
+    public void testReadLock_lockUnlock() {
         StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        lock.unlock(s);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        lock.unlock(rs);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
+
+        for (Function<StampedLock, Long> readLocker : readLockers())
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            long s = 42;
+            for (int i = 0; i < 2; i++) {
+                s = assertValid(lock, readLocker.apply(lock));
+                assertFalse(lock.isWriteLocked());
+                assertTrue(lock.isReadLocked());
+                assertEquals(i + 1, lock.getReadLockCount());
+            }
+            for (int i = 0; i < 2; i++) {
+                assertFalse(lock.isWriteLocked());
+                assertTrue(lock.isReadLocked());
+                assertEquals(2 - i, lock.getReadLockCount());
+                readUnlocker.accept(lock, s);
+            }
+            assertUnlocked(lock);
+        }
     }
 
     /**
-     * tryUnlockRead/Write succeeds if locked in associated mode else
-     * returns false
+     * tryUnlockWrite fails if not write locked
      */
-    public void testTryUnlock() {
+    public void testTryUnlockWrite_failure() {
         StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        assertFalse(lock.tryUnlockRead());
-        assertTrue(lock.tryUnlockWrite());
         assertFalse(lock.tryUnlockWrite());
-        assertFalse(lock.tryUnlockRead());
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        assertFalse(lock.tryUnlockWrite());
-        assertTrue(lock.tryUnlockRead());
-        assertFalse(lock.tryUnlockRead());
-        assertFalse(lock.tryUnlockWrite());
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
+
+        for (Function<StampedLock, Long> readLocker : readLockers())
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            long s = assertValid(lock, readLocker.apply(lock));
+            assertFalse(lock.tryUnlockWrite());
+            assertTrue(lock.isReadLocked());
+            readUnlocker.accept(lock, s);
+            assertUnlocked(lock);
+        }
     }
 
     /**
-     * write-unlocking an unlocked lock throws IllegalMonitorStateException
+     * tryUnlockRead fails if not read locked
      */
-    public void testWriteUnlock_IMSE() {
+    public void testTryUnlockRead_failure() {
         StampedLock lock = new StampedLock();
-        try {
-            lock.unlockWrite(0L);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
+        assertFalse(lock.tryUnlockRead());
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers())
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
+            long s = writeLocker.apply(lock);
+            assertFalse(lock.tryUnlockRead());
+            assertTrue(lock.isWriteLocked());
+            writeUnlocker.accept(lock, s);
+            assertUnlocked(lock);
+        }
     }
 
     /**
-     * write-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testWriteUnlock_IMSE2() {
-        StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        lock.unlockWrite(s);
-        try {
-            lock.unlockWrite(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * write-unlocking after readlock throws IllegalMonitorStateException
-     */
-    public void testWriteUnlock_IMSE3() {
-        StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        try {
-            lock.unlockWrite(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE() {
-        StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        lock.unlockRead(s);
-        try {
-            lock.unlockRead(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE2() {
-        StampedLock lock = new StampedLock();
-        try {
-            lock.unlockRead(0L);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking after writeLock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE3() {
-        StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        try {
-            lock.unlockRead(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * validate(0) fails
+     * validate(0L) fails
      */
     public void testValidate0() {
         StampedLock lock = new StampedLock();
@@ -265,29 +248,24 @@
     }
 
     /**
-     * A stamp obtained from a successful lock operation validates
+     * A stamp obtained from a successful lock operation validates while the lock is held
      */
     public void testValidate() throws InterruptedException {
         StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        s = lock.readLock();
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
+
+        for (Function<StampedLock, Long> readLocker : readLockers())
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            long s = assertNonZero(readLocker.apply(lock));
+            assertTrue(lock.validate(s));
+            readUnlocker.accept(lock, s);
+        }
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers())
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
+            long s = assertNonZero(writeLocker.apply(lock));
+            assertTrue(lock.validate(s));
+            writeUnlocker.accept(lock, s);
+        }
     }
 
     /**
@@ -295,124 +273,190 @@
      */
     public void testValidate2() throws InterruptedException {
         StampedLock lock = new StampedLock();
-        long s;
-        assertTrue((s = lock.writeLock()) != 0L);
+        long s = assertNonZero(lock.writeLock());
         assertTrue(lock.validate(s));
         assertFalse(lock.validate(lock.tryWriteLock()));
-        assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS)));
+        assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS)));
         assertFalse(lock.validate(lock.tryReadLock()));
-        assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS)));
+        assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS)));
         assertFalse(lock.validate(lock.tryOptimisticRead()));
         lock.unlockWrite(s);
     }
 
+    void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) {
+        for (Action action : actions) {
+            Thread.currentThread().interrupt();
+            try {
+                action.run();
+                shouldThrow();
+            }
+            catch (InterruptedException success) {}
+            catch (Throwable fail) { threadUnexpectedException(fail); }
+            assertFalse(Thread.interrupted());
+        }
+    }
+
     /**
-     * writeLockInterruptibly is interruptible
+     * interruptible operations throw InterruptedException when pre-interrupted
      */
-    public void testWriteLockInterruptibly_Interruptible()
-            throws InterruptedException {
+    public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() {
+        final CountDownLatch running = new CountDownLatch(1);
+        final StampedLock lock = new StampedLock();
+
+        Action[] interruptibleLockActions = {
+            () -> lock.writeLockInterruptibly(),
+            () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS),
+            () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
+            () -> lock.readLockInterruptibly(),
+            () -> lock.tryReadLock(Long.MIN_VALUE, DAYS),
+            () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
+            () -> lock.asWriteLock().lockInterruptibly(),
+            () -> lock.asWriteLock().tryLock(0L, DAYS),
+            () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
+            () -> lock.asReadLock().lockInterruptibly(),
+            () -> lock.asReadLock().tryLock(0L, DAYS),
+            () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
+        };
+        shuffle(interruptibleLockActions);
+
+        assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
+        {
+            long s = lock.writeLock();
+            assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
+            lock.unlockWrite(s);
+        }
+        {
+            long s = lock.readLock();
+            assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
+            lock.unlockRead(s);
+        }
+    }
+
+    void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) {
+        int n = actions.length;
+        Future<?>[] futures = new Future<?>[n];
+        CountDownLatch threadsStarted = new CountDownLatch(n);
+        CountDownLatch done = new CountDownLatch(n);
+
+        for (int i = 0; i < n; i++) {
+            Action action = actions[i];
+            futures[i] = cachedThreadPool.submit(new CheckedRunnable() {
+                public void realRun() throws Throwable {
+                    threadsStarted.countDown();
+                    try {
+                        action.run();
+                        shouldThrow();
+                    }
+                    catch (InterruptedException success) {}
+                    catch (Throwable fail) { threadUnexpectedException(fail); }
+                    assertFalse(Thread.interrupted());
+                    done.countDown();
+                }});
+        }
+
+        await(threadsStarted);
+        assertEquals(n, done.getCount());
+        for (Future<?> future : futures) // Interrupt all the tasks
+            future.cancel(true);
+        await(done);
+    }
+
+    /**
+     * interruptible operations throw InterruptedException when write locked and interrupted
+     */
+    public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
         final CountDownLatch running = new CountDownLatch(1);
         final StampedLock lock = new StampedLock();
         long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.writeLockInterruptibly();
-            }});
 
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
+        Action[] interruptibleLockBlockingActions = {
+            () -> lock.writeLockInterruptibly(),
+            () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
+            () -> lock.readLockInterruptibly(),
+            () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
+            () -> lock.asWriteLock().lockInterruptibly(),
+            () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
+            () -> lock.asReadLock().lockInterruptibly(),
+            () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
+        };
+        shuffle(interruptibleLockBlockingActions);
+
+        assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
     }
 
     /**
-     * timed tryWriteLock is interruptible
+     * interruptible operations throw InterruptedException when read locked and interrupted
      */
-    public void testWriteTryLock_Interruptible() throws InterruptedException {
+    public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
         final CountDownLatch running = new CountDownLatch(1);
         final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS);
-            }});
+        long s = lock.readLock();
 
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
+        Action[] interruptibleLockBlockingActions = {
+            () -> lock.writeLockInterruptibly(),
+            () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
+            () -> lock.asWriteLock().lockInterruptibly(),
+            () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
+        };
+        shuffle(interruptibleLockBlockingActions);
+
+        assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
     }
 
     /**
-     * readLockInterruptibly is interruptible
+     * Non-interruptible operations ignore and preserve interrupt status
      */
-    public void testReadLockInterruptibly_Interruptible()
-            throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
+    public void testNonInterruptibleOperationsIgnoreInterrupts() {
         final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.readLockInterruptibly();
-            }});
+        Thread.currentThread().interrupt();
 
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            long s = assertValid(lock, lock.readLock());
+            readUnlocker.accept(lock, s);
+            s = assertValid(lock, lock.tryReadLock());
+            readUnlocker.accept(lock, s);
+        }
 
-    /**
-     * timed tryReadLock is interruptible
-     */
-    public void testReadTryLock_Interruptible() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS);
-            }});
+        lock.asReadLock().lock();
+        lock.asReadLock().unlock();
 
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
+            long s = assertValid(lock, lock.writeLock());
+            writeUnlocker.accept(lock, s);
+            s = assertValid(lock, lock.tryWriteLock());
+            writeUnlocker.accept(lock, s);
+        }
+
+        lock.asWriteLock().lock();
+        lock.asWriteLock().unlock();
+
+        assertTrue(Thread.interrupted());
     }
 
     /**
      * tryWriteLock on an unlocked lock succeeds
      */
-    public void testWriteTryLock() {
+    public void testTryWriteLock() {
         final StampedLock lock = new StampedLock();
         long s = lock.tryWriteLock();
         assertTrue(s != 0L);
         assertTrue(lock.isWriteLocked());
-        long s2 = lock.tryWriteLock();
-        assertEquals(s2, 0L);
+        assertEquals(0L, lock.tryWriteLock());
         releaseWriteLock(lock, s);
     }
 
     /**
      * tryWriteLock fails if locked
      */
-    public void testWriteTryLockWhenLocked() {
+    public void testTryWriteLockWhenLocked() {
         final StampedLock lock = new StampedLock();
         long s = lock.writeLock();
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() {
-                long ws = lock.tryWriteLock();
-                assertTrue(ws == 0L);
+                assertEquals(0L, lock.tryWriteLock());
             }});
 
+        assertEquals(0L, lock.tryWriteLock());
         awaitTermination(t);
         releaseWriteLock(lock, s);
     }
@@ -420,15 +464,15 @@
     /**
      * tryReadLock fails if write-locked
      */
-    public void testReadTryLockWhenLocked() {
+    public void testTryReadLockWhenLocked() {
         final StampedLock lock = new StampedLock();
         long s = lock.writeLock();
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() {
-                long rs = lock.tryReadLock();
-                assertEquals(rs, 0L);
+                assertEquals(0L, lock.tryReadLock());
             }});
 
+        assertEquals(0L, lock.tryReadLock());
         awaitTermination(t);
         releaseWriteLock(lock, s);
     }
@@ -442,13 +486,20 @@
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
                 long s2 = lock.tryReadLock();
-                assertTrue(s2 != 0L);
+                assertValid(lock, s2);
                 lock.unlockRead(s2);
                 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
-                assertTrue(s3 != 0L);
+                assertValid(lock, s3);
                 lock.unlockRead(s3);
                 long s4 = lock.readLock();
+                assertValid(lock, s4);
                 lock.unlockRead(s4);
+                lock.asReadLock().lock();
+                lock.asReadLock().unlock();
+                lock.asReadLock().lockInterruptibly();
+                lock.asReadLock().unlock();
+                lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
+                lock.asReadLock().unlock();
             }});
 
         awaitTermination(t);
@@ -470,7 +521,7 @@
             }});
 
         running.await();
-        waitForThreadToEnterWaitState(t, 100);
+        waitForThreadToEnterWaitState(t, MEDIUM_DELAY_MS);
         assertFalse(lock.isWriteLocked());
         lock.unlockRead(rs);
         awaitTermination(t);
@@ -497,6 +548,7 @@
                 lock.unlockWrite(ws);
             }});
 
+        assertTrue(lock.isReadLocked());
         assertFalse(lock.isWriteLocked());
         lock.unlockRead(s);
         awaitTermination(t2);
@@ -508,25 +560,31 @@
      */
     public void testReadAfterWriteLock() {
         final StampedLock lock = new StampedLock();
+        final CountDownLatch threadsStarted = new CountDownLatch(2);
         final long s = lock.writeLock();
         Thread t1 = newStartedThread(new CheckedRunnable() {
             public void realRun() {
+                threadsStarted.countDown();
                 long rs = lock.readLock();
                 lock.unlockRead(rs);
             }});
         Thread t2 = newStartedThread(new CheckedRunnable() {
             public void realRun() {
+                threadsStarted.countDown();
                 long rs = lock.readLock();
                 lock.unlockRead(rs);
             }});
 
+        await(threadsStarted);
+        waitForThreadToEnterWaitState(t1, MEDIUM_DELAY_MS);
+        waitForThreadToEnterWaitState(t2, MEDIUM_DELAY_MS);
         releaseWriteLock(lock, s);
         awaitTermination(t1);
         awaitTermination(t2);
     }
 
     /**
-     * tryReadLock succeeds if readlocked but not writelocked
+     * tryReadLock succeeds if read locked but not write locked
      */
     public void testTryLockWhenReadLocked() {
         final StampedLock lock = new StampedLock();
@@ -534,7 +592,7 @@
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() {
                 long rs = lock.tryReadLock();
-                threadAssertTrue(rs != 0L);
+                assertValid(lock, rs);
                 lock.unlockRead(rs);
             }});
 
@@ -543,15 +601,14 @@
     }
 
     /**
-     * tryWriteLock fails when readlocked
+     * tryWriteLock fails when read locked
      */
-    public void testWriteTryLockWhenReadLocked() {
+    public void testTryWriteLockWhenReadLocked() {
         final StampedLock lock = new StampedLock();
         long s = lock.readLock();
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() {
-                long ws = lock.tryWriteLock();
-                threadAssertEquals(ws, 0L);
+                threadAssertEquals(0L, lock.tryWriteLock());
             }});
 
         awaitTermination(t);
@@ -559,86 +616,82 @@
     }
 
     /**
-     * timed tryWriteLock times out if locked
+     * timed lock operations time out if lock not available
      */
-    public void testWriteTryLock_Timeout() {
+    public void testTimedLock_Timeout() throws Exception {
+        ArrayList<Future<?>> futures = new ArrayList<>();
+
+        // Write locked
         final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
+        long stamp = lock.writeLock();
+        assertEquals(0L, lock.tryReadLock(0L, DAYS));
+        assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
+        assertFalse(lock.asReadLock().tryLock(0L, DAYS));
+        assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
+        assertEquals(0L, lock.tryWriteLock(0L, DAYS));
+        assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
+        assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
+        assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
+
+        futures.add(cachedThreadPool.submit(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
                 long startTime = System.nanoTime();
-                long timeoutMillis = 10;
-                long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS);
-                assertEquals(ws, 0L);
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            }});
+                assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            }}));
 
-        awaitTermination(t);
+        futures.add(cachedThreadPool.submit(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                long startTime = System.nanoTime();
+                assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            }}));
+
+        // Read locked
+        final StampedLock lock2 = new StampedLock();
+        long stamp2 = lock2.readLock();
+        assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
+        assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
+        assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
+        assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
+
+        futures.add(cachedThreadPool.submit(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                long startTime = System.nanoTime();
+                assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            }}));
+
+        for (Future<?> future : futures)
+            assertNull(future.get());
+
+        releaseWriteLock(lock, stamp);
+        releaseReadLock(lock2, stamp2);
+    }
+
+    /**
+     * writeLockInterruptibly succeeds if unlocked
+     */
+    public void testWriteLockInterruptibly() throws InterruptedException {
+        final StampedLock lock = new StampedLock();
+        long s = lock.writeLockInterruptibly();
+        assertTrue(lock.isWriteLocked());
         releaseWriteLock(lock, s);
     }
 
     /**
-     * timed tryReadLock times out if write-locked
-     */
-    public void testReadTryLock_Timeout() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
-                long timeoutMillis = 10;
-                long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS);
-                assertEquals(rs, 0L);
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            }});
-
-        awaitTermination(t);
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
-    }
-
-    /**
-     * writeLockInterruptibly succeeds if unlocked, else is interruptible
-     */
-    public void testWriteLockInterruptibly() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLockInterruptibly();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.writeLockInterruptibly();
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        assertTrue(lock.isWriteLocked());
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * readLockInterruptibly succeeds if lock free else is interruptible
+     * readLockInterruptibly succeeds if lock free
      */
     public void testReadLockInterruptibly() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
         final StampedLock lock = new StampedLock();
-        long s;
-        s = lock.readLockInterruptibly();
+
+        long s = assertValid(lock, lock.readLockInterruptibly());
+        assertTrue(lock.isReadLocked());
         lock.unlockRead(s);
-        s = lock.writeLockInterruptibly();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.readLockInterruptibly();
-            }});
 
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
+        lock.asReadLock().lockInterruptibly();
+        assertTrue(lock.isReadLocked());
+        lock.asReadLock().unlock();
     }
 
     /**
@@ -670,54 +723,39 @@
     }
 
     /**
-     * tryOptimisticRead succeeds and validates if unlocked, fails if locked
+     * tryOptimisticRead succeeds and validates if unlocked, fails if
+     * exclusively locked
      */
     public void testValidateOptimistic() throws InterruptedException {
         StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockRead(s);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockRead(s);
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
+
+        assertValid(lock, lock.tryOptimisticRead());
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers()) {
+            long s = assertValid(lock, writeLocker.apply(lock));
+            assertEquals(0L, lock.tryOptimisticRead());
+            releaseWriteLock(lock, s);
+        }
+
+        for (Function<StampedLock, Long> readLocker : readLockers()) {
+            long s = assertValid(lock, readLocker.apply(lock));
+            long p = assertValid(lock, lock.tryOptimisticRead());
+            releaseReadLock(lock, s);
+            assertTrue(lock.validate(p));
+        }
+
+        assertValid(lock, lock.tryOptimisticRead());
     }
 
     /**
      * tryOptimisticRead stamp does not validate if a write lock intervenes
      */
     public void testValidateOptimisticWriteLocked() {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue((s = lock.writeLock()) != 0L);
+        final StampedLock lock = new StampedLock();
+        final long p = assertValid(lock, lock.tryOptimisticRead());
+        final long s = assertValid(lock, lock.writeLock());
         assertFalse(lock.validate(p));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
+        assertEquals(0L, lock.tryOptimisticRead());
         assertTrue(lock.validate(s));
         lock.unlockWrite(s);
     }
@@ -730,8 +768,8 @@
             throws InterruptedException {
         final CountDownLatch running = new CountDownLatch(1);
         final StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
+        final long p = assertValid(lock, lock.tryOptimisticRead());
+
         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
             public void realRun() throws InterruptedException {
                 lock.writeLockInterruptibly();
@@ -741,228 +779,209 @@
 
         running.await();
         assertFalse(lock.validate(p));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
+        assertEquals(0L, lock.tryOptimisticRead());
         t.interrupt();
         awaitTermination(t);
     }
 
     /**
-     * tryConvertToOptimisticRead succeeds and validates if successfully locked,
+     * tryConvertToOptimisticRead succeeds and validates if successfully locked
      */
     public void testTryConvertToOptimisticRead() throws InterruptedException {
         StampedLock lock = new StampedLock();
-        long s, p;
+        long s, p, q;
         assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
 
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
+        s = assertValid(lock, lock.tryOptimisticRead());
         assertEquals(s, lock.tryConvertToOptimisticRead(s));
         assertTrue(lock.validate(s));
 
-        assertTrue((p = lock.readLock()) != 0L);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertEquals(s, lock.tryConvertToOptimisticRead(s));
-        assertTrue(lock.validate(s));
-        lock.unlockRead(p);
+        for (Function<StampedLock, Long> writeLocker : writeLockers()) {
+            s = assertValid(lock, writeLocker.apply(lock));
+            p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
+            assertFalse(lock.validate(s));
+            assertTrue(lock.validate(p));
+            assertUnlocked(lock);
+        }
 
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
+        for (Function<StampedLock, Long> readLocker : readLockers()) {
+            s = assertValid(lock, readLocker.apply(lock));
+            q = assertValid(lock, lock.tryOptimisticRead());
+            assertEquals(q, lock.tryConvertToOptimisticRead(q));
+            assertTrue(lock.validate(q));
+            assertTrue(lock.isReadLocked());
+            p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
+            assertTrue(lock.validate(p));
+            assertTrue(lock.validate(s));
+            assertUnlocked(lock);
+            assertEquals(q, lock.tryConvertToOptimisticRead(q));
+            assertTrue(lock.validate(q));
+        }
     }
 
     /**
-     * tryConvertToReadLock succeeds and validates if successfully locked
-     * or lock free;
+     * tryConvertToReadLock succeeds for valid stamps
      */
     public void testTryConvertToReadLock() throws InterruptedException {
         StampedLock lock = new StampedLock();
         long s, p;
 
-        assertFalse((p = lock.tryConvertToReadLock(0L)) != 0L);
+        assertEquals(0L, lock.tryConvertToReadLock(0L));
 
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
+        s = assertValid(lock, lock.tryOptimisticRead());
+        p = assertValid(lock, lock.tryConvertToReadLock(s));
         assertTrue(lock.isReadLocked());
         assertEquals(1, lock.getReadLockCount());
+        assertTrue(lock.validate(s));
         lock.unlockRead(p);
 
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
+        s = assertValid(lock, lock.tryOptimisticRead());
         lock.readLock();
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
+        p = assertValid(lock, lock.tryConvertToReadLock(s));
         assertTrue(lock.isReadLocked());
         assertEquals(2, lock.getReadLockCount());
         lock.unlockRead(p);
         lock.unlockRead(p);
+        assertUnlocked(lock);
 
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isReadLocked());
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(p);
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            for (Function<StampedLock, Long> writeLocker : writeLockers()) {
+                s = assertValid(lock, writeLocker.apply(lock));
+                p = assertValid(lock, lock.tryConvertToReadLock(s));
+                assertFalse(lock.validate(s));
+                assertTrue(lock.isReadLocked());
+                assertEquals(1, lock.getReadLockCount());
+                readUnlocker.accept(lock, p);
+            }
 
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertEquals(s, lock.tryConvertToReadLock(s));
-        assertTrue(lock.validate(s));
-        assertTrue(lock.isReadLocked());
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(s);
-
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(p);
-
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertEquals(s, lock.tryConvertToReadLock(s));
-        assertTrue(lock.validate(s));
-        assertTrue(lock.isReadLocked());
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(s);
-
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isReadLocked());
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(p);
-
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertEquals(s, lock.tryConvertToReadLock(s));
-        assertTrue(lock.validate(s));
-        assertTrue(lock.isReadLocked());
-        assertEquals(1, lock.getReadLockCount());
-        lock.unlockRead(s);
+            for (Function<StampedLock, Long> readLocker : readLockers()) {
+                s = assertValid(lock, readLocker.apply(lock));
+                assertEquals(s, lock.tryConvertToReadLock(s));
+                assertTrue(lock.validate(s));
+                assertTrue(lock.isReadLocked());
+                assertEquals(1, lock.getReadLockCount());
+                readUnlocker.accept(lock, s);
+            }
+        }
     }
 
     /**
-     * tryConvertToWriteLock succeeds and validates if successfully locked
-     * or lock free;
+     * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
      */
     public void testTryConvertToWriteLock() throws InterruptedException {
         StampedLock lock = new StampedLock();
         long s, p;
 
-        assertFalse((p = lock.tryConvertToWriteLock(0L)) != 0L);
+        assertEquals(0L, lock.tryConvertToWriteLock(0L));
 
         assertTrue((s = lock.tryOptimisticRead()) != 0L);
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
         assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
 
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertEquals(s, lock.tryConvertToWriteLock(s));
-        assertTrue(lock.validate(s));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
+            for (Function<StampedLock, Long> writeLocker : writeLockers()) {
+                s = assertValid(lock, writeLocker.apply(lock));
+                assertEquals(s, lock.tryConvertToWriteLock(s));
+                assertTrue(lock.validate(s));
+                assertTrue(lock.isWriteLocked());
+                writeUnlocker.accept(lock, s);
+            }
 
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(p);
+            for (Function<StampedLock, Long> readLocker : readLockers()) {
+                s = assertValid(lock, readLocker.apply(lock));
+                p = assertValid(lock, lock.tryConvertToWriteLock(s));
+                assertFalse(lock.validate(s));
+                assertTrue(lock.validate(p));
+                assertTrue(lock.isWriteLocked());
+                writeUnlocker.accept(lock, p);
+            }
+        }
 
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertEquals(s, lock.tryConvertToWriteLock(s));
-        assertTrue(lock.validate(s));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
-
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(p);
-
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(p);
-
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(p);
+        // failure if multiply read locked
+        for (Function<StampedLock, Long> readLocker : readLockers()) {
+            s = assertValid(lock, readLocker.apply(lock));
+            p = assertValid(lock, readLocker.apply(lock));
+            assertEquals(0L, lock.tryConvertToWriteLock(s));
+            assertTrue(lock.validate(s));
+            assertTrue(lock.validate(p));
+            assertEquals(2, lock.getReadLockCount());
+            lock.unlock(p);
+            lock.unlock(s);
+            assertUnlocked(lock);
+        }
     }
 
     /**
      * asWriteLock can be locked and unlocked
      */
-    public void testAsWriteLock() {
+    public void testAsWriteLock() throws Throwable {
         StampedLock sl = new StampedLock();
         Lock lock = sl.asWriteLock();
-        lock.lock();
-        assertFalse(lock.tryLock());
-        lock.unlock();
-        assertTrue(lock.tryLock());
+        for (Action locker : lockLockers(lock)) {
+            locker.run();
+            assertTrue(sl.isWriteLocked());
+            assertFalse(sl.isReadLocked());
+            assertFalse(lock.tryLock());
+            lock.unlock();
+            assertUnlocked(sl);
+        }
     }
 
     /**
      * asReadLock can be locked and unlocked
      */
-    public void testAsReadLock() {
+    public void testAsReadLock() throws Throwable {
         StampedLock sl = new StampedLock();
         Lock lock = sl.asReadLock();
-        lock.lock();
-        lock.unlock();
-        assertTrue(lock.tryLock());
+        for (Action locker : lockLockers(lock)) {
+            locker.run();
+            assertTrue(sl.isReadLocked());
+            assertFalse(sl.isWriteLocked());
+            assertEquals(1, sl.getReadLockCount());
+            locker.run();
+            assertTrue(sl.isReadLocked());
+            assertEquals(2, sl.getReadLockCount());
+            lock.unlock();
+            lock.unlock();
+            assertUnlocked(sl);
+        }
     }
 
     /**
      * asReadWriteLock.writeLock can be locked and unlocked
      */
-    public void testAsReadWriteLockWriteLock() {
+    public void testAsReadWriteLockWriteLock() throws Throwable {
         StampedLock sl = new StampedLock();
         Lock lock = sl.asReadWriteLock().writeLock();
-        lock.lock();
-        assertFalse(lock.tryLock());
-        lock.unlock();
-        assertTrue(lock.tryLock());
+        for (Action locker : lockLockers(lock)) {
+            locker.run();
+            assertTrue(sl.isWriteLocked());
+            assertFalse(sl.isReadLocked());
+            assertFalse(lock.tryLock());
+            lock.unlock();
+            assertUnlocked(sl);
+        }
     }
 
     /**
      * asReadWriteLock.readLock can be locked and unlocked
      */
-    public void testAsReadWriteLockReadLock() {
+    public void testAsReadWriteLockReadLock() throws Throwable {
         StampedLock sl = new StampedLock();
         Lock lock = sl.asReadWriteLock().readLock();
-        lock.lock();
-        lock.unlock();
-        assertTrue(lock.tryLock());
+        for (Action locker : lockLockers(lock)) {
+            locker.run();
+            assertTrue(sl.isReadLocked());
+            assertFalse(sl.isWriteLocked());
+            assertEquals(1, sl.getReadLockCount());
+            locker.run();
+            assertTrue(sl.isReadLocked());
+            assertEquals(2, sl.getReadLockCount());
+            lock.unlock();
+            lock.unlock();
+            assertUnlocked(sl);
+        }
     }
 
     /**
@@ -985,8 +1004,7 @@
         Runnable[] actions = {
             () -> {
                 StampedLock sl = new StampedLock();
-                long stamp = sl.tryOptimisticRead();
-                assertTrue(stamp != 0);
+                long stamp = assertValid(sl, sl.tryOptimisticRead());
                 sl.unlockRead(stamp);
             },
             () -> {
@@ -1003,21 +1021,21 @@
             },
             () -> {
                 StampedLock sl = new StampedLock();
-                long stamp = sl.tryOptimisticRead();
                 sl.readLock();
+                long stamp = assertValid(sl, sl.tryOptimisticRead());
                 sl.unlockRead(stamp);
             },
             () -> {
                 StampedLock sl = new StampedLock();
-                long stamp = sl.tryOptimisticRead();
                 sl.readLock();
+                long stamp = assertValid(sl, sl.tryOptimisticRead());
                 sl.unlock(stamp);
             },
 
             () -> {
                 StampedLock sl = new StampedLock();
                 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
-                assertTrue(stamp != 0);
+                assertValid(sl, stamp);
                 sl.writeLock();
                 sl.unlockWrite(stamp);
             },
@@ -1043,7 +1061,7 @@
             () -> {
                 StampedLock sl = new StampedLock();
                 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                assertTrue(stamp != 0);
+                assertValid(sl, stamp);
                 sl.writeLock();
                 sl.unlockWrite(stamp);
             },
@@ -1063,7 +1081,7 @@
                 StampedLock sl = new StampedLock();
                 sl.readLock();
                 long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                assertTrue(stamp != 0);
+                assertValid(sl, stamp);
                 sl.readLock();
                 sl.unlockRead(stamp);
             },
@@ -1106,100 +1124,84 @@
     }
 
     /**
-     * Invalid write stamps result in IllegalMonitorStateException
+     * Invalid stamps result in IllegalMonitorStateException
      */
-    public void testInvalidWriteStampsThrowIllegalMonitorStateException() {
-        List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
-        writeLockers.add((sl) -> sl.writeLock());
-        writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl));
-        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
-        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0, DAYS));
+    public void testInvalidStampsThrowIllegalMonitorStateException() {
+        final StampedLock sl = new StampedLock();
 
-        List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>();
-        writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp));
-        writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite()));
-        writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock());
-        writeUnlockers.add((sl, stamp) -> sl.unlock(stamp));
+        assertThrows(IllegalMonitorStateException.class,
+                     () -> sl.unlockWrite(0L),
+                     () -> sl.unlockRead(0L),
+                     () -> sl.unlock(0L));
 
-        List<Consumer<StampedLock>> mutaters = new ArrayList<>();
-        mutaters.add((sl) -> {});
-        mutaters.add((sl) -> sl.readLock());
-        for (Function<StampedLock, Long> writeLocker : writeLockers)
-            mutaters.add((sl) -> writeLocker.apply(sl));
+        final long optimisticStamp = sl.tryOptimisticRead();
+        final long readStamp = sl.readLock();
+        sl.unlockRead(readStamp);
+        final long writeStamp = sl.writeLock();
+        sl.unlockWrite(writeStamp);
+        assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
+        final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
+        final Runnable assertNoLongerValidStampsThrow = () -> {
+            for (long noLongerValidStamp : noLongerValidStamps)
+                assertThrows(IllegalMonitorStateException.class,
+                             () -> sl.unlockWrite(noLongerValidStamp),
+                             () -> sl.unlockRead(noLongerValidStamp),
+                             () -> sl.unlock(noLongerValidStamp));
+        };
+        assertNoLongerValidStampsThrow.run();
 
-        for (Function<StampedLock, Long> writeLocker : writeLockers)
-        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers)
-        for (Consumer<StampedLock> mutater : mutaters) {
-            final StampedLock sl = new StampedLock();
+        for (Function<StampedLock, Long> readLocker : readLockers())
+        for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
+            final long stamp = readLocker.apply(sl);
+            assertValid(sl, stamp);
+            assertNoLongerValidStampsThrow.run();
+            assertThrows(IllegalMonitorStateException.class,
+                         () -> sl.unlockWrite(stamp),
+                         () -> sl.unlockRead(sl.tryOptimisticRead()),
+                         () -> sl.unlockRead(0L));
+            readUnlocker.accept(sl, stamp);
+            assertUnlocked(sl);
+            assertNoLongerValidStampsThrow.run();
+        }
+
+        for (Function<StampedLock, Long> writeLocker : writeLockers())
+        for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
             final long stamp = writeLocker.apply(sl);
-            assertTrue(stamp != 0L);
+            assertValid(sl, stamp);
+            assertNoLongerValidStampsThrow.run();
             assertThrows