Merge
authorlana
Thu, 25 Aug 2016 22:35:56 +0000
changeset 40553 39bbc4d59ba8
parent 40526 52640b6b26b4 (current diff)
parent 40552 3c63a28172cc (diff)
child 40554 d395be393449
Merge
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java	Thu Aug 25 22:35:56 2016 +0000
@@ -986,8 +986,9 @@
             if (padding != null) {
                 int padStart = padding.unpad(outWithPadding, 0, outLen);
                 if (padStart < 0) {
-                    throw new BadPaddingException("Given final block not "
-                                                  + "properly padded");
+                    throw new BadPaddingException("Given final block not " +
+                    "properly padded. Such issues can arise if a bad key " +
+                    "is used during decryption.");
                 }
                 outLen = padStart;
             }
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Thu Aug 25 22:35:56 2016 +0000
@@ -331,12 +331,6 @@
      * Note that this method does not check whether the requested class
      * is accessible to its caller.
      *
-     * <p> If the {@code loader} is {@code null}, and a security
-     * manager is present, and the caller's class loader is not null, then this
-     * method calls the security manager's {@code checkPermission} method
-     * with a {@code RuntimePermission("getClassLoader")} permission to
-     * ensure it's ok to access the bootstrap class loader.
-     *
      * @param name       fully qualified name of the desired class
      * @param initialize if {@code true} the class will be initialized.
      *                   See Section 12.4 of <em>The Java Language Specification</em>.
@@ -348,6 +342,11 @@
      *            by this method fails
      * @exception ClassNotFoundException if the class cannot be located by
      *            the specified class loader
+     * @exception SecurityException
+     *            if a security manager is present, and the {@code loader} is
+     *            {@code null}, and the caller's class loader is not
+     *            {@code null}, and the caller does not have the
+     *            {@link RuntimePermission}{@code ("getClassLoader")}
      *
      * @see       java.lang.Class#forName(String)
      * @see       java.lang.ClassLoader
@@ -782,22 +781,17 @@
      * null in such implementations if this class was loaded by the bootstrap
      * class loader.
      *
-     * <p> If a security manager is present, and the caller's class loader is
-     * not null and the caller's class loader is not the same as or an ancestor of
-     * the class loader for the class whose class loader is requested, then
-     * this method calls the security manager's {@code checkPermission}
-     * method with a {@code RuntimePermission("getClassLoader")}
-     * permission to ensure it's ok to access the class loader for the class.
-     *
      * <p>If this object
      * represents a primitive type or void, null is returned.
      *
      * @return  the class loader that loaded the class or interface
      *          represented by this object.
-     * @throws SecurityException
-     *    if a security manager exists and its
-     *    {@code checkPermission} method denies
-     *    access to the class loader for the class.
+     * @throws  SecurityException
+     *          if a security manager is present, and the caller's class loader
+     *          is not {@code null} and is not the same as or an ancestor of the
+     *          class loader for the class whose class loader is requested,
+     *          and the caller does not have the
+     *          {@link RuntimePermission}{@code ("getClassLoader")}
      * @see java.lang.ClassLoader
      * @see SecurityManager#checkPermission
      * @see java.lang.RuntimePermission
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1537,22 +1537,13 @@
      * will return <tt>null</tt> in such implementations if this class loader's
      * parent is the bootstrap class loader.
      *
-     * <p> If a security manager is present, and the invoker's class loader is
-     * not <tt>null</tt> and is not an ancestor of this class loader, then this
-     * method invokes the security manager's {@link
-     * SecurityManager#checkPermission(java.security.Permission)
-     * <tt>checkPermission</tt>} method with a {@link
-     * RuntimePermission#RuntimePermission(String)
-     * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
-     * access to the parent class loader is permitted.  If not, a
-     * <tt>SecurityException</tt> will be thrown.  </p>
-     *
      * @return  The parent <tt>ClassLoader</tt>
      *
      * @throws  SecurityException
-     *          If a security manager exists and its <tt>checkPermission</tt>
-     *          method doesn't allow access to this class loader's parent class
-     *          loader.
+     *          If a security manager is present, and the caller's class loader
+     *          is not {@code null} and is not an ancestor of this class loader,
+     *          and the caller does not have the
+     *          {@link RuntimePermission}{@code ("getClassLoader")}
      *
      * @since  1.2
      */
@@ -1590,12 +1581,11 @@
      * @return  The platform {@code ClassLoader}.
      *
      * @throws  SecurityException
-     *          If a security manager exists and the caller's class loader is
-     *          not {@code null} and the caller's class loader is not the same
+     *          If a security manager is present, and the caller's class loader is
+     *          not {@code null}, and the caller's class loader is not the same
      *          as or an ancestor of the platform class loader,
-     *          and the {@link SecurityManager#checkPermission(java.security.Permission)
-     *          checkPermission} method denies {@code RuntimePermission("getClassLoader")}
-     *          to access the platform class loader.
+     *          and the caller does not have the
+     *          {@link RuntimePermission}{@code ("getClassLoader")}
      *
      * @since 9
      */
@@ -1636,17 +1626,6 @@
      * If circular initialization of the system class loader is detected then
      * an unspecified error or exception is thrown.
      *
-     * <p> If a security manager is present, and the invoker's class loader is
-     * not <tt>null</tt> and the invoker's class loader is not the same as or
-     * an ancestor of the system class loader, then this method invokes the
-     * security manager's {@link
-     * SecurityManager#checkPermission(java.security.Permission)
-     * <tt>checkPermission</tt>} method with a {@link
-     * RuntimePermission#RuntimePermission(String)
-     * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
-     * access to the system class loader.  If not, a
-     * <tt>SecurityException</tt> will be thrown.  </p>
-     *
      * @implNote The system property to override the system class loader is not
      * examined until the VM is almost fully initialized. Code that executes
      * this method during startup should take care not to cache the return
@@ -1656,8 +1635,10 @@
      *          <tt>null</tt> if none
      *
      * @throws  SecurityException
-     *          If a security manager exists and its <tt>checkPermission</tt>
-     *          method doesn't allow access to the system class loader.
+     *          If a security manager is present, and the caller's class loader
+     *          is not {@code null} and is not the same as or an ancestor of the
+     *          system class loader, and the caller does not have the
+     *          {@link RuntimePermission}{@code ("getClassLoader")}
      *
      * @throws  IllegalStateException
      *          If invoked recursively during the construction of the class
--- a/jdk/src/java.base/share/classes/java/lang/Math.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1370,8 +1370,13 @@
      * result is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code float} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value:<br>
+     * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
@@ -1389,8 +1394,13 @@
      * is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code double} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value:<br>
+     * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1070,8 +1070,13 @@
      * result is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code float} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value: <br>
+     * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
@@ -1089,8 +1094,13 @@
      * is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code double} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value: <br>
+     * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1507,28 +1507,25 @@
     }
 
     /**
-     * Returns the context ClassLoader for this Thread. The context
-     * ClassLoader is provided by the creator of the thread for use
+     * Returns the context {@code ClassLoader} for this thread. The context
+     * {@code ClassLoader} is provided by the creator of the thread for use
      * by code running in this thread when loading classes and resources.
      * If not {@linkplain #setContextClassLoader set}, the default is the
-     * ClassLoader context of the parent Thread. The context ClassLoader of the
+     * {@code ClassLoader} context of the parent thread. The context
+     * {@code ClassLoader} of the
      * primordial thread is typically set to the class loader used to load the
      * application.
      *
-     * <p>If a security manager is present, and the invoker's class loader is not
-     * {@code null} and is not the same as or an ancestor of the context class
-     * loader, then this method invokes the security manager's {@link
-     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
-     * method with a {@link RuntimePermission RuntimePermission}{@code
-     * ("getClassLoader")} permission to verify that retrieval of the context
-     * class loader is permitted.
      *
-     * @return  the context ClassLoader for this Thread, or {@code null}
+     * @return  the context {@code ClassLoader} for this thread, or {@code null}
      *          indicating the system class loader (or, failing that, the
      *          bootstrap class loader)
      *
      * @throws  SecurityException
-     *          if the current thread cannot get the context ClassLoader
+     *          if a security manager is present, and the caller's class loader
+     *          is not {@code null} and is not the same as or an ancestor of the
+     *          context class loader, and the caller does not have the
+     *          {@link RuntimePermission}{@code ("getClassLoader")}
      *
      * @since 1.2
      */
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Aug 25 22:35:56 2016 +0000
@@ -492,7 +492,7 @@
     }
 
     // Caching machinery for field accessors:
-    private static final byte
+    static final byte
             AF_GETFIELD        = 0,
             AF_PUTFIELD        = 1,
             AF_GETSTATIC       = 2,
@@ -502,7 +502,7 @@
             AF_LIMIT           = 6;
     // Enumerate the different field kinds using Wrapper,
     // with an extra case added for checked references.
-    private static final int
+    static final int
             FT_LAST_WRAPPER    = Wrapper.COUNT-1,
             FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
             FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
@@ -515,7 +515,7 @@
     @Stable
     private static final LambdaForm[] ACCESSOR_FORMS
             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
-    private static int ftypeKind(Class<?> ftype) {
+    static int ftypeKind(Class<?> ftype) {
         if (ftype.isPrimitive())
             return Wrapper.forPrimitiveType(ftype).ordinal();
         else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
@@ -566,7 +566,64 @@
 
     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 
-    private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
+    private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
+        if (isGetter) {
+            if (isVolatile) {
+                switch (wrapper) {
+                    case BOOLEAN: return GET_BOOLEAN_VOLATILE;
+                    case BYTE:    return GET_BYTE_VOLATILE;
+                    case SHORT:   return GET_SHORT_VOLATILE;
+                    case CHAR:    return GET_CHAR_VOLATILE;
+                    case INT:     return GET_INT_VOLATILE;
+                    case LONG:    return GET_LONG_VOLATILE;
+                    case FLOAT:   return GET_FLOAT_VOLATILE;
+                    case DOUBLE:  return GET_DOUBLE_VOLATILE;
+                    case OBJECT:  return GET_OBJECT_VOLATILE;
+                }
+            } else {
+                switch (wrapper) {
+                    case BOOLEAN: return GET_BOOLEAN;
+                    case BYTE:    return GET_BYTE;
+                    case SHORT:   return GET_SHORT;
+                    case CHAR:    return GET_CHAR;
+                    case INT:     return GET_INT;
+                    case LONG:    return GET_LONG;
+                    case FLOAT:   return GET_FLOAT;
+                    case DOUBLE:  return GET_DOUBLE;
+                    case OBJECT:  return GET_OBJECT;
+                }
+            }
+        } else {
+            if (isVolatile) {
+                switch (wrapper) {
+                    case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
+                    case BYTE:    return PUT_BYTE_VOLATILE;
+                    case SHORT:   return PUT_SHORT_VOLATILE;
+                    case CHAR:    return PUT_CHAR_VOLATILE;
+                    case INT:     return PUT_INT_VOLATILE;
+                    case LONG:    return PUT_LONG_VOLATILE;
+                    case FLOAT:   return PUT_FLOAT_VOLATILE;
+                    case DOUBLE:  return PUT_DOUBLE_VOLATILE;
+                    case OBJECT:  return PUT_OBJECT_VOLATILE;
+                }
+            } else {
+                switch (wrapper) {
+                    case BOOLEAN: return PUT_BOOLEAN;
+                    case BYTE:    return PUT_BYTE;
+                    case SHORT:   return PUT_SHORT;
+                    case CHAR:    return PUT_CHAR;
+                    case INT:     return PUT_INT;
+                    case LONG:    return PUT_LONG;
+                    case FLOAT:   return PUT_FLOAT;
+                    case DOUBLE:  return PUT_DOUBLE;
+                    case OBJECT:  return PUT_OBJECT;
+                }
+            }
+        }
+        throw new AssertionError("Invalid arguments");
+    }
+
+    static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
         boolean isStatic  = (formOp >= AF_GETSTATIC);
         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
@@ -576,24 +633,14 @@
         assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
 
         // getObject, putIntVolatile, etc.
-        StringBuilder nameBuilder = new StringBuilder();
-        if (isGetter) {
-            nameBuilder.append("get");
-        } else {
-            nameBuilder.append("put");
-        }
-        nameBuilder.append(fw.primitiveSimpleName());
-        nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
-        if (isVolatile) {
-            nameBuilder.append("Volatile");
-        }
+        Kind kind = getFieldKind(isGetter, isVolatile, fw);
 
         MethodType linkerType;
         if (isGetter)
             linkerType = MethodType.methodType(ft, Object.class, long.class);
         else
             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
-        MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
+        MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
         try {
             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
         } catch (ReflectiveOperationException ex) {
@@ -620,6 +667,7 @@
         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
+        final int U_HOLDER  = nameCursor++;  // UNSAFE holder
         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
         final int LINKER_CALL = nameCursor++;
@@ -632,7 +680,7 @@
             names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
         assert(outArgs.length == (isGetter ? 3 : 4));
-        outArgs[0] = UNSAFE;
+        outArgs[0] = names[U_HOLDER] = new Name(NF_UNSAFE);
         if (isStatic) {
             outArgs[1] = names[F_HOLDER]  = new Name(NF_staticBase, names[DMH_THIS]);
             outArgs[2] = names[F_OFFSET]  = new Name(NF_staticOffset, names[DMH_THIS]);
@@ -650,6 +698,7 @@
         for (Name n : names)  assert(n != null);
         // add some detail to the lambdaForm debugname,
         // significant only for debugging
+        StringBuilder nameBuilder = new StringBuilder(kind.methodName);
         if (isStatic) {
             nameBuilder.append("Static");
         } else {
@@ -657,7 +706,12 @@
         }
         if (needsCast)  nameBuilder.append("Cast");
         if (needsInit)  nameBuilder.append("Init");
-        return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+        if (needsCast || needsInit) {
+            // can't use the pre-generated form when casting and/or initializing
+            return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+        } else {
+            return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind);
+        }
     }
 
     /**
@@ -674,7 +728,8 @@
             NF_staticOffset,
             NF_checkCast,
             NF_allocateInstance,
-            NF_constructorMethod;
+            NF_constructorMethod,
+            NF_UNSAFE;
     static {
         try {
             NamedFunction nfs[] = {
@@ -697,7 +752,9 @@
                     NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
                             .getDeclaredMethod("allocateInstance", Object.class)),
                     NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
-                            .getDeclaredMethod("constructorMethod", Object.class))
+                            .getDeclaredMethod("constructorMethod", Object.class)),
+                    NF_UNSAFE = new NamedFunction(new MemberName(MethodHandleStatics.class
+                            .getDeclaredField("UNSAFE")))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java	Thu Aug 25 22:35:56 2016 +0000
@@ -28,9 +28,11 @@
 import java.util.Map;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
-
 import java.util.ArrayList;
 import java.util.HashSet;
+import sun.invoke.util.Wrapper;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
 
 /**
  * Helper class to assist the GenerateJLIClassesPlugin to get access to
@@ -66,14 +68,38 @@
 
     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]);
-            names[i] = forms[i].kind.defaultLambdaName;
+        ArrayList<LambdaForm> forms = new ArrayList<>();
+        ArrayList<String> names = new ArrayList<>();
+        for (int i = 0; i < methodTypes.length; i++) {
+            LambdaForm form = DirectMethodHandle
+                    .makePreparedLambdaForm(methodTypes[i], types[i]);
+            forms.add(form);
+            names.add(form.kind.defaultLambdaName);
         }
-        return generateCodeBytesForLFs(className, names, forms);
+        for (Wrapper wrapper : Wrapper.values()) {
+            if (wrapper == Wrapper.VOID) {
+                continue;
+            }
+            for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
+                int ftype = DirectMethodHandle.ftypeKind(wrapper.primitiveType());
+                LambdaForm form = DirectMethodHandle
+                        .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
+                if (form.kind != LambdaForm.Kind.GENERIC) {
+                    forms.add(form);
+                    names.add(form.kind.defaultLambdaName);
+                }
+                // volatile
+                form = DirectMethodHandle
+                        .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
+                if (form.kind != LambdaForm.Kind.GENERIC) {
+                    forms.add(form);
+                    names.add(form.kind.defaultLambdaName);
+                }
+            }
+        }
+        return generateCodeBytesForLFs(className,
+                names.toArray(new String[0]),
+                forms.toArray(new LambdaForm[0]));
     }
 
     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
@@ -107,6 +133,34 @@
                 forms.toArray(new LambdaForm[0]));
     }
 
+    static byte[] generateInvokersHolderClassBytes(String className,
+            MethodType[] methodTypes) {
+
+        HashSet<MethodType> dedupSet = new HashSet<>();
+        ArrayList<LambdaForm> forms = new ArrayList<>();
+        ArrayList<String> names = new ArrayList<>();
+        int[] types = {
+            MethodTypeForm.LF_EX_LINKER,
+            MethodTypeForm.LF_EX_INVOKER,
+            MethodTypeForm.LF_GEN_LINKER,
+            MethodTypeForm.LF_GEN_INVOKER
+        };
+        for (int i = 0; i < methodTypes.length; i++) {
+            // generate methods representing invokers of the specified type
+            if (dedupSet.add(methodTypes[i])) {
+                for (int type : types) {
+                    LambdaForm invokerForm = Invokers.invokeHandleForm(methodTypes[i],
+                            /*customized*/false, type);
+                    forms.add(invokerForm);
+                    names.add(invokerForm.kind.defaultLambdaName);
+                }
+            }
+        }
+        return generateCodeBytesForLFs(className,
+                names.toArray(new String[0]),
+                forms.toArray(new LambdaForm[0]));
+    }
+
     /*
      * Generate customized code for a set of LambdaForms of specified types into
      * a class with a specified name.
@@ -166,4 +220,5 @@
                          BoundMethodHandle.Factory.generateConcreteBMHClassBytes(
                                  shortTypes, types, className));
     }
+
 }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Aug 25 22:35:56 2016 +0000
@@ -629,6 +629,28 @@
                 name = name + "_" + form.returnType().basicTypeChar();
                 return resolveFrom(name, invokerType, LambdaForm.Holder.class);
             }
+            case EXACT_INVOKER:             // fall-through
+            case EXACT_LINKER:              // fall-through
+            case GENERIC_INVOKER:           // fall-through
+            case GENERIC_LINKER:            return resolveFrom(name, invokerType.basicType(), Invokers.Holder.class);
+            case GET_OBJECT:                // fall-through
+            case GET_BOOLEAN:               // fall-through
+            case GET_BYTE:                  // fall-through
+            case GET_CHAR:                  // fall-through
+            case GET_SHORT:                 // fall-through
+            case GET_INT:                   // fall-through
+            case GET_LONG:                  // fall-through
+            case GET_FLOAT:                 // fall-through
+            case GET_DOUBLE:                // fall-through
+            case PUT_OBJECT:                // fall-through
+            case PUT_BOOLEAN:               // fall-through
+            case PUT_BYTE:                  // fall-through
+            case PUT_CHAR:                  // fall-through
+            case PUT_SHORT:                 // fall-through
+            case PUT_INT:                   // fall-through
+            case PUT_LONG:                  // fall-through
+            case PUT_FLOAT:                 // fall-through
+            case PUT_DOUBLE:                // fall-through
             case DIRECT_INVOKE_INTERFACE:   // fall-through
             case DIRECT_INVOKE_SPECIAL:     // fall-through
             case DIRECT_INVOKE_STATIC:      // fall-through
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Thu Aug 25 22:35:56 2016 +0000
@@ -36,6 +36,7 @@
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
 import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
 
 /**
  * Construction and caching of often-used invokers.
@@ -254,7 +255,7 @@
      * @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
      *                          0x02 whether it is for invokeExact or generic invoke
      */
-    private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
+    static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
         boolean isCached;
         if (!customized) {
             mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
@@ -263,12 +264,12 @@
             isCached = false;  // maybe cache if mtype == mtype.basicType()
         }
         boolean isLinker, isGeneric;
-        String debugName;
+        Kind kind;
         switch (which) {
-        case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; debugName = "invokeExact_MT"; break;
-        case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
-        case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
-        case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
+        case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; kind = EXACT_LINKER; break;
+        case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; kind = EXACT_INVOKER; break;
+        case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  kind = GENERIC_LINKER; break;
+        case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  kind = GENERIC_INVOKER; break;
         default: throw new InternalError();
         }
         LambdaForm lform;
@@ -323,7 +324,11 @@
             names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
         }
         names[LINKER_CALL] = new Name(outCallType, outArgs);
-        lform = new LambdaForm(debugName, INARG_LIMIT, names);
+        if (customized) {
+            lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names);
+        } else {
+            lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names, kind);
+        }
         if (isLinker)
             lform.compileToBytecode();  // JVM needs a real methodOop
         if (isCached)
@@ -614,4 +619,15 @@
             }
         }
     }
+
+    static {
+        // The Holder class will contain pre-generated Invokers 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 Invokers generated ahead of time */
+    final class Holder {}
 }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Aug 25 22:35:56 2016 +0000
@@ -275,12 +275,52 @@
         BOUND_REINVOKER("BMH.reinvoke"),
         REINVOKER("MH.reinvoke"),
         DELEGATE("MH.delegate"),
+        EXACT_LINKER("MH.invokeExact_MT"),
+        EXACT_INVOKER("MH.exactInvoker"),
+        GENERIC_LINKER("MH.invoke_MT"),
+        GENERIC_INVOKER("MH.invoker"),
         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");
+        DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"),
+        GET_OBJECT("getObject"),
+        PUT_OBJECT("putObject"),
+        GET_OBJECT_VOLATILE("getObjectVolatile"),
+        PUT_OBJECT_VOLATILE("putObjectVolatile"),
+        GET_INT("getInt"),
+        PUT_INT("putInt"),
+        GET_INT_VOLATILE("getIntVolatile"),
+        PUT_INT_VOLATILE("putIntVolatile"),
+        GET_BOOLEAN("getBoolean"),
+        PUT_BOOLEAN("putBoolean"),
+        GET_BOOLEAN_VOLATILE("getBooleanVolatile"),
+        PUT_BOOLEAN_VOLATILE("putBooleanVolatile"),
+        GET_BYTE("getByte"),
+        PUT_BYTE("putByte"),
+        GET_BYTE_VOLATILE("getByteVolatile"),
+        PUT_BYTE_VOLATILE("putByteVolatile"),
+        GET_CHAR("getChar"),
+        PUT_CHAR("putChar"),
+        GET_CHAR_VOLATILE("getCharVolatile"),
+        PUT_CHAR_VOLATILE("putCharVolatile"),
+        GET_SHORT("getShort"),
+        PUT_SHORT("putShort"),
+        GET_SHORT_VOLATILE("getShortVolatile"),
+        PUT_SHORT_VOLATILE("putShortVolatile"),
+        GET_LONG("getLong"),
+        PUT_LONG("putLong"),
+        GET_LONG_VOLATILE("getLongVolatile"),
+        PUT_LONG_VOLATILE("putLongVolatile"),
+        GET_FLOAT("getFloat"),
+        PUT_FLOAT("putFloat"),
+        GET_FLOAT_VOLATILE("getFloatVolatile"),
+        PUT_FLOAT_VOLATILE("putFloatVolatile"),
+        GET_DOUBLE("getDouble"),
+        PUT_DOUBLE("putDouble"),
+        GET_DOUBLE_VOLATILE("getDoubleVolatile"),
+        PUT_DOUBLE_VOLATILE("putDoubleVolatile");
 
         final String defaultLambdaName;
         final String methodName;
@@ -330,6 +370,10 @@
         this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
     }
     LambdaForm(String debugName,
+               int arity, Name[] names, Kind kind) {
+        this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, kind);
+    }
+    LambdaForm(String debugName,
                int arity, Name[] names, boolean forceInline) {
         this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
     }
@@ -817,54 +861,6 @@
         }
     }
 
-    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)) {
-            if (!m.isStatic() || !m.isPackage())  continue;
-            MethodType mt = m.getMethodType();
-            if (mt.parameterCount() > 0 &&
-                mt.parameterType(0) == MethodHandle.class &&
-                m.getName().startsWith("interpret_")) {
-                String sig = null;
-                assert((sig = basicTypeSignature(mt)) != null &&
-                        m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
-                LambdaForm form = new LambdaForm(mt);
-                form.vmentry = m;
-                form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
-            }
-        }
-    }
-
-    // Set this false to disable use of the interpret_L methods defined in this file.
-    private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
-
-    // The following are predefined exact invokers.  The system must build
-    // a separate invoker for each distinct signature.
-    static Object interpret_L(MethodHandle mh) throws Throwable {
-        Object[] av = {mh};
-        String sig = null;
-        assert(argumentTypesMatch(sig = "L_L", av));
-        Object res = mh.form.interpretWithArguments(av);
-        assert(returnTypesMatch(sig, av, res));
-        return res;
-    }
-    static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
-        Object[] av = {mh, x1};
-        String sig = null;
-        assert(argumentTypesMatch(sig = "LL_L", av));
-        Object res = mh.form.interpretWithArguments(av);
-        assert(returnTypesMatch(sig, av, res));
-        return res;
-    }
-    static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
-        Object[] av = {mh, x1, x2};
-        String sig = null;
-        assert(argumentTypesMatch(sig = "LLL_L", av));
-        Object res = mh.form.interpretWithArguments(av);
-        assert(returnTypesMatch(sig, av, res));
-        return res;
-    }
-
     // The next few routines are called only from assert expressions
     // They verify that the built-in invokers process the correct raw data types.
     private static boolean argumentTypesMatch(String sig, Object[] av) {
@@ -1151,113 +1147,6 @@
             return super.hashCode();
         }
 
-        // Put the predefined NamedFunction invokers into the table.
-        static void initializeInvokers() {
-            for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
-                if (!m.isStatic() || !m.isPackage())  continue;
-                MethodType type = m.getMethodType();
-                if (type.equals(INVOKER_METHOD_TYPE) &&
-                    m.getName().startsWith("invoke_")) {
-                    String sig = m.getName().substring("invoke_".length());
-                    int arity = LambdaForm.signatureArity(sig);
-                    MethodType srcType = MethodType.genericMethodType(arity);
-                    if (LambdaForm.signatureReturn(sig) == V_TYPE)
-                        srcType = srcType.changeReturnType(void.class);
-                    MethodTypeForm typeForm = srcType.form();
-                    typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m));
-                }
-            }
-        }
-
-        // The following are predefined NamedFunction invokers.  The system must build
-        // a separate invoker for each distinct signature.
-        /** void return type invokers. */
-        @Hidden
-        static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(0, void.class, mh, a));
-            mh.invokeBasic();
-            return null;
-        }
-        @Hidden
-        static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(1, void.class, mh, a));
-            mh.invokeBasic(a[0]);
-            return null;
-        }
-        @Hidden
-        static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(2, void.class, mh, a));
-            mh.invokeBasic(a[0], a[1]);
-            return null;
-        }
-        @Hidden
-        static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(3, void.class, mh, a));
-            mh.invokeBasic(a[0], a[1], a[2]);
-            return null;
-        }
-        @Hidden
-        static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(4, void.class, mh, a));
-            mh.invokeBasic(a[0], a[1], a[2], a[3]);
-            return null;
-        }
-        @Hidden
-        static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(5, void.class, mh, a));
-            mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
-            return null;
-        }
-        /** Object return type invokers. */
-        @Hidden
-        static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(0, mh, a));
-            return mh.invokeBasic();
-        }
-        @Hidden
-        static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(1, mh, a));
-            return mh.invokeBasic(a[0]);
-        }
-        @Hidden
-        static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(2, mh, a));
-            return mh.invokeBasic(a[0], a[1]);
-        }
-        @Hidden
-        static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(3, mh, a));
-            return mh.invokeBasic(a[0], a[1], a[2]);
-        }
-        @Hidden
-        static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(4, mh, a));
-            return mh.invokeBasic(a[0], a[1], a[2], a[3]);
-        }
-        @Hidden
-        static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
-            assert(arityCheck(5, mh, a));
-            return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
-        }
-        private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) {
-            return arityCheck(arity, Object.class, mh, a);
-        }
-        private static boolean arityCheck(int arity, Class<?> rtype, MethodHandle mh, Object[] a) {
-            assert(a.length == arity)
-                    : Arrays.asList(a.length, arity);
-            assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype))
-                    : Arrays.asList(mh, rtype, arity);
-            MemberName member = mh.internalMemberName();
-            if (isInvokeBasic(member)) {
-                assert(arity > 0);
-                assert(a[0] instanceof MethodHandle);
-                MethodHandle mh2 = (MethodHandle) a[0];
-                assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype))
-                        : Arrays.asList(member, mh2, rtype, arity);
-            }
-            return true;
-        }
-
         static final MethodType INVOKER_METHOD_TYPE =
             MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
 
@@ -1920,12 +1809,7 @@
             DEBUG_NAME_COUNTERS = null;
     }
 
-    // Put this last, so that previous static inits can run before.
     static {
-        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
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1745,6 +1745,13 @@
                 return GenerateJLIClassesHelper
                         .generateBasicFormsClassBytes(className);
             }
+
+            @Override
+            public byte[] generateInvokersHolderClassBytes(final String className,
+                    MethodType[] methodTypes) {
+                return GenerateJLIClassesHelper
+                        .generateInvokersHolderClassBytes(className, methodTypes);
+            }
         });
     }
 
--- a/jdk/src/java.base/share/classes/java/time/Duration.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java	Thu Aug 25 22:35:56 2016 +0000
@@ -150,10 +150,12 @@
     /**
      * The pattern for parsing.
      */
-    private static final Pattern PATTERN =
+    private static class Lazy {
+        static final Pattern PATTERN =
             Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
                     "(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
                     Pattern.CASE_INSENSITIVE);
+    }
 
     /**
      * The number of seconds in the duration.
@@ -387,7 +389,7 @@
      */
     public static Duration parse(CharSequence text) {
         Objects.requireNonNull(text, "text");
-        Matcher matcher = PATTERN.matcher(text);
+        Matcher matcher = Lazy.PATTERN.matcher(text);
         if (matcher.matches()) {
             // check for letter T but no time sections
             if (!charMatch(text, matcher.start(3), matcher.end(3), 'T')) {
--- a/jdk/src/java.base/share/classes/java/time/ZoneOffset.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/time/ZoneOffset.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -375,15 +375,15 @@
         } else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) {
             throw new DateTimeException("Zone offset minutes and seconds must have the same sign");
         }
-        if (Math.abs(minutes) > 59) {
-            throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " +
-                    Math.abs(minutes) + " is not in the range 0 to 59");
+        if (minutes < -59 || minutes > 59) {
+            throw new DateTimeException("Zone offset minutes not in valid range: value " +
+                    minutes + " is not in the range -59 to 59");
         }
-        if (Math.abs(seconds) > 59) {
-            throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " +
-                    Math.abs(seconds) + " is not in the range 0 to 59");
+        if (seconds < -59 || seconds > 59) {
+            throw new DateTimeException("Zone offset seconds not in valid range: value " +
+                    seconds + " is not in the range -59 to 59");
         }
-        if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) {
+        if (Math.abs(hours) == 18 && (minutes | seconds) != 0) {
             throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
         }
     }
@@ -411,7 +411,7 @@
      * @throws DateTimeException if the offset is not in the required range
      */
     public static ZoneOffset ofTotalSeconds(int totalSeconds) {
-        if (Math.abs(totalSeconds) > MAX_SECONDS) {
+        if (totalSeconds < -MAX_SECONDS || totalSeconds > MAX_SECONDS) {
             throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
         }
         if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
@@ -696,11 +696,12 @@
      * The comparison is "consistent with equals", as defined by {@link Comparable}.
      *
      * @param other  the other date to compare to, not null
-     * @return the comparator value, negative if less, postive if greater
+     * @return the comparator value, negative if less, positive if greater
      * @throws NullPointerException if {@code other} is null
      */
     @Override
     public int compareTo(ZoneOffset other) {
+        // abs(totalSeconds) <= MAX_SECONDS, so no overflow can happen here
         return other.totalSeconds - totalSeconds;
     }
 
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Aug 25 22:35:56 2016 +0000
@@ -4566,7 +4566,10 @@
             boolean modified = false;
             // Use (c instanceof Set) as a hint that lookup in c is as
             // efficient as this view
-            if (c instanceof Set<?> && c.size() > map.table.length) {
+            Node<K,V>[] t;
+            if ((t = map.table) == null) {
+                return false;
+            } else if (c instanceof Set<?> && c.size() > t.length) {
                 for (Iterator<?> it = iterator(); it.hasNext(); ) {
                     if (c.contains(it.next())) {
                         it.remove();
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java	Thu Aug 25 22:35:56 2016 +0000
@@ -353,7 +353,7 @@
         if (isMultiRelease) {
             return true;
         }
-        if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) {
+        if (MULTI_RELEASE_ENABLED) {
             try {
                 checkForSpecialAttributes();
             } catch (IOException io) {
@@ -644,7 +644,7 @@
             return signers == null ? null : signers.clone();
         }
         JarFileEntry realEntry() {
-            if (isMultiRelease()) {
+            if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) {
                 String entryName = super.getName();
                 return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
             }
@@ -960,7 +960,7 @@
                 hasClassPathAttribute = match(CLASSPATH_CHARS, b,
                         CLASSPATH_LASTOCC) != -1;
                 // is this a multi-release jar file
-                if (MULTI_RELEASE_ENABLED && versionMajor != BASE_VERSION_MAJOR) {
+                if (MULTI_RELEASE_ENABLED) {
                     int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC);
                     if (i != -1) {
                         i += MULTIRELEASE_CHARS.length;
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Thu Aug 25 22:35:56 2016 +0000
@@ -46,7 +46,7 @@
     boolean isNative(Object mname);
 
     /**
-     * Returns a {@code byte[]} containing the bytecode for a class implementing
+     * Returns a {@code byte[]} representation of a class implementing
      * DirectMethodHandle of each pairwise combination of {@code MethodType} and
      * an {@code int} representing method type.  Used by
      * GenerateJLIClassesPlugin to generate such a class during the jlink phase.
@@ -55,7 +55,7 @@
             MethodType[] methodTypes, int[] types);
 
     /**
-     * Returns a {@code byte[]} containing the bytecode for a class implementing
+     * Returns a {@code byte[]} representation of 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.
@@ -64,7 +64,7 @@
             MethodType[] methodTypes);
 
     /**
-     * Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle
+     * Returns a {@code byte[]} representation of {@code BoundMethodHandle}
      * species class implementing the signature defined by {@code types}. Used
      * by GenerateBMHClassesPlugin to enable generation of such classes during
      * the jlink phase. Should do some added validation since this string may be
@@ -74,8 +74,15 @@
             final String types);
 
     /**
-     * Returns a {@code byte[]} containing the bytecode for a class implementing
+     * Returns a {@code byte[]} representation of a class implementing
      * the zero and identity forms of all {@code LambdaForm.BasicType}s.
      */
     byte[] generateBasicFormsClassBytes(final String className);
+
+    /**
+     * Returns a {@code byte[]} representation of a class implementing
+     * the invoker forms for the set of supplied {@code methodTypes}.
+     */
+    byte[] generateInvokersHolderClassBytes(String className,
+            MethodType[] methodTypes);
 }
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java	Thu Aug 25 22:35:56 2016 +0000
@@ -253,7 +253,8 @@
     public byte[] pad(byte[] data) throws BadPaddingException {
         if (data.length > maxDataSize) {
             throw new BadPaddingException("Data must be shorter than "
-                + (maxDataSize + 1) + " bytes");
+                + (maxDataSize + 1) + " bytes but received "
+                + data.length + " bytes.");
         }
         switch (type) {
         case PAD_NONE:
@@ -281,7 +282,9 @@
      */
     public byte[] unpad(byte[] padded) throws BadPaddingException {
         if (padded.length != paddedSize) {
-            throw new BadPaddingException("Decryption error");
+            throw new BadPaddingException("Decryption error." +
+                "The padded array length (" + padded.length +
+                ") is not the specified padded size (" + paddedSize + ")");
         }
         switch (type) {
         case PAD_NONE:
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java	Thu Aug 25 22:35:56 2016 +0000
@@ -493,7 +493,9 @@
 
                 if (protocolVersion.useTLS11PlusSpec()) {
                     if (newLen < blockSize) {
-                        throw new BadPaddingException("invalid explicit IV");
+                        throw new BadPaddingException("The length after " +
+                        "padding removal (" + newLen + ") should be larger " +
+                        "than <" + blockSize + "> since explicit IV used");
                     }
                 }
             }
@@ -504,7 +506,6 @@
         }
     }
 
-
     /*
      * Decrypts a block of data, returning the size of the
      * resulting block if padding was required.  position and limit
@@ -575,7 +576,9 @@
                 // check the explicit IV of TLS v1.1 or later
                 if (protocolVersion.useTLS11PlusSpec()) {
                     if (newLen < blockSize) {
-                        throw new BadPaddingException("invalid explicit IV");
+                        throw new BadPaddingException("The length after " +
+                        "padding removal (" + newLen + ") should be larger " +
+                        "than <" + blockSize + "> since explicit IV used");
                     }
 
                     // reset the position to the end of the decrypted data
@@ -756,7 +759,9 @@
             // so accept that as well
             // v3 does not require any particular value for the other bytes
             if (padLen > blockSize) {
-                throw new BadPaddingException("Invalid SSLv3 padding");
+                throw new BadPaddingException("Padding length (" +
+                padLen + ") of SSLv3 message should not be bigger " +
+                "than the block size (" + blockSize + ")");
             }
         }
         return newLen;
@@ -802,7 +807,9 @@
             // so accept that as well
             // v3 does not require any particular value for the other bytes
             if (padLen > blockSize) {
-                throw new BadPaddingException("Invalid SSLv3 padding");
+                throw new BadPaddingException("Padding length (" +
+                padLen + ") of SSLv3 message should not be bigger " +
+                "than the block size (" + blockSize + ")");
             }
         }
 
@@ -925,7 +932,10 @@
             case AEAD_CIPHER:
                 if (bb.remaining() < (recordIvSize + tagSize)) {
                     throw new BadPaddingException(
-                                        "invalid AEAD cipher fragment");
+                        "Insufficient buffer remaining for AEAD cipher " +
+                        "fragment (" + bb.remaining() + "). Needs to be " +
+                        "more than or equal to IV size (" + recordIvSize +
+                         ") + tag size (" + tagSize + ")");
                 }
 
                 // initialize the AEAD cipher for the unique IV
--- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java	Thu Aug 25 22:35:56 2016 +0000
@@ -27,15 +27,8 @@
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.lang.ref.SoftReference;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
-import java.util.List;
-import java.util.Locale;
 import java.util.Map;
-import java.util.Set;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
 
@@ -80,8 +73,6 @@
     private static final long ABBR_MASK = 0xf00L;
     private static final int TRANSITION_NSHIFT = 12;
 
-    private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
-
     /**
      * The raw GMT offset in milliseconds between this zone and GMT.
      * Negative offsets are to the west of Greenwich.  To obtain local
@@ -379,6 +370,7 @@
             throw new IllegalArgumentException();
         }
 
+        Gregorian gcal = CalendarSystem.getGregorianCalendar();
         CalendarDate date = gcal.newCalendarDate(null);
         date.setDate(year, month + 1, day);
         if (gcal.validate(date) == false) {
--- a/jdk/src/java.base/share/conf/security/java.security	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/conf/security/java.security	Thu Aug 25 22:35:56 2016 +0000
@@ -803,3 +803,44 @@
 #       E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
+
+#
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
+#
+#   Policy:
+#       Constraint {"," Constraint }
+#   Constraint:
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
+#
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
--- a/jdk/src/java.base/share/lib/security/default.policy	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/share/lib/security/default.policy	Thu Aug 25 22:35:56 2016 +0000
@@ -72,6 +72,8 @@
                    "removeProviderProperty.XMLDSig";
     permission java.security.SecurityPermission
                    "com.sun.org.apache.xml.internal.security.register";
+    permission java.security.SecurityPermission
+                   "getProperty.jdk.xml.dsig.secureValidationPolicy";
 };
 
 grant codeBase "jrt:/java.xml.ws" {
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java	Thu Aug 25 22:35:56 2016 +0000
@@ -252,6 +252,21 @@
         return new UnixPath(getFileSystem(), new byte[0]);
     }
 
+
+    // return true if this path has "." or ".."
+    private boolean hasDotOrDotDot() {
+        int n = getNameCount();
+        for (int i=0; i<n; i++) {
+            byte[] bytes = getName(i).path;
+            if ((bytes.length == 1 && bytes[0] == '.'))
+                return true;
+            if ((bytes.length == 2 && bytes[0] == '.') && bytes[1] == '.') {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public UnixFileSystem getFileSystem() {
         return fs;
@@ -405,80 +420,94 @@
 
     @Override
     public UnixPath relativize(Path obj) {
-        UnixPath other = toUnixPath(obj);
-        if (other.equals(this))
+        UnixPath child = toUnixPath(obj);
+        if (child.equals(this))
             return emptyPath();
 
         // can only relativize paths of the same type
-        if (this.isAbsolute() != other.isAbsolute())
+        if (this.isAbsolute() != child.isAbsolute())
             throw new IllegalArgumentException("'other' is different type of Path");
 
         // this path is the empty path
         if (this.isEmpty())
-            return other;
+            return child;
 
-        int bn = this.getNameCount();
-        int cn = other.getNameCount();
+        UnixPath base = this;
+        if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
+            base = base.normalize();
+            child = child.normalize();
+        }
+
+        int baseCount = base.getNameCount();
+        int childCount = child.getNameCount();
 
         // skip matching names
-        int n = (bn > cn) ? cn : bn;
+        int n = Math.min(baseCount, childCount);
         int i = 0;
         while (i < n) {
-            if (!this.getName(i).equals(other.getName(i)))
+            if (!base.getName(i).equals(child.getName(i)))
                 break;
             i++;
         }
 
-        int dotdots = bn - i;
-        if (i < cn) {
-            // remaining name components in other
-            UnixPath remainder = other.subpath(i, cn);
-            if (dotdots == 0)
-                return remainder;
+        // remaining elements in child
+        UnixPath childRemaining;
+        boolean isChildEmpty;
+        if (i == childCount) {
+            childRemaining = emptyPath();
+            isChildEmpty = true;
+        } else {
+            childRemaining = child.subpath(i, childCount);
+            isChildEmpty = childRemaining.isEmpty();
+        }
+
+        // matched all of base
+        if (i == baseCount) {
+            return childRemaining;
+        }
 
-            // other is the empty path
-            boolean isOtherEmpty = other.isEmpty();
+        // the remainder of base cannot contain ".."
+        UnixPath baseRemaining = base.subpath(i, baseCount);
+        if (baseRemaining.hasDotOrDotDot()) {
+            throw new IllegalArgumentException("Unable to compute relative "
+                    + " path from " + this + " to " + obj);
+        }
+        if (baseRemaining.isEmpty())
+            return childRemaining;
+
+        // number of ".." needed
+        int dotdots = baseRemaining.getNameCount();
+        if (dotdots == 0) {
+            return childRemaining;
+        }
 
-            // result is a  "../" for each remaining name in base
-            // followed by the remaining names in other. If the remainder is
-            // the empty path then we don't add the final trailing slash.
-            int len = dotdots*3 + remainder.path.length;
-            if (isOtherEmpty) {
-                assert remainder.isEmpty();
-                len--;
+        // result is a  "../" for each remaining name in base followed by the
+        // remaining names in child. If the remainder is the empty path
+        // then we don't add the final trailing slash.
+        int len = dotdots*3 + childRemaining.path.length;
+        if (isChildEmpty) {
+            assert childRemaining.isEmpty();
+            len--;
+        }
+        byte[] result = new byte[len];
+        int pos = 0;
+        while (dotdots > 0) {
+            result[pos++] = (byte)'.';
+            result[pos++] = (byte)'.';
+            if (isChildEmpty) {
+                if (dotdots > 1) result[pos++] = (byte)'/';
+            } else {
+                result[pos++] = (byte)'/';
             }
-            byte[] result = new byte[len];
-            int pos = 0;
-            while (dotdots > 0) {
-                result[pos++] = (byte)'.';
-                result[pos++] = (byte)'.';
-                if (isOtherEmpty) {
-                    if (dotdots > 1) result[pos++] = (byte)'/';
-                } else {
-                    result[pos++] = (byte)'/';
-                }
-                dotdots--;
-            }
-            System.arraycopy(remainder.path, 0, result, pos, remainder.path.length);
-            return new UnixPath(getFileSystem(), result);
-        } else {
-            // no remaining names in other so result is simply a sequence of ".."
-            byte[] result = new byte[dotdots*3 - 1];
-            int pos = 0;
-            while (dotdots > 0) {
-                result[pos++] = (byte)'.';
-                result[pos++] = (byte)'.';
-                // no tailing slash at the end
-                if (dotdots > 1)
-                    result[pos++] = (byte)'/';
-                dotdots--;
-            }
-            return new UnixPath(getFileSystem(), result);
+            dotdots--;
         }
+        System.arraycopy(childRemaining.path,0, result, pos,
+                             childRemaining.path.length);
+        return new UnixPath(getFileSystem(), result);
     }
 
     @Override
-    public Path normalize() {
+    public UnixPath normalize() {
         final int count = getNameCount();
         if (count == 0 || isEmpty())
             return this;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java	Thu Aug 25 22:35:56 2016 +0000
@@ -375,57 +375,108 @@
         return (WindowsPath)path;
     }
 
+    // return true if this path has "." or ".."
+    private boolean hasDotOrDotDot() {
+        int n = getNameCount();
+        for (int i=0; i<n; i++) {
+            String name = elementAsString(i);
+            if (name.length() == 1 && name.charAt(0) == '.')
+                return true;
+            if (name.length() == 2
+                    && name.charAt(0) == '.' && name.charAt(1) == '.')
+                return true;
+        }
+        return false;
+    }
+
     @Override
     public WindowsPath relativize(Path obj) {
-        WindowsPath other = toWindowsPath(obj);
-        if (this.equals(other))
+        WindowsPath child = toWindowsPath(obj);
+        if (this.equals(child))
             return emptyPath();
 
         // can only relativize paths of the same type
-        if (this.type != other.type)
+        if (this.type != child.type)
             throw new IllegalArgumentException("'other' is different type of Path");
 
         // can only relativize paths if root component matches
-        if (!this.root.equalsIgnoreCase(other.root))
+        if (!this.root.equalsIgnoreCase(child.root))
             throw new IllegalArgumentException("'other' has different root");
 
         // this path is the empty path
         if (this.isEmpty())
-            return other;
+            return child;
+
 
-        int bn = this.getNameCount();
-        int cn = other.getNameCount();
+        WindowsPath base = this;
+        if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
+            base = base.normalize();
+            child = child.normalize();
+        }
+
+        int baseCount = base.getNameCount();
+        int childCount = child.getNameCount();
 
         // skip matching names
-        int n = (bn > cn) ? cn : bn;
+        int n = Math.min(baseCount, childCount);
         int i = 0;
         while (i < n) {
-            if (!this.getName(i).equals(other.getName(i)))
+            if (!base.getName(i).equals(child.getName(i)))
                 break;
             i++;
         }
 
-        // append ..\ for remaining names in the base
+        // remaining elements in child
+        WindowsPath childRemaining;
+        boolean isChildEmpty;
+        if (i == childCount) {
+            childRemaining = emptyPath();
+            isChildEmpty = true;
+        } else {
+            childRemaining = child.subpath(i, childCount);
+            isChildEmpty = childRemaining.isEmpty();
+        }
+
+        // matched all of base
+        if (i == baseCount) {
+            return childRemaining;
+        }
+
+        // the remainder of base cannot contain ".."
+        WindowsPath baseRemaining = base.subpath(i, baseCount);
+        if (baseRemaining.hasDotOrDotDot()) {
+            throw new IllegalArgumentException("Unable to compute relative "
+                    + " path from " + this + " to " + obj);
+        }
+        if (baseRemaining.isEmpty())
+            return childRemaining;
+
+        // number of ".." needed
+        int dotdots = baseRemaining.getNameCount();
+        if (dotdots == 0) {
+            return childRemaining;
+        }
+
         StringBuilder result = new StringBuilder();
-        for (int j=i; j<bn; j++) {
+        for (int j=0; j<dotdots; j++) {
             result.append("..\\");
         }
 
         // append remaining names in child
-        if (!other.isEmpty()) {
-            for (int j=i; j<cn; j++) {
-                result.append(other.getName(j).toString());
+        if (!isChildEmpty) {
+            for (int j=0; j<childRemaining.getNameCount(); j++) {
+                result.append(childRemaining.getName(j).toString());
                 result.append("\\");
             }
         }
 
-        // drop trailing slash in result
+        // drop trailing slash
         result.setLength(result.length()-1);
         return createFromNormalizedPath(getFileSystem(), result.toString());
     }
 
     @Override
-    public Path normalize() {
+    public WindowsPath normalize() {
         final int count = getNameCount();
         if (count == 0 || isEmpty())
             return this;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java	Thu Aug 25 22:35:56 2016 +0000
@@ -390,35 +390,27 @@
 
             for (int i=1; i <= retries; i++) {
                 String proto = useTCP?"TCP":"UDP";
-                try (NetClient kdcClient = NetClient.getInstance(
-                        proto, kdc, port, timeout)) {
-                    if (DEBUG) {
-                        System.out.println(">>> KDCCommunication: kdc=" + kdc
+                if (DEBUG) {
+                    System.out.println(">>> KDCCommunication: kdc=" + kdc
                             + " " + proto + ":"
                             +  port +  ", timeout="
                             + timeout
                             + ",Attempt =" + i
                             + ", #bytes=" + obuf.length);
+                }
+                try (NetClient kdcClient = NetClient.getInstance(
+                        proto, kdc, port, timeout)) {
+                    kdcClient.send(obuf);
+                    ibuf = kdcClient.receive();
+                    break;
+                } catch (SocketTimeoutException se) {
+                    if (DEBUG) {
+                        System.out.println ("SocketTimeOutException with " +
+                                "attempt: " + i);
                     }
-                    try {
-                        /*
-                        * Send the data to the kdc.
-                        */
-                        kdcClient.send(obuf);
-                        /*
-                        * And get a response.
-                        */
-                        ibuf = kdcClient.receive();
-                        break;
-                    } catch (SocketTimeoutException se) {
-                        if (DEBUG) {
-                            System.out.println ("SocketTimeOutException with " +
-                                                "attempt: " + i);
-                        }
-                        if (i == retries) {
-                            ibuf = null;
-                            throw se;
-                        }
+                    if (i == retries) {
+                        ibuf = null;
+                        throw se;
                     }
                 }
             }
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -3204,7 +3204,6 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @since 1.4
     */
    public void setNull(String parameterName, int sqlType) throws SQLException {
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3240,7 +3239,6 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @since 1.4
     */
    public void setNull (String parameterName, int sqlType, String typeName)
        throws SQLException{
@@ -3259,7 +3257,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setBoolean(String parameterName, boolean x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3277,7 +3274,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setByte(String parameterName, byte x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3295,7 +3291,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setShort(String parameterName, short x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3313,7 +3308,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setInt(String parameterName, int x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3332,7 +3326,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setLong(String parameterName, long x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3350,7 +3343,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setFloat(String parameterName, float x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3368,7 +3360,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setDouble(String parameterName, double x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3387,7 +3378,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3408,7 +3398,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setString(String parameterName, String x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3428,7 +3417,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setBytes(String parameterName, byte x[]) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -3447,7 +3435,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x)
        throws SQLException{
@@ -3474,7 +3461,6 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @since 1.4
     */
    public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
        throws SQLException{
@@ -3500,7 +3486,6 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @since 1.4
     */
    public void setBinaryStream(String parameterName, java.io.InputStream x,
                         int length) throws SQLException{
@@ -3528,7 +3513,6 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @since 1.4
     */
    public void setCharacterStream(String parameterName,
                            java.io.Reader reader,
@@ -3684,7 +3668,6 @@
     * this data type
     * @see Types
     * @see #getParams
-    * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType, int scale)
        throws SQLException{
@@ -3710,7 +3693,6 @@
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
     * @see #getParams
-    * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType)
        throws SQLException{
@@ -3751,7 +3733,6 @@
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
    * @see #getParams
-   * @since 1.4
    */
   public void setObject(String parameterName, Object x) throws SQLException{
         throw new SQLFeatureNotSupportedException("Feature not supported");
@@ -4024,7 +4005,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x)
            throws SQLException {
@@ -4050,7 +4030,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
            throws SQLException {
@@ -4069,7 +4048,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x)
            throws SQLException {
@@ -4095,7 +4073,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
            throws SQLException {
@@ -4121,7 +4098,6 @@
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @see #getParams
-    * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
            throws SQLException {
@@ -4459,7 +4435,6 @@
     * @exception SQLException if a database access error occurs or
     * this method is called on a closed <code>PreparedStatement</code>
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
-    * @since 1.4
     */
    public void setURL(int parameterIndex, java.net.URL x) throws SQLException {
        throw new SQLFeatureNotSupportedException("Feature not supported");
--- a/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/CommonDataSource.java	Thu Aug 25 22:35:56 2016 +0000
@@ -57,7 +57,6 @@
      *        logging is disabled
      * @exception java.sql.SQLException if a database access error occurs
      * @see #setLogWriter
-     * @since 1.4
      */
     java.io.PrintWriter getLogWriter() throws SQLException;
 
@@ -79,7 +78,6 @@
      * @param out the new log writer; to disable logging, set to null
      * @exception SQLException if a database access error occurs
      * @see #getLogWriter
-     * @since 1.4
      */
     void setLogWriter(java.io.PrintWriter out) throws SQLException;
 
@@ -94,7 +92,6 @@
      * @param seconds the data source login time limit
      * @exception SQLException if a database access error occurs.
      * @see #getLoginTimeout
-     * @since 1.4
      */
     void setLoginTimeout(int seconds) throws SQLException;
 
@@ -109,7 +106,6 @@
      * @return the data source login time limit
      * @exception SQLException if a database access error occurs.
      * @see #setLoginTimeout
-     * @since 1.4
      */
     int getLoginTimeout() throws SQLException;
 
--- a/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/ConnectionPoolDataSource.java	Thu Aug 25 22:35:56 2016 +0000
@@ -72,6 +72,34 @@
   PooledConnection getPooledConnection(String user, String password)
     throws SQLException;
 
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  java.io.PrintWriter getLogWriter() throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLoginTimeout(int seconds) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  int getLoginTimeout() throws SQLException;
+
   //------------------------- JDBC 4.3 -----------------------------------
 
   /**
--- a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java	Thu Aug 25 22:35:56 2016 +0000
@@ -109,6 +109,34 @@
   Connection getConnection(String username, String password)
     throws SQLException;
 
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  java.io.PrintWriter getLogWriter() throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLoginTimeout(int seconds) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  int getLoginTimeout() throws SQLException;
+
   // JDBC 4.3
 
   /**
--- a/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.sql/share/classes/javax/sql/XADataSource.java	Thu Aug 25 22:35:56 2016 +0000
@@ -81,7 +81,35 @@
   XAConnection getXAConnection(String user, String password)
     throws SQLException;
 
-  // JDBC 4.3
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  java.io.PrintWriter getLogWriter() throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLogWriter(java.io.PrintWriter out) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  void setLoginTimeout(int seconds) throws SQLException;
+
+  /**
+   * {@inheritDoc}
+   * @since 1.4
+   */
+  @Override
+  int getLoginTimeout() throws SQLException;
+
+   // JDBC 4.3
 
   /**
    * Creates a new {@code XAConnectionBuilder} instance
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Thu Aug 25 22:35:56 2016 +0000
@@ -150,7 +150,7 @@
             this.macAlgorithm.init(secretKey);
         } catch (InvalidKeyException ex) {
             // reinstantiate Mac object to work around bug in JDK
-            // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+            // see: http://bugs.java.com/view_bug.do?bug_id=4953555
             Mac mac = this.macAlgorithm;
             try {
                 this.macAlgorithm = Mac.getInstance(macAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java	Thu Aug 25 22:35:56 2016 +0000
@@ -112,7 +112,7 @@
             this.signatureAlgorithm.initVerify((PublicKey) publicKey);
         } catch (InvalidKeyException ex) {
             // reinstantiate Signature object to work around bug in JDK
-            // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+            // see: http://bugs.java.com/view_bug.do?bug_id=4953555
             Signature sig = this.signatureAlgorithm;
             try {
                 this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java	Thu Aug 25 22:35:56 2016 +0000
@@ -139,7 +139,7 @@
             this.signatureAlgorithm.initVerify((PublicKey) publicKey);
         } catch (InvalidKeyException ex) {
             // reinstantiate Signature object to work around bug in JDK
-            // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+            // see: http://bugs.java.com/view_bug.do?bug_id=4953555
             Signature sig = this.signatureAlgorithm;
             try {
                 this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java	Thu Aug 25 22:35:56 2016 +0000
@@ -252,7 +252,7 @@
             this.signatureAlgorithm.initVerify((PublicKey) publicKey);
         } catch (InvalidKeyException ex) {
             // reinstantiate Signature object to work around bug in JDK
-            // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+            // see: http://bugs.java.com/view_bug.do?bug_id=4953555
             Signature sig = this.signatureAlgorithm;
             try {
                 this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $
@@ -38,7 +38,6 @@
 
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
 import com.sun.org.apache.xml.internal.security.transforms.Transform;
-import com.sun.org.apache.xml.internal.security.transforms.Transforms;
 
 import javax.xml.crypto.*;
 import javax.xml.crypto.dom.DOMCryptoContext;
@@ -150,7 +149,7 @@
 
         if (Utils.secureValidation(xc)) {
             String algorithm = getAlgorithm();
-            if (Transforms.TRANSFORM_XSLT.equals(algorithm)) {
+            if (Policy.restrictAlg(algorithm)) {
                 throw new TransformException(
                     "Transform " + algorithm + " is forbidden when secure validation is enabled"
                 );
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -110,9 +110,10 @@
                                            localName + ", expected Reference");
             }
             refs.add(new DOMReference(refElem, context, provider));
-            if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) {
-                String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " "
-                    + "references per Manifest are allowed with secure validation";
+            if (secVal && Policy.restrictNumReferences(refs.size())) {
+                String error = "A maximum of " + Policy.maxReferences()
+                    + " references per Manifest are allowed when"
+                    + " secure validation is enabled";
                 throw new MarshalException(error);
             }
             refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -51,7 +51,6 @@
 import org.w3c.dom.Node;
 
 import org.jcp.xml.dsig.internal.DigesterOutputStream;
-import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
 import com.sun.org.apache.xml.internal.security.utils.Base64;
@@ -67,11 +66,6 @@
     implements Reference, DOMURIReference {
 
    /**
-    * The maximum number of transforms per reference, if secure validation is enabled.
-    */
-   public static final int MAXIMUM_TRANSFORM_COUNT = 5;
-
-   /**
     * Look up useC14N11 system property. If true, an explicit C14N11 transform
     * will be added if necessary when generating the signature. See section
     * 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info.
@@ -208,9 +202,10 @@
                 }
                 transforms.add
                     (new DOMTransform(transformElem, context, provider));
-                if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) {
-                    String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " "
-                        + "transforms per Reference are allowed with secure validation";
+                if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+                    String error = "A maximum of " + Policy.maxTransforms()
+                        + " transforms per Reference are allowed when"
+                        + " secure validation is enabled";
                     throw new MarshalException(error);
                 }
                 transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -227,10 +222,10 @@
         Element dmElem = nextSibling;
         this.digestMethod = DOMDigestMethod.unmarshal(dmElem);
         String digestMethodAlgorithm = this.digestMethod.getAlgorithm();
-        if (secVal
-            && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) {
+        if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) {
             throw new MarshalException(
-                "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled"
+                "It is forbidden to use algorithm " + digestMethodAlgorithm +
+                " when secure validation is enabled"
             );
         }
 
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -149,9 +149,10 @@
                 }
                 transforms.add
                     (new DOMTransform(transformElem, context, provider));
-                if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) {
-                    String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " "
-                        + "transforms per Reference are allowed with secure validation";
+                if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+                    String error = "A maximum of " + Policy.maxTransforms()
+                        + " transforms per Reference are allowed when"
+                        + " secure validation is enabled";
                     throw new MarshalException(error);
                 }
                 transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -238,7 +239,8 @@
         }
 
         // guard against RetrievalMethod loops
-        if ((data instanceof NodeSetData) && Utils.secureValidation(context)) {
+        if ((data instanceof NodeSetData) && Utils.secureValidation(context)
+            && Policy.restrictRetrievalMethodLoops()) {
             NodeSetData<?> nsd = (NodeSetData<?>)data;
             Iterator<?> i = nsd.iterator();
             if (i.hasNext()) {
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -45,7 +45,6 @@
 import org.w3c.dom.Node;
 
 import com.sun.org.apache.xml.internal.security.utils.Base64;
-import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
 
 /**
@@ -55,22 +54,9 @@
  */
 public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
 
-    /**
-     * The maximum number of references per Manifest, if secure validation is enabled.
-     */
-    public static final int MAXIMUM_REFERENCE_COUNT = 30;
-
     private static java.util.logging.Logger log =
         java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
 
-    /** Signature - NOT Recommended RSAwithMD5 */
-    private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
-        Constants.MoreAlgorithmsSpecNS + "rsa-md5";
-
-    /** HMAC - NOT Recommended HMAC-MD5 */
-    private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
-        Constants.MoreAlgorithmsSpecNS + "hmac-md5";
-
     private List<Reference> references;
     private CanonicalizationMethod canonicalizationMethod;
     private SignatureMethod signatureMethod;
@@ -158,10 +144,10 @@
         boolean secVal = Utils.secureValidation(context);
 
         String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
-        if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
-                || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
+        if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) {
             throw new MarshalException(
-                "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
+                "It is forbidden to use algorithm " + signatureMethodAlgorithm +
+                " when secure validation is enabled"
             );
         }
 
@@ -179,9 +165,10 @@
             }
             refList.add(new DOMReference(refElem, context, provider));
 
-            if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) {
-                String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " "
-                    + "references per Manifest are allowed with secure validation";
+            if (secVal && Policy.restrictNumReferences(refList.size())) {
+                String error = "A maximum of " + Policy.maxReferences()
+                    + " references per Manifest are allowed when"
+                    + " secure validation is enabled";
                 throw new MarshalException(error);
             }
             refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java	Thu Aug 25 22:35:56 2016 +0000
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMURIDereferencer.java 1231033 2012-01-13 12:12:12Z coheigea $
@@ -73,6 +73,11 @@
 
         boolean secVal = Utils.secureValidation(context);
 
+        if (secVal && Policy.restrictReferenceUriScheme(uri)) {
+            throw new URIReferenceException(
+                "Uri " + uri + " is forbidden when secure validation is enabled");
+        }
+
         // Check if same-document URI and already registered on the context
         if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') {
             String id = uri.substring(1);
@@ -83,12 +88,19 @@
                 id = id.substring(i1+1, i2);
             }
 
-            Node referencedElem = dcc.getElementById(id);
+            // check if element is registered by Id
+            Node referencedElem = uriAttr.getOwnerDocument().getElementById(id);
+            if (referencedElem == null) {
+               // see if element is registered in DOMCryptoContext
+               referencedElem = dcc.getElementById(id);
+            }
             if (referencedElem != null) {
-                if (secVal) {
+                if (secVal && Policy.restrictDuplicateIds()) {
                     Element start = referencedElem.getOwnerDocument().getDocumentElement();
                     if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) {
-                        String error = "Multiple Elements with the same ID " + id + " were detected";
+                        String error = "Multiple Elements with the same ID "
+                            + id + " detected when secure validation"
+                            + " is enabled";
                         throw new URIReferenceException(error);
                     }
                 }
@@ -110,9 +122,9 @@
 
         try {
             ResourceResolver apacheResolver =
-                ResourceResolver.getInstance(uriAttr, baseURI, secVal);
+                ResourceResolver.getInstance(uriAttr, baseURI, false);
             XMLSignatureInput in = apacheResolver.resolve(uriAttr,
-                                                          baseURI, secVal);
+                                                          baseURI, false);
             if (in.isOctetStream()) {
                 return new ApacheOctetStreamData(in);
             } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+package org.jcp.xml.dsig.internal.dom;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * The secure validation policy as specified by the
+ * jdk.xml.dsig.secureValidationPolicy security property.
+ */
+public final class Policy {
+
+    // all restrictions are initialized to be unconstrained
+    private static Set<URI> disallowedAlgs = new HashSet<>();
+    private static int maxTrans = Integer.MAX_VALUE;
+    private static int maxRefs = Integer.MAX_VALUE;
+    private static Set<String> disallowedRefUriSchemes = new HashSet<>();
+    private static boolean noDuplicateIds = false;
+    private static boolean noRMLoops = false;
+
+    static {
+        try {
+            initialize();
+        } catch (Exception e) {
+            throw new SecurityException(
+                "Cannot initialize the secure validation policy", e);
+        }
+    }
+
+    private Policy() {}
+
+    private static void initialize() {
+        String prop =
+            AccessController.doPrivileged((PrivilegedAction<String>) () ->
+                Security.getProperty("jdk.xml.dsig.secureValidationPolicy"));
+        if (prop == null || prop.isEmpty()) {
+            // no policy specified, so don't enforce any restrictions
+            return;
+        }
+        String[] entries = prop.split(",");
+        for (String entry : entries) {
+            String[] tokens = entry.split("\\s");
+            String type = tokens[0];
+            switch(type) {
+                case "disallowAlg":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    disallowedAlgs.add(URI.create(tokens[1]));
+                    break;
+                case "maxTransforms":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    maxTrans = Integer.parseUnsignedInt(tokens[1]);
+                    break;
+                case "maxReferences":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    maxRefs = Integer.parseUnsignedInt(tokens[1]);
+                    break;
+                case "disallowReferenceUriSchemes":
+                    if (tokens.length == 1) {
+                        error(entry);
+                    }
+                    for (int i = 1; i < tokens.length; i++) {
+                        String scheme = tokens[i];
+                        disallowedRefUriSchemes.add(
+                            scheme.toLowerCase(Locale.ROOT));
+                    }
+                    break;
+                case "noDuplicateIds":
+                    if (tokens.length != 1) {
+                        error(entry);
+                    }
+                    noDuplicateIds = true;
+                    break;
+                case "noRetrievalMethodLoops":
+                    if (tokens.length != 1) {
+                        error(entry);
+                    }
+                    noRMLoops = true;
+                    break;
+                default:
+                    error(entry);
+            }
+        }
+    }
+
+    public static boolean restrictAlg(String alg) {
+        try {
+            URI uri = new URI(alg);
+            return disallowedAlgs.contains(uri);
+        } catch (URISyntaxException use) {
+            return false;
+        }
+    }
+
+    public static boolean restrictNumTransforms(int numTrans) {
+        return (numTrans > maxTrans);
+    }
+
+    public static boolean restrictNumReferences(int numRefs) {
+        return (numRefs > maxRefs);
+    }
+
+    public static boolean restrictReferenceUriScheme(String uri) {
+        if (uri != null) {
+            String scheme = java.net.URI.create(uri).getScheme();
+            if (scheme != null) {
+                return disallowedRefUriSchemes.contains(
+                    scheme.toLowerCase(Locale.ROOT));
+            }
+        }
+        return false;
+    }
+
+    public static boolean restrictDuplicateIds() {
+        return noDuplicateIds;
+    }
+
+    public static boolean restrictRetrievalMethodLoops() {
+        return noRMLoops;
+    }
+
+    public static Set<URI> disabledAlgs() {
+        return Collections.<URI>unmodifiableSet(disallowedAlgs);
+    }
+
+    public static int maxTransforms() {
+        return maxTrans;
+    }
+
+    public static int maxReferences() {
+        return maxRefs;
+    }
+
+    public static Set<String> disabledReferenceUriSchemes() {
+        return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);
+    }
+
+    private static void error(String entry) {
+        throw new IllegalArgumentException(
+            "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);
+    }
+}
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11RSACipher.java	Thu Aug 25 22:35:56 2016 +0000
@@ -358,7 +358,9 @@
                 System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs);
                 tmpBuffer = p11.C_Sign(session.id(), tmpBuffer);
                 if (tmpBuffer.length > outLen) {
-                    throw new BadPaddingException("Output buffer too small");
+                    throw new BadPaddingException(
+                        "Output buffer (" + outLen + ") is too small to " +
+                        "hold the produced data (" + tmpBuffer.length + ")");
                 }
                 System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
                 n = tmpBuffer.length;
--- a/jdk/src/jdk.internal.opt/share/classes/module-info.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/jdk.internal.opt/share/classes/module-info.java	Thu Aug 25 22:35:56 2016 +0000
@@ -24,5 +24,5 @@
  */
 
 module jdk.internal.opt {
-    exports jdk.internal.joptsimple to jdk.jlink;
+    exports jdk.internal.joptsimple to jdk.jlink, jdk.jshell;
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Aug 25 22:35:56 2016 +0000
@@ -48,14 +48,12 @@
     private static final String NAME = "generate-jli-classes";
 
     private static final String BMH_PARAM = "bmh";
-
     private static final String BMH_SPECIES_PARAM = "bmh-species";
 
-    private static final String DMH_PARAM = "dmh";
-
     private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
 
-    private static final String DIRECT_METHOD_HANDLE = "java/lang/invoke/DirectMethodHandle$Holder";
+    private static final String DMH_PARAM = "dmh";
+    private static final String DIRECT_HOLDER = "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,17 +61,22 @@
     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 INVOKERS_PARAM = "invokers";
 
-    private static final String BASIC_FORMS_HANDLE = "java/lang/invoke/LambdaForm$Holder";
+    private static final String DELEGATING_HOLDER = "java/lang/invoke/DelegatingMethodHandle$Holder";
+    private static final String BASIC_FORMS_HOLDER = "java/lang/invoke/LambdaForm$Holder";
+    private static final String INVOKERS_HOLDER = "java/lang/invoke/Invokers$Holder";
 
     private static final JavaLangInvokeAccess JLIA
             = SharedSecrets.getJavaLangInvokeAccess();
 
     List<String> speciesTypes;
 
+    List<String> invokerTypes;
+
     Map<String, List<String>> dmhMethods;
 
+
     public GenerateJLIClassesPlugin() {
     }
 
@@ -117,6 +120,13 @@
     }
 
     /**
+     * @return the default invoker forms to generate.
+     */
+    public static List<String> defaultInvokers() {
+        return List.of("_L", "_I", "I_I", "LI_I", "ILL_I", "LIL_I", "L_L", "LL_V", "LLLL_L");
+    }
+
+    /**
      * @return the list of default DirectMethodHandle methods to generate.
      */
     public static Map<String, List<String>> defaultDMHMethods() {
@@ -153,6 +163,7 @@
         // Enable by default
         boolean bmhEnabled = true;
         boolean dmhEnabled = true;
+        boolean invokersEnabled = true;
         if (mainArgument != null) {
             List<String> args = Arrays.asList(mainArgument.split(","));
             if (!args.contains(BMH_PARAM)) {
@@ -161,6 +172,9 @@
             if (!args.contains(DMH_PARAM)) {
                 dmhEnabled = false;
             }
+            if (!args.contains(INVOKERS_PARAM)) {
+                dmhEnabled = false;
+            }
         }
 
         if (!bmhEnabled) {
@@ -183,6 +197,21 @@
                     .collect(Collectors.toList());
         }
 
+        if (!invokersEnabled) {
+            invokerTypes = List.of();
+        } else {
+            String args = config.get(INVOKERS_PARAM);
+            if (args != null && !args.isEmpty()) {
+                invokerTypes = Arrays.stream(args.split(","))
+                            .map(String::trim)
+                            .filter(s -> !s.isEmpty())
+                            .collect(Collectors.toList());
+                validateMethodTypes(invokerTypes);
+            } else {
+                invokerTypes = defaultInvokers();
+            }
+
+        }
         // DirectMethodHandles
         if (!dmhEnabled) {
             dmhMethods = Map.of();
@@ -196,18 +225,7 @@
                             .filter(s -> !s.isEmpty())
                             .collect(Collectors.toList());
                     dmhMethods.put(dmhParam, dmhMethodTypes);
-                    // Validation check
-                    for (String type : dmhMethodTypes) {
-                        String[] typeParts = type.split("_");
-                        // check return type (second part)
-                        if (typeParts.length != 2 || typeParts[1].length() != 1
-                                || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) {
-                            throw new PluginException(
-                                    "Method type signature must be of form [LJIFD]*_[LJIFDV]");
-                        }
-                        // expand and check arguments (first part)
-                        expandSignature(typeParts[0]);
-                    }
+                    validateMethodTypes(dmhMethodTypes);
                 }
             }
             if (dmhMethods.isEmpty()) {
@@ -216,6 +234,20 @@
         }
     }
 
+    void validateMethodTypes(List<String> dmhMethodTypes) {
+        for (String type : dmhMethodTypes) {
+            String[] typeParts = type.split("_");
+            // check return type (second part)
+            if (typeParts.length != 2 || typeParts[1].length() != 1
+                    || "LJIFDV".indexOf(typeParts[1].charAt(0)) == -1) {
+                throw new PluginException(
+                        "Method type signature must be of form [LJIFD]*_[LJIFDV]");
+            }
+            // expand and check arguments (first part)
+            expandSignature(typeParts[0]);
+        }
+    }
+
     private static void requireBasicType(char c) {
         if ("LIJFD".indexOf(c) < 0) {
             throw new PluginException(
@@ -228,9 +260,10 @@
         // Copy all but DMH_ENTRY to 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)) {
+                if (entry.path().equals(DIRECT_METHOD_HOLDER_ENTRY) ||
+                    entry.path().equals(DELEGATING_METHOD_HOLDER_ENTRY) ||
+                    entry.path().equals(INVOKERS_HOLDER_ENTRY) ||
+                    entry.path().equals(BASIC_FORMS_HOLDER_ENTRY)) {
                     return null;
                 } else {
                     return entry;
@@ -265,42 +298,53 @@
         for (List<String> entry : dmhMethods.values()) {
             count += entry.size();
         }
-        MethodType[] methodTypes = new MethodType[count];
+        MethodType[] directMethodTypes = new MethodType[count];
         int[] dmhTypes = new int[count];
         int index = 0;
         for (Map.Entry<String, List<String>> entry : dmhMethods.entrySet()) {
             String dmhType = entry.getKey();
             for (String type : entry.getValue()) {
-                methodTypes[index] = asMethodType(type);
+                directMethodTypes[index] = asMethodType(type);
                 dmhTypes[index] = DMH_METHOD_TYPE_MAP.get(dmhType);
                 index++;
             }
         }
+        MethodType[] invokerMethodTypes = new MethodType[this.invokerTypes.size()];
+        for (int i = 0; i < invokerTypes.size(); i++) {
+            invokerMethodTypes[i] = asMethodType(invokerTypes.get(i));
+        }
         try {
             byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
-                    DIRECT_METHOD_HANDLE, methodTypes, dmhTypes);
+                    DIRECT_HOLDER, directMethodTypes, dmhTypes);
             ResourcePoolEntry ndata = ResourcePoolEntry
-                    .create(DIRECT_METHOD_HANDLE_ENTRY, bytes);
+                    .create(DIRECT_METHOD_HOLDER_ENTRY, bytes);
             out.add(ndata);
 
             bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes(
-                    DELEGATING_METHOD_HANDLE, methodTypes);
-            ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HANDLE_ENTRY, bytes);
+                    DELEGATING_HOLDER, directMethodTypes);
+            ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HOLDER_ENTRY, bytes);
             out.add(ndata);
 
-            bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HANDLE);
-            ndata = ResourcePoolEntry.create(BASIC_FORMS_HANDLE_ENTRY, bytes);
+            bytes = JLIA.generateInvokersHolderClassBytes(INVOKERS_HOLDER,
+                    invokerMethodTypes);
+            ndata = ResourcePoolEntry.create(INVOKERS_HOLDER_ENTRY, bytes);
+            out.add(ndata);
+
+            bytes = JLIA.generateBasicFormsClassBytes(BASIC_FORMS_HOLDER);
+            ndata = ResourcePoolEntry.create(BASIC_FORMS_HOLDER_ENTRY, bytes);
             out.add(ndata);
         } catch (Exception ex) {
             throw new PluginException(ex);
         }
     }
-    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";
+    private static final String DIRECT_METHOD_HOLDER_ENTRY =
+            "/java.base/" + DIRECT_HOLDER + ".class";
+    private static final String DELEGATING_METHOD_HOLDER_ENTRY =
+            "/java.base/" + DELEGATING_HOLDER + ".class";
+    private static final String BASIC_FORMS_HOLDER_ENTRY =
+            "/java.base/" + BASIC_FORMS_HOLDER + ".class";
+    private static final String INVOKERS_HOLDER_ENTRY =
+            "/java.base/" + INVOKERS_HOLDER + ".class";
 
     // Convert LL -> LL, L3 -> LLL
     private static String expandSignature(String signature) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Aug 25 22:35:56 2016 +0000
@@ -56,7 +56,7 @@
 
 copy-files.description=\
 If files to copy are not absolute path, JDK home dir is used.\n\
-e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewehere/conf.txt
+e.g.: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewhere/conf.txt
 
 exclude-files.argument=<pattern-list> of files to exclude
 
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java	Thu Aug 25 22:35:56 2016 +0000
@@ -165,8 +165,8 @@
             walk(inode.child, process);
         } else {
             process.accept(inode);
-            walk(inode.sibling, process);
         }
+        walk(inode.sibling, process);
     }
 
     /**
--- a/jdk/test/ProblemList.txt	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/ProblemList.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -124,10 +124,6 @@
 # jdk_lang
 
 java/lang/StringCoding/CheckEncodings.sh                        7008363 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java	8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java	8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java	8160690 generic-all
-java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java	8160690 generic-all
 
 ############################################################################
 
@@ -211,8 +207,6 @@
 
 java/rmi/transport/dgcDeadLock/DGCDeadLock.java                 8029360 macosx-all
 
-sun/rmi/runtime/Log/6409194/NoConsoleOutput.java                8164124 windows-all
-
 ############################################################################
 
 # jdk_security
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Thu Aug 25 22:35:56 2016 +0000
@@ -205,12 +205,13 @@
                     .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
+                    // LFs may or may not be pre-generated, making frames differ
                     .replaceAll("DirectMethodHandle\\$Holder", "LambdaForm\\$DMH")
-                    .replaceAll("DMH\\.invoke", "DMH/xxxxxxxx.invoke")
+                    .replaceAll("Invokers\\$Holder", "LambdaForm\\$MH")
+                    .replaceAll("MH\\.invoke", "MH/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("xx\\.invoke([A-Za-z]*)_[A-Z_]+", "xx.invoke$1")
                     .replaceAll("\\$[0-9]+", "\\$??");
         } else {
             return produced;
--- a/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/net/MulticastSocket/NoLoopbackPackets.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -68,6 +68,7 @@
 
         MulticastSocket msock = null;
         List<SocketAddress> failedGroups = new ArrayList<SocketAddress>();
+        Sender sender = null;
         try {
             msock = new MulticastSocket();
             int port = msock.getLocalPort();
@@ -80,9 +81,8 @@
             groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port));
             groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port));
 
-            Thread sender = new Thread(new Sender(groups));
-            sender.setDaemon(true); // we want sender to stop when main thread exits
-            sender.start();
+            sender = new Sender(groups);
+            new Thread(sender).start();
 
             // Now try to receive multicast packets. we should not see any of them
             // since we disable loopback mode.
@@ -107,6 +107,9 @@
             }
         } finally {
             if (msock != null) try { msock.close(); } catch (Exception e) {}
+            if (sender != null) {
+                sender.stop();
+            }
         }
 
         if (failedGroups.size() > 0) {
@@ -119,6 +122,7 @@
 
     static class Sender implements Runnable {
         private List<SocketAddress> sendToGroups;
+        private volatile boolean stop;
 
         public Sender(List<SocketAddress> groups) {
             sendToGroups = groups;
@@ -136,7 +140,7 @@
 
                 MulticastSocket msock = new MulticastSocket();
                 msock.setLoopbackMode(true);    // disable loopback mode
-                for (;;) {
+                while (!stop) {
                     for (DatagramPacket packet : packets) {
                         msock.send(packet);
                     }
@@ -147,5 +151,9 @@
                 throw new RuntimeException(e);
             }
         }
+
+        void stop() {
+            stop = true;
+        }
     }
 }
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -119,19 +119,31 @@
             ExecutorService pool = Executors.newCachedThreadPool();
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withCachedThreadPool(pool, rand.nextInt(10));
-            testShutdownWithChannels(pool, group);
+            try {
+                testShutdownWithChannels(pool, group);
+            } finally {
+                group.shutdown();
+            }
         }
         for (int i = 0; i < 100; i++) {
             int nThreads = 1 + rand.nextInt(8);
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withFixedThreadPool(nThreads, threadFactory);
-            testShutdownWithChannels(null, group);
+            try {
+                testShutdownWithChannels(null, group);
+            } finally {
+                group.shutdown();
+            }
         }
         for (int i = 0; i < 100; i++) {
             ExecutorService pool = Executors.newCachedThreadPool();
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withThreadPool(pool);
-            testShutdownWithChannels(pool, group);
+            try {
+                testShutdownWithChannels(pool, group);
+            } finally {
+                group.shutdown();
+            }
         }
     }
 
@@ -164,19 +176,31 @@
             ExecutorService pool = pool = Executors.newCachedThreadPool();
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withCachedThreadPool(pool, rand.nextInt(5));
-            testShutdownNow(pool, group);
+            try {
+                testShutdownNow(pool, group);
+            } finally {
+                group.shutdown();
+            }
         }
         for (int i = 0; i < 10; i++) {
             int nThreads = 1 + rand.nextInt(8);
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withFixedThreadPool(nThreads, threadFactory);
-            testShutdownNow(null, group);
+            try {
+                testShutdownNow(null, group);
+            } finally {
+                group.shutdown();
+            }
         }
         for (int i = 0; i < 10; i++) {
             ExecutorService pool = Executors.newCachedThreadPool();
             AsynchronousChannelGroup group = AsynchronousChannelGroup
                     .withThreadPool(pool);
-            testShutdownNow(pool, group);
+            try {
+                testShutdownNow(pool, group);
+            } finally {
+                group.shutdown();
+            }
         }
     }
 
@@ -186,78 +210,78 @@
         AsynchronousChannelGroup group =
             AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory);
 
-        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
-        AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group);
+        try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+                AsynchronousServerSocketChannel listener =
+                    AsynchronousServerSocketChannel.open(group)) {
 
-        // initiate accept
-        listener.bind(new InetSocketAddress(0));
-        Future<AsynchronousSocketChannel> result = listener.accept();
-
-        // shutdown group
-        group.shutdown();
-        if (!group.isShutdown())
-            throw new RuntimeException("Group should be shutdown");
+            // initiate accept
+            listener.bind(new InetSocketAddress(0));
+            Future<AsynchronousSocketChannel> result = listener.accept();
 
-        // attempt to create another channel
-        try {
-            AsynchronousSocketChannel.open(group);
-            throw new RuntimeException("ShutdownChannelGroupException expected");
-        } catch (ShutdownChannelGroupException x) {
-        }
-        try {
-            AsynchronousServerSocketChannel.open(group);
-            throw new RuntimeException("ShutdownChannelGroupException expected");
-        } catch (ShutdownChannelGroupException x) {
-        }
+            // shutdown group
+            group.shutdown();
+            if (!group.isShutdown())
+                throw new RuntimeException("Group should be shutdown");
+
+            // attempt to create another channel
+            try {
+                AsynchronousSocketChannel.open(group);
+                throw new RuntimeException("ShutdownChannelGroupException expected");
+            } catch (ShutdownChannelGroupException x) {
+            }
+            try {
+                AsynchronousServerSocketChannel.open(group);
+                throw new RuntimeException("ShutdownChannelGroupException expected");
+            } catch (ShutdownChannelGroupException x) {
+            }
 
-        // attempt to create another channel by connecting. This should cause
-        // the accept operation to fail.
-        InetAddress lh = InetAddress.getLocalHost();
-        int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
-        InetSocketAddress isa = new InetSocketAddress(lh, port);
-        ch.connect(isa).get();
-        try {
-            result.get();
-            throw new RuntimeException("Connection was accepted");
-        } catch (ExecutionException x) {
-            Throwable cause = x.getCause();
-            if (!(cause instanceof IOException))
-                throw new RuntimeException("Cause should be IOException");
-            cause = cause.getCause();
-            if (!(cause instanceof ShutdownChannelGroupException))
-                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
-        }
+            // attempt to create another channel by connecting. This should cause
+            // the accept operation to fail.
+            InetAddress lh = InetAddress.getLocalHost();
+            int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
+            InetSocketAddress isa = new InetSocketAddress(lh, port);
+            ch.connect(isa).get();
+            try {
+                result.get();
+                throw new RuntimeException("Connection was accepted");
+            } catch (ExecutionException x) {
+                Throwable cause = x.getCause();
+                if (!(cause instanceof IOException))
+                    throw new RuntimeException("Cause should be IOException");
+                cause = cause.getCause();
+                if (!(cause instanceof ShutdownChannelGroupException))
+                    throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+            }
 
-        // initiate another accept even though channel group is shutdown.
-        Future<AsynchronousSocketChannel> res = listener.accept();
-        try {
-            res.get(3, TimeUnit.SECONDS);
-            throw new RuntimeException("TimeoutException expected");
-        } catch (TimeoutException x) {
+            // initiate another accept even though channel group is shutdown.
+            Future<AsynchronousSocketChannel> res = listener.accept();
+            try {
+                res.get(3, TimeUnit.SECONDS);
+                throw new RuntimeException("TimeoutException expected");
+            } catch (TimeoutException x) {
+            }
+            // connect to the listener which should cause the accept to complete
+            AsynchronousSocketChannel.open().connect(isa);
+            try {
+                res.get();
+                throw new RuntimeException("Connection was accepted");
+            } catch (ExecutionException x) {
+                Throwable cause = x.getCause();
+                if (!(cause instanceof IOException))
+                    throw new RuntimeException("Cause should be IOException");
+                cause = cause.getCause();
+                if (!(cause instanceof ShutdownChannelGroupException))
+                    throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
+            }
+
+            // group should *not* terminate as channels are open
+            boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
+            if (terminated) {
+                throw new RuntimeException("Group should not have terminated");
+            }
+        } finally {
+            group.shutdown();
         }
-        // connect to the listener which should cause the accept to complete
-        AsynchronousSocketChannel.open().connect(isa);
-        try {
-            res.get();
-            throw new RuntimeException("Connection was accepted");
-        } catch (ExecutionException x) {
-            Throwable cause = x.getCause();
-            if (!(cause instanceof IOException))
-                throw new RuntimeException("Cause should be IOException");
-            cause = cause.getCause();
-            if (!(cause instanceof ShutdownChannelGroupException))
-                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
-        }
-
-        // group should *not* terminate as channels are open
-        boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
-        if (terminated)
-            throw new RuntimeException("Group should not have terminated");
-
-        // close channel; group should terminate quickly
-        ch.close();
-        listener.close();
-        awaitTermination(group);
     }
 
     static void miscTests() throws Exception {
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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,34 +41,36 @@
 public class GroupOfOne {
 
     public static void main(String[] args) throws Exception {
+        final List<AsynchronousSocketChannel> accepted = new ArrayList<>();
+
         // create listener to accept connections
-        final AsynchronousServerSocketChannel listener =
-            AsynchronousServerSocketChannel.open()
-                .bind(new InetSocketAddress(0));
-        final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>();
-        listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
-            public void completed(AsynchronousSocketChannel ch, Void att) {
-                synchronized (accepted) {
-                    accepted.add(ch);
+        try (final AsynchronousServerSocketChannel listener =
+                AsynchronousServerSocketChannel.open()) {
+
+            listener.bind(new InetSocketAddress(0));
+            listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+                public void completed(AsynchronousSocketChannel ch, Void att) {
+                    synchronized (accepted) {
+                        accepted.add(ch);
+                    }
+                    listener.accept((Void)null, this);
                 }
-                listener.accept((Void)null, this);
-            }
-            public void failed(Throwable exc, Void att) {
-            }
-        });
+                public void failed(Throwable exc, Void att) {
+                }
+            });
 
-        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
-        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
+            int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+            SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
 
-        test(sa, true, false);
-        test(sa, false, true);
-        test(sa, true, true);
-
-        // clean-up
-        listener.close();
-        synchronized (accepted) {
-            for (AsynchronousSocketChannel ch: accepted) {
-                ch.close();
+            test(sa, true, false);
+            test(sa, false, true);
+            test(sa, true, true);
+        } finally {
+            // clean-up
+            synchronized (accepted) {
+                for (AsynchronousSocketChannel ch: accepted) {
+                    ch.close();
+                }
             }
         }
     }
@@ -86,60 +88,60 @@
                     return new Thread(r);
                 }});
         final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+        try {
+            // the latch counts down when:
+            // 1. The read operation fails (expected)
+            // 2. the close/shutdown completes
+            final CountDownLatch latch = new CountDownLatch(2);
 
-        // the latch counts down when:
-        // 1. The read operation fails (expected)
-        // 2. the close/shutdown completes
-        final CountDownLatch latch = new CountDownLatch(2);
+            ch.connect(sa, (Void)null, new CompletionHandler<Void,Void>() {
+                public void completed(Void result, Void att)  {
+                    System.out.println("Connected");
 
-        ch.connect(sa, (Void)null, new CompletionHandler<Void,Void>() {
-            public void completed(Void result, Void att)  {
-                System.out.println("Connected");
+                    // initiate I/O operation that does not complete (successfully)
+                    ByteBuffer buf = ByteBuffer.allocate(100);
+                    ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
+                        public void completed(Integer bytesRead, Void att)  {
+                            throw new RuntimeException();
+                        }
+                        public void failed(Throwable exc, Void att) {
+                            if (!(exc instanceof AsynchronousCloseException))
+                                throw new RuntimeException(exc);
+                            System.out.println("Read failed (expected)");
+                            latch.countDown();
+                        }
+                    });
 
-                // initiate I/O operation that does not complete (successfully)
-                ByteBuffer buf = ByteBuffer.allocate(100);
-                ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
-                    public void completed(Integer bytesRead, Void att)  {
+                    // close channel or shutdown group
+                    try {
+                        if (closeChannel) {
+                            System.out.print("Close channel ...");
+                            ch.close();
+                            System.out.println(" done.");
+                        }
+                        if (shutdownGroup) {
+                            System.out.print("Shutdown group ...");
+                            group.shutdownNow();
+                            System.out.println(" done.");
+                        }
+                        latch.countDown();
+                    } catch (IOException e) {
                         throw new RuntimeException();
                     }
-                    public void failed(Throwable exc, Void att) {
-                        if (!(exc instanceof AsynchronousCloseException))
-                            throw new RuntimeException(exc);
-                        System.out.println("Read failed (expected)");
-                        latch.countDown();
-                    }
-                });
+                }
+                public void failed(Throwable exc, Void att) {
+                    throw new RuntimeException(exc);
+                }
+            });
 
-                // close channel or shutdown group
-                try {
-                    if (closeChannel) {
-                        System.out.print("Close channel ...");
-                        ch.close();
-                        System.out.println(" done.");
-                    }
-                    if (shutdownGroup) {
-                        System.out.print("Shutdown group ...");
-                        group.shutdownNow();
-                        System.out.println(" done.");
-                    }
-                    latch.countDown();
-                } catch (IOException e) {
-                    throw new RuntimeException();
-                }
-            }
-            public void failed(Throwable exc, Void att) {
-                throw new RuntimeException(exc);
-            }
-        });
-
-        latch.await();
-
-        // clean-up
-        group.shutdown();
-        boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
-        if (!terminated)
-            throw new RuntimeException("Group did not terminate");
-
+            latch.await();
+        } finally {
+            // clean-up
+            group.shutdown();
+            boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
+            if (!terminated)
+                throw new RuntimeException("Group did not terminate");
+        }
         System.out.println("TEST OKAY");
     }
 }
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -76,89 +76,91 @@
     }
 
     public static void main(String[] args) throws Exception {
-        // create listener to accept connections
-        final AsynchronousServerSocketChannel listener =
-            AsynchronousServerSocketChannel.open()
-                .bind(new InetSocketAddress(0));
-        listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
-            public void completed(final AsynchronousSocketChannel ch, Void att) {
-                listener.accept((Void)null, this);
-                final ByteBuffer buf = ByteBuffer.allocate(100);
-                ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
-                    public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
-                        if (bytesRead < 0) {
-                            try { ch.close(); } catch (IOException ignore) { }
-                        } else {
-                            buf.clear();
-                            ch.read(buf, ch, this);
-                        }
-                    }
-                    public void failed(Throwable exc, AsynchronousSocketChannel ch) {
-                        try { ch.close(); } catch (IOException ignore) { }
-                    }
-                });
-            }
-            public void failed(Throwable exc, Void att) {
-            }
-        });
-        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
-        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
-
         // create 3-10 channels, each in its own group
         final int groupCount = 3 + rand.nextInt(8);
-        AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
+        final AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
         final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount];
-        for (int i=0; i<groupCount; i++) {
-            ThreadFactory factory = createThreadFactory(i);
-            AsynchronousChannelGroup group;
-            if (rand.nextBoolean()) {
-                int nThreads = 1 + rand.nextInt(10);
-                group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
-            } else {
-                ExecutorService pool = Executors.newCachedThreadPool(factory);
-                group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
-            }
-            groups[i] = group;
+
+        // create listener to accept connections
+        try (final AsynchronousServerSocketChannel listener =
+                AsynchronousServerSocketChannel.open()) {
 
-            // create channel in group and connect it to the server
-            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
-            ch.connect(sa).get();
-            channels[i] = ch;
-        }
+            listener.bind(new InetSocketAddress(0));
+            listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+                public void completed(final AsynchronousSocketChannel ch, Void att) {
+                    listener.accept((Void)null, this);
+                    final ByteBuffer buf = ByteBuffer.allocate(100);
+                    ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+                        public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
+                            if (bytesRead < 0) {
+                                try { ch.close(); } catch (IOException ignore) { }
+                            } else {
+                                buf.clear();
+                                ch.read(buf, ch, this);
+                            }
+                        }
+                        public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+                            try { ch.close(); } catch (IOException ignore) { }
+                        }
+                    });
+                }
+                public void failed(Throwable exc, Void att) {
+                }
+            });
+            int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+            SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
 
-        // randomly write to each channel, ensuring that the completion handler
-        // is always invoked by a thread with the right identity.
-        final AtomicInteger writeCount = new AtomicInteger(100);
-        channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
-            public void completed(Integer bytesWritten, Integer groupId) {
-                if (bytesWritten != 1)
-                    fail("Expected 1 byte to be written");
-                if (!myGroup.get().equals(groupId))
-                    fail("Handler invoked by thread with the wrong identity");
-                if (writeCount.decrementAndGet() > 0) {
-                    int id = rand.nextInt(groupCount);
-                    channels[id].write(getBuffer(), id, this);
+            for (int i=0; i<groupCount; i++) {
+                ThreadFactory factory = createThreadFactory(i);
+                AsynchronousChannelGroup group;
+                if (rand.nextBoolean()) {
+                    int nThreads = 1 + rand.nextInt(10);
+                    group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
                 } else {
-                    done.countDown();
+                    ExecutorService pool = Executors.newCachedThreadPool(factory);
+                    group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
                 }
+                groups[i] = group;
+
+                // create channel in group and connect it to the server
+                AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
+                ch.connect(sa).get();
+                channels[i] = ch;
             }
-            public void failed(Throwable exc, Integer groupId) {
-                fail(exc.getMessage());
-            }
-        });
-
-        // wait until done
-        done.await();
 
-        // clean-up
-        for (AsynchronousSocketChannel ch: channels)
-            ch.close();
-        for (AsynchronousChannelGroup group: groups)
-            group.shutdownNow();
-        listener.close();
+            // randomly write to each channel, ensuring that the completion handler
+            // is always invoked by a thread with the right identity.
+            final AtomicInteger writeCount = new AtomicInteger(100);
+            channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
+                public void completed(Integer bytesWritten, Integer groupId) {
+                    if (bytesWritten != 1)
+                        fail("Expected 1 byte to be written");
+                    if (!myGroup.get().equals(groupId))
+                        fail("Handler invoked by thread with the wrong identity");
+                    if (writeCount.decrementAndGet() > 0) {
+                        int id = rand.nextInt(groupCount);
+                        channels[id].write(getBuffer(), id, this);
+                    } else {
+                        done.countDown();
+                    }
+                }
+                public void failed(Throwable exc, Integer groupId) {
+                    fail(exc.getMessage());
+                }
+            });
 
-        if (failed.get())
-            throw new RuntimeException("Test failed - see log for details");
+            // wait until done
+            done.await();
+        } finally {
+            // clean-up
+            for (AsynchronousSocketChannel ch: channels)
+                ch.close();
+            for (AsynchronousChannelGroup group: groups)
+                group.shutdownNow();
+
+            if (failed.get())
+                throw new RuntimeException("Test failed - see log for details");
+        }
     }
 
     static ByteBuffer getBuffer() {
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -66,21 +66,30 @@
         // group with fixed thread pool
         int nThreads = 1 + rand.nextInt(4);
         AsynchronousChannelGroup group =
-            AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
-        testRestart(group, 100);
-        group.shutdown();
+                AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory);
+        try {
+            testRestart(group, 100);
+        } finally {
+            group.shutdown();
+        }
 
         // group with cached thread pool
         ExecutorService pool = Executors.newCachedThreadPool(factory);
         group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
-        testRestart(group, 100);
-        group.shutdown();
+        try {
+            testRestart(group, 100);
+        } finally {
+            group.shutdown();
+        }
 
         // group with custom thread pool
-        group = AsynchronousChannelGroup
-                .withThreadPool(Executors.newFixedThreadPool(1+rand.nextInt(5), factory));
-        testRestart(group, 100);
-        group.shutdown();
+        group = AsynchronousChannelGroup.withThreadPool(
+                Executors.newFixedThreadPool(1+rand.nextInt(5), factory));
+        try {
+            testRestart(group, 100);
+        } finally {
+            group.shutdown();
+        }
 
         // give time for threads to terminate
         Thread.sleep(3000);
@@ -92,45 +101,43 @@
     static void testRestart(AsynchronousChannelGroup group, int count)
         throws Exception
     {
-        AsynchronousServerSocketChannel listener =
-            AsynchronousServerSocketChannel.open(group)
-                .bind(new InetSocketAddress(0));
+        try (AsynchronousServerSocketChannel listener =
+                AsynchronousServerSocketChannel.open(group)) {
 
-        for (int i=0; i<count; i++) {
-            final CountDownLatch latch = new CountDownLatch(1);
+            listener.bind(new InetSocketAddress(0));
+            for (int i=0; i<count; i++) {
+                final CountDownLatch latch = new CountDownLatch(1);
 
-            listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
-                public void completed(AsynchronousSocketChannel ch, Void att) {
-                    try {
-                        ch.close();
-                    } catch (IOException ignore) { }
+                listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+                    public void completed(AsynchronousSocketChannel ch, Void att) {
+                        try {
+                            ch.close();
+                        } catch (IOException ignore) { }
 
-                    latch.countDown();
+                        latch.countDown();
 
-                    // throw error or runtime exception
-                    if (rand.nextBoolean()) {
-                        throw new Error();
-                    } else {
-                        throw new RuntimeException();
+                        // throw error or runtime exception
+                        if (rand.nextBoolean()) {
+                            throw new Error();
+                        } else {
+                            throw new RuntimeException();
+                        }
                     }
-                }
-                public void failed(Throwable exc, Void att) {
-                }
-            });
+                    public void failed(Throwable exc, Void att) {
+                    }
+                });
 
-            // establish loopback connection which should cause completion
-            // handler to be invoked.
-            int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
-            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
-            InetAddress lh = InetAddress.getLocalHost();
-            ch.connect(new InetSocketAddress(lh, port)).get();
-            ch.close();
+                // establish loopback connection which should cause completion
+                // handler to be invoked.
+                int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+                try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
+                    InetAddress lh = InetAddress.getLocalHost();
+                    ch.connect(new InetSocketAddress(lh, port)).get();
+                }
 
-            // wait for handler to be invoked
-            latch.await();
+                // wait for handler to be invoked
+                latch.await();
+            }
         }
-
-        // clean-up
-        listener.close();
     }
 }
--- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java	Thu Aug 25 22:35:56 2016 +0000
@@ -95,7 +95,7 @@
         return 0;
     }
 
-    static int checkContentTypes(String[] extensions, String[][] expectedTypes)
+    static int checkContentTypes(String[] extensions, String[] expectedTypes)
         throws IOException {
         if (extensions.length != expectedTypes.length) {
             System.err.println("Parameter array lengths differ");
@@ -112,27 +112,10 @@
                     System.err.println("Content type of " + extension
                             + " cannot be determined");
                     failures++;
-                } else {
-                    boolean isTypeFound = false;
-                    for (String s : expectedTypes[i]) {
-                        if (type.equals(s)) {
-                            isTypeFound = true;
-                            break;
-                        }
-                    }
-                    if (!isTypeFound) {
-                        System.err.printf("Content type: %s; expected: ", type);
-                        int j = 0;
-                        for (String s : expectedTypes[i]) {
-                            if (j++ == 0) {
-                                System.err.printf("%s", s);
-                            } else {
-                                System.err.printf(", or %s", s);
-                            }
-                        }
-                        System.err.println();
-                        failures++;
-                    }
+                } else if (!type.equals(expectedTypes[i])) {
+                    System.err.printf("Content type: %s; expected: %s%n",
+                        type, expectedTypes);
+                    failures++;
                 }
             } finally {
                 Files.delete(file);
@@ -174,8 +157,6 @@
 
         // Verify that certain media extensions are mapped to the correct type.
         String[] extensions = new String[]{
-            "aac",
-            "flac",
             "jpg",
             "mp3",
             "mp4",
@@ -183,15 +164,13 @@
             "png",
             "webm"
         };
-        String[][] expectedTypes = new String[][] {
-            {"audio/aac", "audio/x-aac", "audio/vnd.dlna.adts"},
-            {"audio/flac", "audio/x-flac"},
-            {"image/jpeg"},
-            {"audio/mpeg"},
-            {"video/mp4"},
-            {"application/pdf"},
-            {"image/png"},
-            {"video/webm"}
+        String[] expectedTypes = new String[] {
+            "image/jpeg",
+            "audio/mpeg",
+            "video/mp4",
+            "application/pdf",
+            "image/png",
+            "video/webm"
         };
         failures += checkContentTypes(extensions, expectedTypes);
 
--- a/jdk/test/java/nio/file/Path/PathOps.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/file/Path/PathOps.java	Thu Aug 25 22:35:56 2016 +0000
@@ -197,6 +197,19 @@
         return this;
     }
 
+    PathOps relativizeFail(String other) {
+        out.format("test relativize %s\n", other);
+        checkPath();
+        Path that = FileSystems.getDefault().getPath(other);
+        try {
+            Path result = path.relativize(that);
+            out.format("\tExpected: IllegalArgumentException");
+            out.format("\tActual: %s\n",  result);
+            fail();
+        } catch (IllegalArgumentException expected) { }
+        return this;
+    }
+
     PathOps normalize(String expected) {
         out.println("check normalized path");
         checkPath();
@@ -572,29 +585,709 @@
             .resolveSibling("C:\\", "C:\\");
 
         // relativize
-        test("foo")
-            .relativize("foo", "")
-            .relativize("bar", "..\\bar")
+        test("C:\\a")
+            .relativize("C:\\a", "")
+            .relativize("C:\\", "..")
+            .relativize("C:\\.", "..")
+            .relativize("C:\\..", "..")
+            .relativize("C:\\..\\..", "..")
+            .relativize("C:\\a\\b", "b")
+            .relativize("C:\\a\\b\\c", "b\\c")
+            .relativize("C:\\a\\.", "")        // "." also valid
+            .relativize("C:\\a\\..", "..")
+            .relativize("C:\\x", "..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\a\\b")
+            .relativize("C:\\a\\b", "")
+            .relativize("C:\\a", "..")
+            .relativize("C:\\", "..\\..")
+            .relativize("C:\\.", "..\\..")
+            .relativize("C:\\..", "..\\..")
+            .relativize("C:\\..\\..", "..\\..")
+            .relativize("C:\\a\\b\\c", "c")
+            .relativize("C:\\a\\.", "..")
+            .relativize("C:\\a\\..", "..\\..")
+            .relativize("C:\\x", "..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\a\\b\\c")
+            .relativize("C:\\a\\b\\c", "")
+            .relativize("C:\\a\\b", "..")
+            .relativize("C:\\a", "..\\..")
+            .relativize("C:\\", "..\\..\\..")
+            .relativize("C:\\.", "..\\..\\..")
+            .relativize("C:\\..", "..\\..\\..")
+            .relativize("C:\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\a\\b\\c\\d", "d")
+            .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("C:\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\c\\..", "..")
+            .relativize("C:\\a\\x", "..\\..\\x")
+            .relativize("C:\\x", "..\\..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\a")
+            .relativize("C:\\a", "")
+            .relativize("C:\\", "..")
+            .relativize("C:\\.", "..")
+            .relativize("C:\\..", "..")
+            .relativize("C:\\..\\..", "..")
+            .relativize("C:\\a\\b", "b")
+            .relativize("C:\\a\\b\\c", "b\\c")
+            .relativize("C:\\a\\.", "")        // "." also valid
+            .relativize("C:\\a\\..", "..")
+            .relativize("C:\\x", "..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\a\\b")
+            .relativize("C:\\a\\b", "")
+            .relativize("C:\\a", "..")
+            .relativize("C:\\", "..\\..")
+            .relativize("C:\\.", "..\\..")
+            .relativize("C:\\..", "..\\..")
+            .relativize("C:\\..\\..", "..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..")
+            .relativize("C:\\a\\b\\c", "c")
+            .relativize("C:\\a\\b\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\..", "..")
+            .relativize("C:\\a\\x", "..\\x")
+            .relativize("C:\\x", "..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\..\\a\\b")
+            .relativize("C:\\a\\b", "")
+            .relativize("C:\\a", "..")
+            .relativize("C:\\", "..\\..")
+            .relativize("C:\\.", "..\\..")
+            .relativize("C:\\..", "..\\..")
+            .relativize("C:\\..\\..", "..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..")
+            .relativize("C:\\a\\b\\c", "c")
+            .relativize("C:\\a\\b\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\..", "..")
+            .relativize("C:\\a\\x", "..\\x")
+            .relativize("C:\\x", "..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\a\\b\\c")
+            .relativize("C:\\a\\b\\c", "")
+            .relativize("C:\\a\\b", "..")
+            .relativize("C:\\a", "..\\..")
+            .relativize("C:\\", "..\\..\\..")
+            .relativize("C:\\.", "..\\..\\..")
+            .relativize("C:\\..", "..\\..\\..")
+            .relativize("C:\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\a\\b\\c\\d", "d")
+            .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("C:\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\c\\..", "..")
+            .relativize("C:\\a\\x", "..\\..\\x")
+            .relativize("C:\\x", "..\\..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\..\\a\\b\\c")
+            .relativize("C:\\a\\b\\c", "")
+            .relativize("C:\\a\\b", "..")
+            .relativize("C:\\a", "..\\..")
+            .relativize("C:\\", "..\\..\\..")
+            .relativize("C:\\.", "..\\..\\..")
+            .relativize("C:\\..", "..\\..\\..")
+            .relativize("C:\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\a\\b\\c\\d", "d")
+            .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("C:\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\c\\..", "..")
+            .relativize("C:\\a\\x", "..\\..\\x")
+            .relativize("C:\\x", "..\\..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\..\\..\\a\\b\\c")
+            .relativize("C:\\a\\b\\c", "")
+            .relativize("C:\\a\\b", "..")
+            .relativize("C:\\a", "..\\..")
+            .relativize("C:\\", "..\\..\\..")
+            .relativize("C:\\.", "..\\..\\..")
+            .relativize("C:\\..", "..\\..\\..")
+            .relativize("C:\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("C:\\a\\b\\c\\d", "d")
+            .relativize("C:\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("C:\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("C:\\a\\b\\c\\..", "..")
+            .relativize("C:\\a\\x", "..\\..\\x")
+            .relativize("C:\\x", "..\\..\\..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\.\\a")
+            .relativize("C:\\a", "")
+            .relativize("C:\\", "..")
+            .relativize("C:\\.", "..")
+            .relativize("C:\\..", "..")
+            .relativize("C:\\..\\..", "..")
+            .relativize("C:\\a\\b", "b")
+            .relativize("C:\\a\\b\\c", "b\\c")
+            .relativize("C:\\a\\.", "")        // "." also valid
+            .relativize("C:\\a\\..", "..")
+            .relativize("C:\\x", "..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\..\\a")
+            .relativize("C:\\a", "")
+            .relativize("C:\\", "..")
+            .relativize("C:\\.", "..")
+            .relativize("C:\\..", "..")
+            .relativize("C:\\..\\..", "..")
+            .relativize("C:\\a\\b", "b")
+            .relativize("C:\\a\\b\\c", "b\\c")
+            .relativize("C:\\a\\.", "")        // "." also valid
+            .relativize("C:\\a\\..", "..")
+            .relativize("C:\\x", "..\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:\\a\\..")
+            .relativize("C:\\a", "a")
+            .relativize("C:\\", "")          // "." is also valid
+            .relativize("C:\\.", "")
+            .relativize("C:\\..", "")
+            .relativize("C:\\..\\..", "")
+            .relativize("C:\\a\\.", "a")
+            .relativize("C:\\a\\..", "")
+            .relativize("C:\\x", "x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("C:a")
+            .relativize("C:a", "")
+            .relativize("C:", "..")
+            .relativize("C:.", "..")
+            .relativize("C:..", "..\\..")
+            .relativize("C:..\\..", "..\\..\\..")
+            .relativize("C:.\\..", "..\\..")
+            .relativize("C:a\\b", "b")
+            .relativize("C:a\\b\\c", "b\\c")
+            .relativize("C:..\\x", "..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("C:a\\b")
+            .relativize("C:a\\b", "")
+            .relativize("C:a", "..")
+            .relativize("C:", "..\\..")
+            .relativize("C:.", "..\\..")
+            .relativize("C:..", "..\\..\\..")
+            .relativize("C:..\\..", "..\\..\\..\\..")
+            .relativize("C:.\\..", "..\\..\\..")
+            .relativize("C:a\\b\\c", "c")
+            .relativize("C:..\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("C:a\\b\\c")
+            .relativize("C:a\\b\\c", "")
+            .relativize("C:a\\b", "..")
+            .relativize("C:a", "..\\..")
+            .relativize("C:", "..\\..\\..")
+            .relativize("C:.", "..\\..\\..")
+            .relativize("C:..", "..\\..\\..\\..")
+            .relativize("C:..\\..", "..\\..\\..\\..\\..")
+            .relativize("C:.\\..", "..\\..\\..\\..")
+            .relativize("C:a\\b\\c\\d", "d")
+            .relativize("C:a\\b\\c\\d\\e", "d\\e")
+            .relativize("C:a\\x", "..\\..\\x")
+            .relativize("C:..\\x", "..\\..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("C:")
+            .relativize("C:a", "a")
+            .relativize("C:a\\b\\c", "a\\b\\c")
+            .relativize("C:", "")
+            .relativize("C:.", "")              // "" also valid
+            .relativize("C:..", "..")
+            .relativize("C:..\\..", "..\\..")
+            .relativize("C:.\\..", "..")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("C:..")
+            .relativize("C:..\\a", "a")
+            .relativize("C:..", "")
+            .relativize("C:.\\..", "")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("C:..\\a")
+            .relativize("C:..\\a\\b", "b")
+            .relativize("C:..\\a", "")
+            .relativize("C:..", "..")
+            .relativize("C:.\\..", "..")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("C:..\\a\\b")
+            .relativize("C:..\\a\\b\\c", "c")
+            .relativize("C:..\\a\\b", "")
+            .relativize("C:..\\a", "..")
+            .relativize("C:..", "..\\..")
+            .relativize("C:.\\..", "..\\..")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail("x");
+        test("C:a\\..")
+            .relativize("C:b", "b")
+            .relativize("C:", "")
+            .relativize("C:.", "")       // "." also valid
+            .relativize("C:..", "..")
+            .relativize("C:a\\..\\b", "b")
+            .relativize("C:a\\..", "")
+            .relativize("C:..\\b", "..\\b")
+            .relativize("C:b\\..", "")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("x");
+        test("C:a\\..\\b")
+            .relativize("C:a\\..\\b", "")
+            .relativize("C:a\\..", "..")
+            .relativize("C:", "..")
+            .relativize("C:.", "..")
+            .relativize("C:..", "..\\..")
+            .relativize("C:b", "")
+            .relativize("C:c", "..\\c")
+            .relativize("C:..\\c", "..\\..\\c")
+            .relativize("C:a\\..\\b\\c", "c")
+            .relativizeFail("C:\\x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("x");
+        test("\\a")
+            .relativize("\\a", "")
+            .relativize("\\", "..")
+            .relativize("\\.", "..")
+            .relativize("\\..", "..")
+            .relativize("\\..\\..", "..")
+            .relativize("\\a\\b", "b")
+            .relativize("\\a\\b\\c", "b\\c")
+            .relativize("\\a\\.", "")        // "." also valid
+            .relativize("\\a\\..", "..")
+            .relativize("\\x", "..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\a\\b")
+            .relativize("\\a\\b", "")
+            .relativize("\\a", "..")
+            .relativize("\\", "..\\..")
+            .relativize("\\.", "..\\..")
+            .relativize("\\..", "..\\..")
+            .relativize("\\..\\..", "..\\..")
+            .relativize("\\a\\b\\c", "c")
+            .relativize("\\a\\.", "..")
+            .relativize("\\a\\..", "..\\..")
+            .relativize("\\x", "..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\a\\b\\c")
+            .relativize("\\a\\b\\c", "")
+            .relativize("\\a\\b", "..")
+            .relativize("\\a", "..\\..")
+            .relativize("\\", "..\\..\\..")
+            .relativize("\\.", "..\\..\\..")
+            .relativize("\\..", "..\\..\\..")
+            .relativize("\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("\\a\\b\\c\\d", "d")
+            .relativize("\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("\\a\\b\\c\\..", "..")
+            .relativize("\\a\\x", "..\\..\\x")
+            .relativize("\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\a")
+            .relativize("\\a", "")
+            .relativize("\\", "..")
+            .relativize("\\.", "..")
+            .relativize("\\..", "..")
+            .relativize("\\..\\..", "..")
+            .relativize("\\a\\b", "b")
+            .relativize("\\a\\b\\c", "b\\c")
+            .relativize("\\a\\.", "")        // "." also valid
+            .relativize("\\a\\..", "..")
+            .relativize("\\x", "..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\a\\b")
+            .relativize("\\a\\b", "")
+            .relativize("\\a", "..")
+            .relativize("\\", "..\\..")
+            .relativize("\\.", "..\\..")
+            .relativize("\\..", "..\\..")
+            .relativize("\\..\\..", "..\\..")
+            .relativize("\\..\\..\\..", "..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..")
+            .relativize("\\a\\b\\c", "c")
+            .relativize("\\a\\b\\.", "")        // "." also valid
+            .relativize("\\a\\b\\..", "..")
+            .relativize("\\a\\x", "..\\x")
+            .relativize("\\x", "..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\..\\a\\b")
+            .relativize("\\a\\b", "")
+            .relativize("\\a", "..")
+            .relativize("\\", "..\\..")
+            .relativize("\\.", "..\\..")
+            .relativize("\\..", "..\\..")
+            .relativize("\\..\\..", "..\\..")
+            .relativize("\\..\\..\\..", "..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..")
+            .relativize("\\a\\b\\c", "c")
+            .relativize("\\a\\b\\.", "")        // "." also valid
+            .relativize("\\a\\b\\..", "..")
+            .relativize("\\a\\x", "..\\x")
+            .relativize("\\x", "..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\a\\b\\c")
+            .relativize("\\a\\b\\c", "")
+            .relativize("\\a\\b", "..")
+            .relativize("\\a", "..\\..")
+            .relativize("\\", "..\\..\\..")
+            .relativize("\\.", "..\\..\\..")
+            .relativize("\\..", "..\\..\\..")
+            .relativize("\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("\\a\\b\\c\\d", "d")
+            .relativize("\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("\\a\\b\\c\\..", "..")
+            .relativize("\\a\\x", "..\\..\\x")
+            .relativize("\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\..\\a\\b\\c")
+            .relativize("\\a\\b\\c", "")
+            .relativize("\\a\\b", "..")
+            .relativize("\\a", "..\\..")
+            .relativize("\\", "..\\..\\..")
+            .relativize("\\.", "..\\..\\..")
+            .relativize("\\..", "..\\..\\..")
+            .relativize("\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("\\a\\b\\c\\d", "d")
+            .relativize("\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("\\a\\b\\c\\..", "..")
+            .relativize("\\a\\x", "..\\..\\x")
+            .relativize("\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\..\\..\\a\\b\\c")
+            .relativize("\\a\\b\\c", "")
+            .relativize("\\a\\b", "..")
+            .relativize("\\a", "..\\..")
+            .relativize("\\", "..\\..\\..")
+            .relativize("\\.", "..\\..\\..")
+            .relativize("\\..", "..\\..\\..")
+            .relativize("\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..", "..\\..\\..")
+            .relativize("\\..\\..\\..\\..", "..\\..\\..")
+            .relativize("\\a\\b\\c\\d", "d")
+            .relativize("\\a\\b\\c\\d\\e", "d\\e")
+            .relativize("\\a\\b\\c\\.", "")        // "." also valid
+            .relativize("\\a\\b\\c\\..", "..")
+            .relativize("\\a\\x", "..\\..\\x")
+            .relativize("\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\.\\a")
+            .relativize("\\a", "")
+            .relativize("\\", "..")
+            .relativize("\\.", "..")
+            .relativize("\\..", "..")
+            .relativize("\\..\\..", "..")
+            .relativize("\\a\\b", "b")
+            .relativize("\\a\\b\\c", "b\\c")
+            .relativize("\\a\\.", "")        // "." also valid
+            .relativize("\\a\\..", "..")
+            .relativize("\\x", "..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\..\\a")
+            .relativize("\\a", "")
+            .relativize("\\", "..")
+            .relativize("\\.", "..")
+            .relativize("\\..", "..")
+            .relativize("\\..\\..", "..")
+            .relativize("\\a\\b", "b")
+            .relativize("\\a\\b\\c", "b\\c")
+            .relativize("\\a\\.", "")        // "." also valid
+            .relativize("\\a\\..", "..")
+            .relativize("\\x", "..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\a\\..")
+            .relativize("\\a", "a")
+            .relativize("\\", "")          // "." is also valid
+            .relativize("\\.", "")
+            .relativize("\\..", "")
+            .relativize("\\..\\..", "")
+            .relativize("\\a\\.", "a")
+            .relativize("\\a\\..", "")
+            .relativize("\\x", "x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("\\")
+            .relativize("\\a", "a")
+            .relativize("\\", "")          // "." is also valid
+            .relativize("\\.", "")
+            .relativize("\\..", "")
+            .relativize("\\..\\..", "")
+            .relativize("\\a\\.", "a")
+            .relativize("\\a\\..", "")
+            .relativize("\\x", "x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("a")
+            .relativize("a", "")
+            .relativize("", "..")
+            .relativize(".", "..")
             .relativize("..", "..\\..")
-            .relativize("", "..");
-        test("foo\\bar")
-            .relativize("foo\\bar", "")
-            .relativize("foo", "..")
-            .relativize("gus", "..\\..\\gus")
+            .relativize("..\\..", "..\\..\\..")
+            .relativize(".\\..", "..\\..")
+            .relativize("a\\b", "b")
+            .relativize("a\\b\\c", "b\\c")
+            .relativize("..\\x", "..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("a\\b")
+            .relativize("a\\b", "")
+            .relativize("a", "..")
+            .relativize("", "..\\..")
+            .relativize(".", "..\\..")
             .relativize("..", "..\\..\\..")
-            .relativize("", "..\\..");
-        test("C:\\a\\b\\c")
-            .relativize("C:\\a", "..\\..")
-            .relativize("C:\\a\\b\\c", "")
-            .relativize("C:\\x", "..\\..\\..\\x");
-        test("\\\\server\\share\\foo")
-            .relativize("\\\\server\\share\\bar", "..\\bar")
-            .relativize("\\\\server\\share\\foo", "");
+            .relativize("..\\..", "..\\..\\..\\..")
+            .relativize(".\\..", "..\\..\\..")
+            .relativize("a\\b\\c", "c")
+            .relativize("..\\x", "..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("a\\b\\c")
+            .relativize("a\\b\\c", "")
+            .relativize("a\\b", "..")
+            .relativize("a", "..\\..")
+            .relativize("", "..\\..\\..")
+            .relativize(".", "..\\..\\..")
+            .relativize("..", "..\\..\\..\\..")
+            .relativize("..\\..", "..\\..\\..\\..\\..")
+            .relativize(".\\..", "..\\..\\..\\..")
+            .relativize("a\\b\\c\\d", "d")
+            .relativize("a\\b\\c\\d\\e", "d\\e")
+            .relativize("a\\x", "..\\..\\x")
+            .relativize("..\\x", "..\\..\\..\\..\\x")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
         test("")
             .relativize("a", "a")
             .relativize("a\\b\\c", "a\\b\\c")
+            .relativize("", "")
+            .relativize(".", ".")
             .relativize("..", "..")
-            .relativize("", "");
+            .relativize("..\\..", "..\\..")
+            .relativize(".\\..", ".\\..")     // ".." also valid
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("..")
+            .relativize("..\\a", "a")
+            .relativize("..", "")
+            .relativize(".\\..", "")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("..\\a")
+            .relativize("..\\a\\b", "b")
+            .relativize("..\\a", "")
+            .relativize("..", "..")
+            .relativize(".\\..", "..")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("..\\a\\b")
+            .relativize("..\\a\\b\\c", "c")
+            .relativize("..\\a\\b", "")
+            .relativize("..\\a", "..")
+            .relativize("..", "..\\..")
+            .relativize(".\\..", "..\\..")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x")
+            .relativizeFail("")
+            .relativizeFail("x");
+        test("a\\..")
+            .relativize("b", "b")
+            .relativize("", "")
+            .relativize(".", "")       // "." also valid
+            .relativize("..", "..")
+            .relativize("a\\..\\b", "b")
+            .relativize("a\\..", "")
+            .relativize("..\\b", "..\\b")
+            .relativize("b\\..", "")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
+        test("a\\..\\b")
+            .relativize("a\\..\\b", "")
+            .relativize("a\\..", "..")
+            .relativize("", "..")
+            .relativize(".", "..")
+            .relativize("..", "..\\..")
+            .relativize("b", "")
+            .relativize("c", "..\\c")
+            .relativize("..\\c", "..\\..\\c")
+            .relativize("a\\..\\b\\c", "c")
+            .relativizeFail("C:\\x")
+            .relativizeFail("C:x")
+            .relativizeFail("\\")
+            .relativizeFail("\\x");
 
         // normalize
         test("C:\\")
@@ -971,20 +1664,324 @@
             .resolve("", "");
 
         // relativize
+        test("/a")
+            .relativize("/a", "")
+            .relativize("/", "..")
+            .relativize("/.", "..")
+            .relativize("/..", "..")
+            .relativize("/../..", "..")
+            .relativize("/a/b", "b")
+            .relativize("/a/b/c", "b/c")
+            .relativize("/a/.", "")        // "." also valid
+            .relativize("/a/..", "..")
+            .relativize("/x", "../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/a/b")
+            .relativize("/a/b", "")
+            .relativize("/a", "..")
+            .relativize("/", "../..")
+            .relativize("/.", "../..")
+            .relativize("/..", "../..")
+            .relativize("/../..", "../..")
+            .relativize("/a/b/c", "c")
+            .relativize("/a/.", "..")
+            .relativize("/a/..", "../..")
+            .relativize("/x", "../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
         test("/a/b/c")
             .relativize("/a/b/c", "")
+            .relativize("/a/b", "..")
+            .relativize("/a", "../..")
+            .relativize("/", "../../..")
+            .relativize("/.", "../../..")
+            .relativize("/..", "../../..")
+            .relativize("/../..", "../../..")
+            .relativize("/../../..", "../../..")
+            .relativize("/../../../..", "../../..")
+            .relativize("/a/b/c/d", "d")
             .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/b/c/.", "")        // "." also valid
+            .relativize("/a/b/c/..", "..")
+            .relativize("/a/x", "../../x")
+            .relativize("/x", "../../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../a")
+            .relativize("/a", "")
+            .relativize("/", "..")
+            .relativize("/.", "..")
+            .relativize("/..", "..")
+            .relativize("/../..", "..")
+            .relativize("/a/b", "b")
+            .relativize("/a/b/c", "b/c")
+            .relativize("/a/.", "")        // "." also valid
+            .relativize("/a/..", "..")
+            .relativize("/x", "../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../a/b")
+            .relativize("/a/b", "")
+            .relativize("/a", "..")
+            .relativize("/", "../..")
+            .relativize("/.", "../..")
+            .relativize("/..", "../..")
+            .relativize("/../..", "../..")
+            .relativize("/../../..", "../..")
+            .relativize("/../../../..", "../..")
+            .relativize("/a/b/c", "c")
+            .relativize("/a/b/.", "")        // "." also valid
+            .relativize("/a/b/..", "..")
+            .relativize("/a/x", "../x")
+            .relativize("/x", "../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../../a/b")
+            .relativize("/a/b", "")
+            .relativize("/a", "..")
+            .relativize("/", "../..")
+            .relativize("/.", "../..")
+            .relativize("/..", "../..")
+            .relativize("/../..", "../..")
+            .relativize("/../../..", "../..")
+            .relativize("/../../../..", "../..")
+            .relativize("/a/b/c", "c")
+            .relativize("/a/b/.", "")        // "." also valid
+            .relativize("/a/b/..", "..")
+            .relativize("/a/x", "../x")
+            .relativize("/x", "../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../a/b/c")
+            .relativize("/a/b/c", "")
+            .relativize("/a/b", "..")
+            .relativize("/a", "../..")
+            .relativize("/", "../../..")
+            .relativize("/.", "../../..")
+            .relativize("/..", "../../..")
+            .relativize("/../..", "../../..")
+            .relativize("/../../..", "../../..")
+            .relativize("/../../../..", "../../..")
+            .relativize("/a/b/c/d", "d")
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/b/c/.", "")        // "." also valid
+            .relativize("/a/b/c/..", "..")
+            .relativize("/a/x", "../../x")
+            .relativize("/x", "../../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../../a/b/c")
+            .relativize("/a/b/c", "")
+            .relativize("/a/b", "..")
+            .relativize("/a", "../..")
+            .relativize("/", "../../..")
+            .relativize("/.", "../../..")
+            .relativize("/..", "../../..")
+            .relativize("/../..", "../../..")
+            .relativize("/../../..", "../../..")
+            .relativize("/../../../..", "../../..")
+            .relativize("/a/b/c/d", "d")
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/b/c/.", "")        // "." also valid
+            .relativize("/a/b/c/..", "..")
             .relativize("/a/x", "../../x")
-            .relativize("/x", "../../../x");
+            .relativize("/x", "../../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../../../a/b/c")
+            .relativize("/a/b/c", "")
+            .relativize("/a/b", "..")
+            .relativize("/a", "../..")
+            .relativize("/", "../../..")
+            .relativize("/.", "../../..")
+            .relativize("/..", "../../..")
+            .relativize("/../..", "../../..")
+            .relativize("/../../..", "../../..")
+            .relativize("/../../../..", "../../..")
+            .relativize("/a/b/c/d", "d")
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/b/c/.", "")        // "." also valid
+            .relativize("/a/b/c/..", "..")
+            .relativize("/a/x", "../../x")
+            .relativize("/x", "../../../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/./a")
+            .relativize("/a", "")
+            .relativize("/", "..")
+            .relativize("/.", "..")
+            .relativize("/..", "..")
+            .relativize("/../..", "..")
+            .relativize("/a/b", "b")
+            .relativize("/a/b/c", "b/c")
+            .relativize("/a/.", "")        // "." also valid
+            .relativize("/a/..", "..")
+            .relativize("/x", "../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/../a")
+            .relativize("/a", "")
+            .relativize("/", "..")
+            .relativize("/.", "..")
+            .relativize("/..", "..")
+            .relativize("/../..", "..")
+            .relativize("/a/b", "b")
+            .relativize("/a/b/c", "b/c")
+            .relativize("/a/.", "")        // "." also valid
+            .relativize("/a/..", "..")
+            .relativize("/x", "../x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/a/..")
+            .relativize("/a", "a")
+            .relativize("/", "")          // "." is also valid
+            .relativize("/.", "")
+            .relativize("/..", "")
+            .relativize("/../..", "")
+            .relativize("/a/.", "a")
+            .relativize("/a/..", "")
+            .relativize("/x", "x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("/")
+            .relativize("/a", "a")
+            .relativize("/", "")          // "." is also valid
+            .relativize("/.", "")
+            .relativize("/..", "")
+            .relativize("/../..", "")
+            .relativize("/a/.", "a")
+            .relativize("/a/..", "")
+            .relativize("/x", "x")
+            .relativizeFail("x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("..");
+        test("a")
+            .relativize("a", "")
+            .relativize("", "..")
+            .relativize(".", "..")
+            .relativize("..", "../..")
+            .relativize("../..", "../../..")
+            .relativize("./..", "../..")
+            .relativize("a/b", "b")
+            .relativize("a/b/c", "b/c")
+            .relativize("../x", "../../x")
+            .relativizeFail("/")
+            .relativizeFail("/x");
+        test("a/b")
+            .relativize("a/b", "")
+            .relativize("a", "..")
+            .relativize("", "../..")
+            .relativize(".", "../..")
+            .relativize("..", "../../..")
+            .relativize("../..", "../../../..")
+            .relativize("./..", "../../..")
+            .relativize("a/b/c", "c")
+            .relativize("../x", "../../../x")
+            .relativizeFail("/")
+            .relativizeFail("/x");
         test("a/b/c")
+            .relativize("a/b/c", "")
+            .relativize("a/b", "..")
+            .relativize("a", "../..")
+            .relativize("", "../../..")
+            .relativize(".", "../../..")
+            .relativize("..", "../../../..")
+            .relativize("../..", "../../../../..")
+            .relativize("./..", "../../../..")
             .relativize("a/b/c/d", "d")
+            .relativize("a/b/c/d/e", "d/e")
             .relativize("a/x", "../../x")
-            .relativize("x", "../../../x")
-            .relativize("", "../../..");
+            .relativize("../x", "../../../../x")
+            .relativizeFail("/")
+            .relativizeFail("/x");
         test("")
             .relativize("a", "a")
             .relativize("a/b/c", "a/b/c")
-            .relativize("", "");
+            .relativize("", "")
+            .relativize(".", ".")
+            .relativize("..", "..")
+            .relativize("../..", "../..")
+            .relativize("./..", "./..")     // ".." also valid
+            .relativizeFail("/")
+            .relativizeFail("/x");
+        test("..")
+            .relativize("../a", "a")
+            .relativize("..", "")
+            .relativize("./..", "")
+            .relativizeFail("/")
+            .relativizeFail("/x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("../a")
+            .relativize("../a/b", "b")
+            .relativize("../a", "")
+            .relativize("..", "..")
+            .relativize("./..", "..")
+            .relativizeFail("/")
+            .relativizeFail("/x")
+            .relativizeFail("")
+            .relativizeFail(".")
+            .relativizeFail("x");
+        test("../a/b")
+            .relativize("../a/b/c", "c")
+            .relativize("../a/b", "")
+            .relativize("../a", "..")
+            .relativize("..", "../..")
+            .relativize("./..", "../..")
+            .relativizeFail("/")
+            .relativizeFail("/x")
+            .relativizeFail("")
+            .relativizeFail("x");
+        test("a/..")
+            .relativize("b", "b")
+            .relativize("", "")
+            .relativize(".", "")       // "." also valid
+            .relativize("..", "..")
+            .relativize("a/../b", "b")
+            .relativize("a/..", "")
+            .relativize("../b", "../b")
+            .relativize("b/..", "")
+            .relativizeFail("/")
+            .relativizeFail("/x");
+        test("a/../b")
+            .relativize("a/../b", "")
+            .relativize("a/..", "..")
+            .relativize("", "..")
+            .relativize(".", "..")
+            .relativize("..", "../..")
+            .relativize("b", "")
+            .relativize("c", "../c")
+            .relativize("../c", "../../c")
+            .relativize("a/../b/c", "c")
+            .relativizeFail("/")
+            .relativizeFail("/x");
 
         // normalize
         test("/")
--- a/jdk/test/java/nio/file/WatchService/LotsOfCancels.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java	Thu Aug 25 22:35:56 2016 +0000
@@ -53,10 +53,11 @@
             Path testDir = Paths.get(System.getProperty("test.dir", "."));
             Path top = Files.createTempDirectory(testDir, "LotsOfCancels");
             for (int i=1; i<=16; i++) {
+                int id = i;
                 Path dir = Files.createDirectory(top.resolve("dir-" + i));
                 WatchService watcher = FileSystems.getDefault().newWatchService();
-                pool.submit(() -> handle(dir, watcher));
-                pool.submit(() -> poll(watcher));
+                pool.submit(() -> handle(id, dir, watcher));
+                pool.submit(() -> poll(id, watcher));
             }
         } finally {
             pool.shutdown();
@@ -74,7 +75,8 @@
      * Stress the given WatchService, specifically the cancel method, in
      * the given directory. Closes the WatchService when done.
      */
-    static void handle(Path dir, WatchService watcher) {
+    static void handle(int id, Path dir, WatchService watcher) {
+        System.out.printf("begin handle %d%n", id);
         try {
             try {
                 Path file = dir.resolve("anyfile");
@@ -85,12 +87,15 @@
                     key.cancel();
                 }
             } finally {
+                System.out.printf("WatchService %d closing ...%n", id);
                 watcher.close();
+                System.out.printf("WatchService %d closed %n", id);
             }
         } catch (Exception e) {
             e.printStackTrace();
             failed = true;
         }
+        System.out.printf("end handle %d%n", id);
     }
 
     /**
@@ -98,7 +103,8 @@
      * queue drained, it also hogs a CPU core which seems necessary to
      * tickle the original bug.
      */
-    static void poll(WatchService watcher) {
+    static void poll(int id, WatchService watcher) {
+        System.out.printf("begin poll %d%n", id);
         try {
             for (;;) {
                 WatchKey key = watcher.take();
@@ -108,10 +114,12 @@
                 }
             }
         } catch (ClosedWatchServiceException expected) {
-            // nothing to do
+            // nothing to do but print
+            System.out.printf("poll %d expected exception %s%n", id, expected);
         } catch (Exception e) {
             e.printStackTrace();
             failed = true;
         }
+        System.out.printf("end poll %d%n", id);
     }
 }
--- a/jdk/test/java/nio/file/WatchService/UpdateInterference.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/nio/file/WatchService/UpdateInterference.java	Thu Aug 25 22:35:56 2016 +0000
@@ -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
@@ -33,6 +33,9 @@
 import static java.nio.file.StandardWatchEventKinds.*;
 
 public class UpdateInterference {
+
+    private static volatile boolean stop;
+
     public static void main(String[] args) throws IOException, InterruptedException {
         final Path root = Files.createTempDirectory("test");
         final Path foo = root.resolve("foo");
@@ -43,64 +46,89 @@
         Files.createDirectory(bar);
         Files.createDirectory(baz);
 
-        final WatchService watcher = root.getFileSystem().newWatchService();
-        final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE);
-        final WatchKey barKey = bar.register(watcher, ENTRY_CREATE);
+        try (final WatchService watcher = root.getFileSystem().newWatchService()) {
+            final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE);
+            final WatchKey barKey = bar.register(watcher, ENTRY_CREATE);
+
+            Thread t1 = null;
+            Thread t2 = null;
+            try {
+                t1 = new Thread() {
 
-        new Thread() {
-            { setDaemon(true); }
+                    @Override
+                    public void run() {
+                        while (!stop) {
+                            try {
+                                final Path temp = Files.createTempFile(foo, "temp", ".tmp");
+                                Files.delete(temp);
+                                Thread.sleep(10);
+                            } catch (IOException | InterruptedException e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
+                    }
+                };
+
+                t2 = new Thread() {
 
-            @Override
-            public void run() {
-                while (true) {
-                    try {
-                        final Path temp = Files.createTempFile(foo, "temp", ".tmp");
-                        Files.delete(temp);
-                        Thread.sleep(10);
-                    } catch (IOException | InterruptedException e) {
-                        throw new RuntimeException(e);
+                    @Override
+                    public void run() {
+                        WatchKey bazKeys[] = new WatchKey[32];
+                        while (!stop) {
+                            try {
+                                for( int i = 0; i < bazKeys.length; i++) {
+                                    bazKeys[i] = baz.register(watcher, ENTRY_CREATE);
+                                }
+                                for( int i = 0; i < bazKeys.length; i++) {
+                                    bazKeys[i].cancel();
+                                }
+                                Thread.sleep(1);
+                            } catch (IOException | InterruptedException e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
                     }
+                };
+
+                t1.start();
+                t2.start();
+
+                long time = System.currentTimeMillis();
+                while ((System.currentTimeMillis() - time) < 15000) {
+                    final WatchKey key = watcher.poll(60, TimeUnit.SECONDS);
+                    if (key == null) continue;
+
+                    if (key != fooKey) {
+                        List<WatchEvent<?>> pollEvents = key.pollEvents();
+                        for (WatchEvent<?> watchEvent : pollEvents) {
+                            System.out.println(watchEvent.count() + " " +
+                                            watchEvent.kind() + " " +
+                                            watchEvent.context());
+                        }
+                        throw new RuntimeException("Event received for unexpected key");
+                    }
+                    key.reset();
+                }
+            } finally {
+                // the threads should stop before WatchService is closed
+                // to avoid ClosedWatchServiceException
+                stop = true;
+
+                // wait for threads to finish
+                if (t1 != null) {
+                    t1.join();
+                }
+
+                if (t2 != null) {
+                    t2.join();
                 }
             }
-        }.start();
-
-        new Thread() {
-            { setDaemon(true); }
-
-            @Override
-            public void run() {
-                WatchKey bazKeys[] = new WatchKey[32];
-                while (true) {
-                    try {
-                        for( int i = 0; i < bazKeys.length; i++) {
-                            bazKeys[i] = baz.register(watcher, ENTRY_CREATE);
-                        }
-                        for( int i = 0; i < bazKeys.length; i++) {
-                            bazKeys[i].cancel();
-                        }
-                        Thread.sleep(1);
-                    } catch (IOException | InterruptedException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-        }.start();
-
-        long time = System.currentTimeMillis();
-        while ((System.currentTimeMillis() - time) < 15000) {
-            final WatchKey key = watcher.poll(60, TimeUnit.SECONDS);
-            if (key == null) continue;
-
-            if (key != fooKey) {
-                List<WatchEvent<?>> pollEvents = key.pollEvents();
-                for (WatchEvent<?> watchEvent : pollEvents) {
-                    System.out.println(watchEvent.count() + " " +
-                                       watchEvent.kind() + " " +
-                                       watchEvent.context());
-                }
-                throw new RuntimeException("Event received for unexpected key");
-            }
-            key.reset();
+        } finally {
+            // clean up
+            Files.delete(foo);
+            Files.delete(bar);
+            Files.delete(baz);
+            Files.delete(root);
         }
     }
 }
--- a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -419,6 +419,21 @@
         ZoneOffset.ofHoursMinutesSeconds(-19, 0, 0);
     }
 
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_minutesMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, -1);
+    }
+
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_secondsMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, 0, Integer.MIN_VALUE);
+    }
+
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_minutesAndSecondsMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, Integer.MIN_VALUE);
+    }
+
     //-----------------------------------------------------------------------
     @Test
     public void test_factory_ofTotalSeconds() {
@@ -437,6 +452,11 @@
         ZoneOffset.ofTotalSeconds(-18 * 60 * 60 - 1);
     }
 
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_ofTotalSeconds_minValue() {
+        ZoneOffset.ofTotalSeconds(Integer.MIN_VALUE);
+    }
+
     //-----------------------------------------------------------------------
     // from()
     //-----------------------------------------------------------------------
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java	Thu Aug 25 22:35:56 2016 +0000
@@ -360,6 +360,21 @@
     }
 
     /**
+     * Test keySet().removeAll on empty map
+     */
+    public void testKeySet_empty_removeAll() {
+        ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
+        Set<Integer> set = map.keySet();
+        set.removeAll(Collections.emptyList());
+        assertTrue(map.isEmpty());
+        assertTrue(set.isEmpty());
+        // following is test for JDK-8163353
+        set.removeAll(Collections.emptySet());
+        assertTrue(map.isEmpty());
+        assertTrue(set.isEmpty());
+    }
+
+    /**
      * keySet.toArray returns contains all keys
      */
     public void testKeySetToArray() {
--- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java	Thu Aug 25 22:35:56 2016 +0000
@@ -80,7 +80,7 @@
         }
 
         try (JarFile jf = new JarFile(multirelease)) {
-            Assert.assertFalse(jf.isMultiRelease());
+            Assert.assertTrue(jf.isMultiRelease());
         }
 
         try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Runtime.version())) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,72 @@
+/*
+ * 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 8151893
+ * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property
+ * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom
+ */
+
+import java.security.Security;
+import java.util.List;
+import org.jcp.xml.dsig.internal.dom.Policy;
+
+public class SecureValidationPolicy {
+
+    public static void main(String[] args) throws Exception {
+
+        List<String> restrictedSchemes = List.of("file:/tmp/foo",
+            "http://java.com", "https://java.com");
+        List<String> restrictedAlgs = List.of(
+            "http://www.w3.org/TR/1999/REC-xslt-19991116",
+            "http://www.w3.org/2001/04/xmldsig-more#rsa-md5",
+            "http://www.w3.org/2001/04/xmldsig-more#hmac-md5",
+            "http://www.w3.org/2001/04/xmldsig-more#md5");
+
+        // Test expected defaults
+        System.out.println("Testing defaults");
+        if (!Policy.restrictNumTransforms(6)) {
+            throw new Exception("maxTransforms not enforced");
+        }
+        if (!Policy.restrictNumReferences(31)) {
+            throw new Exception("maxReferences not enforced");
+        }
+        for (String scheme : restrictedSchemes) {
+            if (!Policy.restrictReferenceUriScheme(scheme)) {
+                throw new Exception(scheme + " scheme not restricted");
+            }
+        }
+        for (String alg : restrictedAlgs) {
+            if (!Policy.restrictAlg(alg)) {
+                throw new Exception(alg + " alg not restricted");
+            }
+        }
+        if (!Policy.restrictDuplicateIds()) {
+            throw new Exception("noDuplicateIds not enforced");
+        }
+        if (!Policy.restrictRetrievalMethodLoops()) {
+            throw new Exception("noRetrievalMethodLoops not enforced");
+        }
+    }
+}
--- a/jdk/test/jdk/lambda/TEST.properties	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/jdk/lambda/TEST.properties	Thu Aug 25 22:35:56 2016 +0000
@@ -3,4 +3,4 @@
 TestNG.dirs = .
 
 javatest.maxOutputSize = 250000
-modules = jdk.compiler
+modules = jdk.compiler jdk.zipfs
--- a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java	Thu Aug 25 22:35:56 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, 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
@@ -26,6 +26,7 @@
  * @summary Verify the defining class loader of each module never delegates
  *          to its child class loader. Also sanity check java.compact2
  *          requires.
+ * @modules java.compact2
  * @run testng/othervm --add-modules=ALL-SYSTEM VerifyModuleDelegation
  */
 
@@ -33,7 +34,9 @@
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReference;
 import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.Set;
+import static java.util.stream.Collectors.toSet;
 
 import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
 
@@ -58,8 +61,9 @@
             .requires(Set.of(PUBLIC), "java.xml")
             .build();
 
-    private static final Set<ModuleReference> MREFS
-            = ModuleFinder.ofSystem().findAll();
+    private static final Set<ModuleDescriptor> MREFS
+            = Layer.boot().modules().stream().map(Module::getDescriptor)
+                .collect(toSet());
 
     private void check(ModuleDescriptor md, ModuleDescriptor ref) {
         assertTrue(md.requires().size() == ref.requires().size());
@@ -69,7 +73,7 @@
     @Test
     public void checkJavaBase() {
         ModuleDescriptor md =
-                MREFS.stream().map(ModuleReference::descriptor)
+                MREFS.stream()
                      .filter(d -> d.name().equals(JAVA_BASE))
                      .findFirst().orElseThrow(Error::new);
 
@@ -78,7 +82,7 @@
     @Test
     public void checkCompact2() {
         ModuleDescriptor md =
-                MREFS.stream().map(ModuleReference::descriptor)
+                MREFS.stream()
                      .filter(d -> d.name().equals(JAVA_COMPACT2))
                      .findFirst().orElseThrow(Error::new);
         check(md, COMPACT2);
@@ -87,7 +91,7 @@
     @Test
     public void checkLoaderDelegation() {
         Layer boot = Layer.boot();
-        MREFS.stream().map(ModuleReference::descriptor)
+        MREFS.stream()
              .forEach(md -> md.requires().stream().forEach(req ->
                  {
                      // check if M requires D and D's loader must be either the
--- a/jdk/test/jdk/modules/scenarios/container/ContainerTest.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java	Thu Aug 25 22:35:56 2016 +0000
@@ -26,6 +26,8 @@
  * @library /lib/testlibrary
  * @modules jdk.jartool/sun.tools.jar
  *          jdk.compiler
+ *          jdk.zipfs
+ *          java.se
  * @build ContainerTest CompilerUtils jdk.testlibrary.*
  * @run testng ContainerTest
  * @summary Starts a simple container that uses dynamic configurations
--- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java	Thu Aug 25 22:35:56 2016 +0000
@@ -28,7 +28,7 @@
  * @library /lib/testlibrary/java/util/jar
  * @build Compiler JarBuilder CreateMultiReleaseTestJars
  * @run testng MultiReleaseJarTest
- * @modules java.compiler
+ * @modules jdk.compiler
  *          jdk.jartool
  *          jdk.zipfs
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,124 @@
+/*
+ * 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 8164389
+ * @summary walk entries in a jdk.nio.zipfs.JarFileSystem
+ * @modules jdk.jartool/sun.tools.jar
+ * @run testng JFSTester
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class JFSTester {
+    private URI jarURI;
+    private Path jarfile;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        String userdir = System.getProperty("user.dir",".");
+        jarfile = Paths.get(userdir, "test.jar");
+        String srcdir = System.getProperty("test.src");
+        String[] args = (
+                        "-cf "
+                        + jarfile.toString()
+                        + " -C "
+                        + srcdir
+                        + " root --release 9 -C "
+                        + srcdir
+                        + System.getProperty("file.separator")
+                        + "v9 root"
+        ).split(" +");
+        new sun.tools.jar.Main(System.out, System.err, "jar").run(args);
+        String ssp = jarfile.toUri().toString();
+        jarURI = new URI("jar", ssp, null);
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.deleteIfExists(jarfile);
+    }
+
+    @Test
+    public void testWalk() throws IOException {
+
+        // no configuration, treat multi-release jar as unversioned
+        Map<String,String> env = new HashMap<>();
+        Set<String> contents = doTest(env);
+        Set<String> baseContents = Set.of(
+                "This is leaf 1.\n",
+                "This is leaf 2.\n",
+                "This is leaf 3.\n",
+                "This is leaf 4.\n"
+        );
+        Assert.assertEquals(contents, baseContents);
+
+        // a configuration and jar file is multi-release
+        env.put("multi-release", "9");
+        contents = doTest(env);
+        Set<String> versionedContents = Set.of(
+                "This is versioned leaf 1.\n",
+                "This is versioned leaf 2.\n",
+                "This is versioned leaf 3.\n",
+                "This is versioned leaf 4.\n"
+        );
+        Assert.assertEquals(contents, versionedContents);
+    }
+
+    private Set<String> doTest(Map<String,String> env) throws IOException {
+        Set<String> contents;
+        try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) {
+            Path root = fs.getPath("root");
+            contents = Files.walk(root)
+                    .filter(p -> !Files.isDirectory(p))
+                    .map(this::pathToContents)
+                    .collect(Collectors.toSet());
+        }
+        return contents;
+    }
+
+    private String pathToContents(Path path) {
+        try {
+            return new String(Files.readAllBytes(path));
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is leaf 1.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is leaf 2.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is leaf 3.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is leaf 4.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is versioned leaf 1.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is versioned leaf 2.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is versioned leaf 3.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,1 @@
+This is versioned leaf 4.
--- a/jdk/test/jdk/security/jarsigner/Spec.java	Thu Aug 25 21:18:46 2016 +0000
+++ b/jdk/test/jdk/security/jarsigner/Spec.java	Thu Aug 25 22:35:56 2016 +0000
@@ -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 @@
  * @modules java.base/sun.security.tools.keytool
  *          java.base/sun.security.provider.certpath
  *          jdk.jartool
+ *          jdk.crypto.ec
  */
 
 import com.sun.jarsigner.ContentSigner;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/KdcPolicy.java	Thu Aug 25 22:35:56 2016 +0000
@@ -0,0 +1,366 @@
+/*
+ * 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.*;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.security.auth.login.LoginException;
+import sun.security.krb5.Asn1Exception;
+import sun.security.krb5.Config;
+
+/*
+ * @test
+ * @bug 8164656
+ * @run main/othervm KdcPolicy udp
+ * @run main/othervm KdcPolicy tcp
+ * @summary krb5.kdc.bad.policy test
+ */
+public class KdcPolicy {
+
+    // Is this test on UDP?
+    static boolean udp;
+
+    public static void main(String[] args) throws Exception {
+
+        udp = args[0].equals("udp");
+
+        try {
+            main0();
+        } catch (LoginException le) {
+            Throwable cause = le.getCause();
+            if (cause instanceof Asn1Exception) {
+                System.out.println("Another process sends a packet to " +
+                        "this server. Ignored.");
+                return;
+            }
+            throw le;
+        }
+    }
+
+    static DebugMatcher cm = new DebugMatcher();
+
+    static void main0() throws Exception {
+
+        System.setProperty("sun.security.krb5.debug", "true");
+
+        // One real KDC. Must be created before fake KDCs
+        // to read the TestHosts file.
+        OneKDC kdc = new OneKDC(null);
+
+        // Two fake KDCs, d1 and d2 only listen but do not respond.
+
+        if (udp) {
+            try (DatagramSocket d1 = new DatagramSocket();
+                 DatagramSocket d2 = new DatagramSocket()) {
+                run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort());
+            }
+        } else {
+            try (ServerSocket d1 = new ServerSocket(0);
+                 ServerSocket d2 = new ServerSocket(0)) {
+                run(d1.getLocalPort(), d2.getLocalPort(), kdc.getPort());
+            }
+        }
+    }
+
+    static void run(int p1, int p2, int p3) throws Exception {
+
+        // cm.kdc() will return a and b for fake KDCs, and c for real KDC.
+        cm.addPort(-1).addPort(p1).addPort(p2).addPort(p3);
+
+        System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
+
+        // Check default timeout is 30s. Use real KDC only, otherwise too
+        // slow to wait for timeout.
+        writeConf(-1, -1, p3);
+        test("c30000c30000");
+
+        // 1. Default policy is tryLast
+        //Security.setProperty("krb5.kdc.bad.policy", "tryLast");
+
+        // Need a real KDC, otherwise there is no last good.
+        // This test waste 3 seconds waiting for d1 to timeout.
+        // It is possible the real KDC cannot fulfil the request
+        // in 3s, so it might fail (either 1st time or 2nd time).
+        writeConf(1, 3000, p1, p3);
+        test("a3000c3000c3000|a3000c3000-|a3000c3000c3000-");
+
+        // If a test case won't use a real KDC, it can be sped up.
+        writeConf(3, 5, p1, p2);
+        test("a5a5a5b5b5b5-");  // default max_retries == 3
+        test("a5a5a5b5b5b5-");  // all bad means no bad
+
+        // 2. No policy.
+        Security.setProperty("krb5.kdc.bad.policy", "");
+        Config.refresh();
+
+        // This case needs a real KDC, otherwise, all bad means no
+        // bad and we cannot tell the difference. This case waste 3
+        // seconds on d1 to timeout twice. It is possible the real KDC
+        // cannot fulfil the request within 3s, so it might fail
+        // (either 1st time or 2nd time).
+        writeConf(1, 3000, p1, p3);
+        test("a3000c3000a3000c3000|a3000c3000-|a3000c3000a3000c3000-");
+
+        // 3. tryLess with no argument means tryLess:1,5000
+        Security.setProperty("krb5.kdc.bad.policy", "tryLess");
+
+        // This case will waste 11s. We are checking that the default
+        // value of 5000 in tryLess is only used if it's less than timeout
+        // in krb5.conf
+        writeConf(1, 6000, p1);
+        test("a6000-"); // timeout in krb5.conf is 6s
+        test("a5000-"); // tryLess to 5s. This line can be made faster if
+                        // d1 is a read KDC, but we have no existing method
+                        // to start KDC on an existing ServerSocket (port).
+
+        writeConf(-1, 4, p1, p2);
+        test("a4a4a4b4b4b4-");  // default max_retries == 3
+        test("a4b4-");          // tryLess to 1. And since 4 < 5000, use 4.
+        Config.refresh();
+        test("a4a4a4b4b4b4-");
+
+        writeConf(5, 4, p1, p2);
+        test("a4a4a4a4a4b4b4b4b4b4-"); // user-provided max_retries == 5
+        test("a4b4-");
+        Config.refresh();
+        test("a4a4a4a4a4b4b4b4b4b4-");
+
+        // 3. tryLess with arguments
+        Security.setProperty("krb5.kdc.bad.policy",
+                "tryLess:2,5");
+
+        writeConf(-1, 6, p1, p2);
+        test("a6a6a6b6b6b6-");  // default max_retries == 3
+        test("a5a5b5b5-");      // tryLess to 2
+        Config.refresh();
+        test("a6a6a6b6b6b6-");
+
+        writeConf(5, 4, p1, p2);
+        test("a4a4a4a4a4b4b4b4b4b4-");  // user-provided max_retries == 5
+        test("a4a4b4b4-");              // tryLess to 2
+        Config.refresh();
+        test("a4a4a4a4a4b4b4b4b4b4-");
+    }
+
+    /**
+     * Writes a krb5.conf file.
+     * @param max max_retries, -1 if not set
+     * @param to kdc_timeout, -1 if not set
+     * @param ports where KDCs listen on
+     */
+    static void writeConf(int max, int to, int... ports) throws Exception {
+
+        // content of krb5.conf
+        String conf = "";
+
+        // Extra settings in [libdefaults]
+        String inDefaults = "";
+
+        // Extra settings in [realms]
+        String inRealm = "";
+
+        // We will randomly put extra settings only in [libdefaults],
+        // or in [realms] but with different values in [libdefaults],
+        // to prove that settings in [realms] override those in [libdefaults].
+        Random r = new Random();
+
+        if (max > 0) {
+            if (r.nextBoolean()) {
+                inDefaults += "max_retries = " + max + "\n";
+            } else {
+                inRealm += "   max_retries = " + max + "\n";
+                inDefaults += "max_retries = " + (max + 1) + "\n";
+            }
+        }
+
+        if (to > 0) {
+            if (r.nextBoolean()) {
+                inDefaults += "kdc_timeout = " + to + "\n";
+            } else {
+                inRealm += "   kdc_timeout = " + to + "\n";
+                inDefaults += "kdc_timeout = " + (to + 1) + "\n";
+            }
+        }
+
+        if (udp) {
+            if (r.nextBoolean()) {
+                inDefaults += "udp_preference_limit = 10000\n";
+            } else if (r.nextBoolean()) {
+                inRealm += "   udp_preference_limit = 10000\n";
+                inDefaults += "udp_preference_limit = 1\n";
+            } // else no settings means UDP
+        } else {
+            if (r.nextBoolean()) {
+                inDefaults += "udp_preference_limit = 1\n";
+            } else {
+                inRealm += "   udp_preference_limit = 1\n";
+                inDefaults += "udp_preference_limit = 10000\n";
+            }
+        }
+
+        conf = "[libdefaults]\n" +
+                "default_realm = " + OneKDC.REALM + "\n" +
+                inDefaults +
+                "\n" +
+                "[realms]\n" +
+                OneKDC.REALM + " = {\n";
+
+        for (int port : ports) {
+            conf += "   kdc = " + OneKDC.KDCHOST + ":" + port + "\n" +
+                    inRealm;
+        }
+
+        conf += "}\n";
+
+        Files.write(Paths.get("alternative-krb5.conf"), conf.getBytes());
+        Config.refresh();
+    }
+
+    /**
+     * One call of krb5 login. As long as the result matches one of expected,
+     * the test is considered as success. The grammar of expected is
+     *
+     *    kdc#, timeout, kdc#, timeout, ..., optional "-" for failure
+     */
+    static void test(String... expected) throws Exception {
+
+        System.out.println("------------------TEST----------------------");
+        PrintStream oldOut = System.out;
+        boolean failed = false;
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(bo));
+        try {
+            Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        } catch (Exception e) {
+            failed = true;
+        } finally {
+            System.setOut(oldOut);
+        }
+
+        String[] lines = new String(bo.toByteArray()).split("\n");
+        StringBuilder sb = new StringBuilder();
+        for (String line: lines) {
+            if (cm.match(line)) {
+                if (udp != cm.isUDP()) {
+                    sb.append("x");
+                }
+                sb.append(cm.kdc()).append(cm.timeout());
+            }
+        }
+        if (failed) sb.append('-');
+
+        String output = sb.toString();
+
+        boolean found = false;
+        for (String ex : expected) {
+            if (output.matches(ex)) {
+                System.out.println("Expected: " + ex + ", actual " + output);
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) {
+            System.out.println("--------------- ERROR START -------------");
+            System.out.println(new String(bo.toByteArray()));
+            System.out.println("--------------- ERROR END ---------------");
+            throw new Exception("Does not match. Output is " + output);
+        }
+    }
+
+    /**
+     * A helper class to match the krb5 debug output:
+     * >>> KDCCommunication: kdc=host UDP:11555, timeout=200,Attempt =1, #bytes=138
+     *
+     * Example:
+     *  DebugMatcher cm = new DebugMatcher();
+     *  cm.addPort(12345).addPort(11555);
+     *  for (String line : debugOutput) {
+     *      if (cm.match(line)) {
+     *          System.out.printf("%c%d\n", cm.kdc(), cm.timeout());
+     *          // shows b200 for the example above
+     *      }
+     *  }
+     */
+    static class DebugMatcher {
+
+        static final Pattern re = Pattern.compile(
+                ">>> KDCCommunication: kdc=\\S+ (TCP|UDP):(\\d+), " +
+                        "timeout=(\\d+),Attempt\\s*=(\\d+)");
+
+        List<Integer> kdcPorts = new ArrayList<>();
+        Matcher matcher;
+
+        /**
+         * Add KDC ports one by one. See {@link #kdc()}.
+         */
+        DebugMatcher addPort(int port) {
+            if (port > 0) {
+                kdcPorts.add(port);
+            } else {
+                kdcPorts.clear();
+            }
+            return this;
+        }
+
+        /**
+         * When a line matches the ">>> KDCCommunication:" pattern. After a
+         * match, the getters below can be called on this match.
+         */
+        boolean match(String line) {
+            matcher = re.matcher(line);
+            return matcher.find();
+        }
+
+        /**
+         * Protocol of this match, "UDP" or "TCP".
+         */
+        boolean isUDP() {
+            return matcher.group(1).equals("UDP");
+        }
+
+        /**
+         * KDC for this match, "a" for the one 1st added bt addPort(), "b"
+         * for second, etc. Undefined for not added.
+         */
+        char kdc() {
+            int port = Integer.parseInt(matcher.group(2));
+            return (char) (kdcPorts.indexOf(port) + 'a');
+        }
+
+        /**
+         * Timeout value for this match.
+         */
+        int timeout() {
+            return Integer.parseInt(matcher.group(3));
+        }
+    }
+}