Merge jdk9-b88
authorduke
Wed, 05 Jul 2017 20:54:58 +0200
changeset 33025 16b4968f9bb8
parent 33024 8e7aa0e2c42f (diff)
parent 32972 26d6cb3dde11 (current diff)
child 33026 1747b3826577
child 33027 f40267448832
child 33050 6d40d389d985
child 33060 5e522d8ea16c
child 33201 0729c02cb845
child 33234 611d93af2f9b
child 33304 9a65d47fef72
child 33322 4400d372d3c6
child 33326 e5b07cebf4a0
child 33329 15a50c5e0668
child 33344 cc4a221f42b7
child 33348 301b567dba56
child 33354 94480e2b28e1
child 33357 917698397de2
child 33359 0cb7d3a940db
child 33365 b25c5559727e
Merge
--- a/.hgtags-top-repo	Wed Jul 05 20:54:03 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 20:54:58 2017 +0200
@@ -329,3 +329,4 @@
 1c8134475511ffe6726677e1418a89a7a45e92d6 jdk9-b84
 1f345217c9bab05f192d00cf1665b3286c49ccdb jdk9-b85
 2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
+fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
--- a/common/autoconf/generated-configure.sh	Wed Jul 05 20:54:03 2017 +0200
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 20:54:58 2017 +0200
@@ -4587,7 +4587,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1444224363
+DATE_WHEN_GENERATED=1444643341
 
 ###############################################################################
 #
@@ -46678,10 +46678,24 @@
     X_CFLAGS=
     X_LIBS=
   else
-    # Check if the user has specified sysroot, but not --x-includes or --x-libraries.
-    # Make a simple check for the libraries at the sysroot, and setup --x-includes and
-    # --x-libraries for the sysroot, if that seems to be correct.
-    if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
+
+    if test "x${with_x}" = xno; then
+      as_fn_error $? "It is not possible to disable the use of X11. Remove the --without-x option." "$LINENO" 5
+    fi
+
+    if test "x${with_x}" != x &&  test "x${with_x}" != xyes; then
+      # The user has specified a X11 base directory. Use it for includes and
+      # libraries, unless explicitely overridden.
+      if test "x$x_includes" = xNONE; then
+        x_includes="${with_x}/include"
+      fi
+      if test "x$x_libraries" = xNONE; then
+        x_libraries="${with_x}/lib"
+      fi
+    else
+      # Check if the user has specified sysroot, but not --with-x, --x-includes or --x-libraries.
+      # Make a simple check for the libraries at the sysroot, and setup --x-includes and
+      # --x-libraries for the sysroot, if that seems to be correct.
       if test "x$SYSROOT" != "x"; then
         if test "x$x_includes" = xNONE; then
           if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
--- a/common/autoconf/lib-x11.m4	Wed Jul 05 20:54:03 2017 +0200
+++ b/common/autoconf/lib-x11.m4	Wed Jul 05 20:54:58 2017 +0200
@@ -35,10 +35,24 @@
     X_CFLAGS=
     X_LIBS=
   else
-    # Check if the user has specified sysroot, but not --x-includes or --x-libraries.
-    # Make a simple check for the libraries at the sysroot, and setup --x-includes and
-    # --x-libraries for the sysroot, if that seems to be correct.
-    if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
+
+    if test "x${with_x}" = xno; then
+      AC_MSG_ERROR([It is not possible to disable the use of X11. Remove the --without-x option.])
+    fi
+
+    if test "x${with_x}" != x &&  test "x${with_x}" != xyes; then
+      # The user has specified a X11 base directory. Use it for includes and
+      # libraries, unless explicitely overridden.
+      if test "x$x_includes" = xNONE; then
+        x_includes="${with_x}/include"
+      fi
+      if test "x$x_libraries" = xNONE; then
+        x_libraries="${with_x}/lib"
+      fi
+    else
+      # Check if the user has specified sysroot, but not --with-x, --x-includes or --x-libraries.
+      # Make a simple check for the libraries at the sysroot, and setup --x-includes and
+      # --x-libraries for the sysroot, if that seems to be correct.
       if test "x$SYSROOT" != "x"; then
         if test "x$x_includes" = xNONE; then
           if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
--- a/corba/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -329,3 +329,4 @@
 df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
 3ec06af1368924469f7ce60a00324bac55eaeecc jdk9-b85
 0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
+a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
--- a/hotspot/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -489,3 +489,4 @@
 184c4328444974edd6b3b490b9d0177ace7e331c jdk9-b84
 03845376ea9dbf9690b6a9cfb4ed63f8cc0541c0 jdk9-b85
 1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
+d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
--- a/jaxp/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -329,3 +329,4 @@
 91795d86744f3074d1e59b1e75d9c851c098688f jdk9-b84
 1d9850c1b35c74e8b5c17970ed5d46dc0fc33f06 jdk9-b85
 88d9b1f6b73e0c46fcb5ccabe1231a30ce758a22 jdk9-b86
+eb435c878c2cbbfb043d0b205f4d5bd6faffd44a jdk9-b87
--- a/jaxws/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -332,3 +332,4 @@
 51729143f8fe038f52cf55720c4c1f89267f5948 jdk9-b84
 67b626ec730d2601d95ef036d06be34b37fa9ce6 jdk9-b85
 5289646179079394890a34a898a8ab70fcde0331 jdk9-b86
+f7dba191a38cfc29665b0d77174615a530803297 jdk9-b87
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java	Wed Jul 05 20:54:58 2017 +0200
@@ -30,6 +30,7 @@
 import com.sun.xml.internal.bind.util.Which;
 
 import javax.lang.model.SourceVersion;
+import javax.tools.Diagnostic;
 import javax.tools.DiagnosticCollector;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
@@ -248,7 +249,12 @@
             if (episode != null)
                 r.setEpisodeFile(episode);
             task.setProcessors(Collections.singleton(r));
-            return task.call();
+            boolean res = task.call();
+            //Print messages generated by compiler
+            for (Diagnostic<? extends JavaFileObject> d : diagnostics.getDiagnostics()) {
+                 System.err.println(d.toString());
+            }
+            return res;
         }
     }
 
--- a/jdk/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -329,3 +329,4 @@
 757ef7f6d0042934edea3e0bf616fad2c1a22789 jdk9-b84
 fe40b31c0e526d357cf5b62044fea006e43b53a5 jdk9-b85
 e8a66c0b05d786a282a7ff1d7eb4989afa30c891 jdk9-b86
+110fc90bdfa0fe59606c047c2301ed75d2bad6cf jdk9-b87
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 20:54:58 2017 +0200
@@ -152,7 +152,6 @@
 		Java_java_lang_StrictMath_log10;
 		Java_java_lang_StrictMath_sin;
 		Java_java_lang_StrictMath_sqrt;
-		Java_java_lang_StrictMath_cbrt;
 		Java_java_lang_StrictMath_tan;
 		Java_java_lang_StrictMath_cosh;
 		Java_java_lang_StrictMath_sinh;
--- a/jdk/src/java.base/share/classes/java/lang/FdLibm.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/FdLibm.java	Wed Jul 05 20:54:58 2017 +0200
@@ -100,6 +100,64 @@
     }
 
     /**
+     * cbrt(x)
+     * Return cube root of x
+     */
+    public static class Cbrt {
+        // unsigned
+        private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+        private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+        private static final double C =  0x1.15f15f15f15f1p-1; //   19/35   ~= 5.42857142857142815906e-01
+        private static final double D = -0x1.691de2532c834p-1; // -864/1225 ~= 7.05306122448979611050e-01
+        private static final double E =  0x1.6a0ea0ea0ea0fp0;  //   99/70   ~= 1.41428571428571436819e+00
+        private static final double F =  0x1.9b6db6db6db6ep0;  //   45/28   ~= 1.60714285714285720630e+00
+        private static final double G =  0x1.6db6db6db6db7p-2; //    5/14   ~= 3.57142857142857150787e-01
+
+        public static strictfp double compute(double x) {
+            double  t = 0.0;
+            double sign;
+
+            if (x == 0.0 || !Double.isFinite(x))
+                return x; // Handles signed zeros properly
+
+            sign = (x < 0.0) ? -1.0:  1.0;
+
+            x = Math.abs(x);   // x <- |x|
+
+            // Rough cbrt to 5 bits
+            if (x < 0x1.0p-1022) {     // subnormal number
+                t = 0x1.0p54;          // set t= 2**54
+                t *= x;
+                t = __HI(t, __HI(t)/3 + B2);
+            } else {
+                int hx = __HI(x);           // high word of x
+                t = __HI(t, hx/3 + B1);
+            }
+
+            // New cbrt to 23 bits, may be implemented in single precision
+            double  r, s, w;
+            r = t * t/x;
+            s = C + r*t;
+            t *= G + F/(s + E + D/s);
+
+            // Chopped to 20 bits and make it larger than cbrt(x)
+            t = __LO(t, 0);
+            t = __HI(t, __HI(t) + 0x00000001);
+
+            // One step newton iteration to 53 bits with error less than 0.667 ulps
+            s = t * t;          // t*t is exact
+            r = x / s;
+            w = t + t;
+            r = (r - t)/(w + r);  // r-s is exact
+            t = t + t*r;
+
+            // Restore the original sign bit
+            return sign * t;
+        }
+    }
+
+    /**
      * hypot(x,y)
      *
      * Method :
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Wed Jul 05 20:54:58 2017 +0200
@@ -307,7 +307,9 @@
      * @return  the cube root of {@code a}.
      * @since 1.5
      */
-    public static native double cbrt(double a);
+    public static double cbrt(double a) {
+        return FdLibm.Cbrt.compute(a);
+    }
 
     /**
      * Computes the remainder operation on two arguments as prescribed
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -834,7 +834,7 @@
 
         static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
             try {
-                return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null));
+                return LOOKUP.findStatic(cbmh, "make", MethodType.fromDescriptor(makeSignature(types, false), null));
             } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
                 throw newInternalError(e);
             }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -141,7 +141,7 @@
         synchronized (this) {
             if (type instanceof String) {
                 String sig = (String) type;
-                MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
+                MethodType res = MethodType.fromDescriptor(sig, getClassLoader());
                 type = res;
             } else if (type instanceof Object[]) {
                 Object[] typeInfo = (Object[]) type;
@@ -206,7 +206,7 @@
         synchronized (this) {
             if (type instanceof String) {
                 String sig = (String) type;
-                MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
+                MethodType mtype = MethodType.fromDescriptor("()"+sig, getClassLoader());
                 Class<?> res = mtype.returnType();
                 type = res;
             }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Wed Jul 05 20:54:58 2017 +0200
@@ -383,7 +383,7 @@
         if (type instanceof MethodType)
             return (MethodType) type;
         else
-            return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
+            return MethodType.fromDescriptor((String)type, callerClass.getClassLoader());
     }
     // Tracing logic:
     static MemberName linkMethodTracing(Class<?> callerClass, int refKind,
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -1058,6 +1058,23 @@
     public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
         throws IllegalArgumentException, TypeNotPresentException
     {
+        return fromDescriptor(descriptor,
+                              (loader == null) ? ClassLoader.getSystemClassLoader() : loader);
+    }
+
+    /**
+     * Same as {@link #fromMethodDescriptorString(String, ClassLoader)}, but
+     * {@code null} ClassLoader means the bootstrap loader is used here.
+     * <p>
+     * IMPORTANT: This method is preferable for JDK internal use as it more
+     * correctly interprets {@code null} ClassLoader than
+     * {@link #fromMethodDescriptorString(String, ClassLoader)}.
+     * Use of this method also avoids early initialization issues when system
+     * ClassLoader is not initialized yet.
+     */
+    static MethodType fromDescriptor(String descriptor, ClassLoader loader)
+        throws IllegalArgumentException, TypeNotPresentException
+    {
         if (!descriptor.startsWith("(") ||  // also generates NPE if needed
             descriptor.indexOf(')') < 0 ||
             descriptor.indexOf('.') >= 0)
--- a/jdk/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -131,7 +131,7 @@
     }
 
     private static String boxingDescriptor(Wrapper w) {
-        return String.format("(%s)L%s;", w.basicTypeChar(), wrapperName(w));
+        return "(" + w.basicTypeChar() + ")L" + wrapperName(w) + ";";
     }
 
     private static String unboxingDescriptor(Wrapper w) {
--- a/jdk/src/java.base/share/classes/java/net/URLStreamHandlerFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/URLStreamHandlerFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -28,9 +28,9 @@
 /**
  * This interface defines a factory for {@code URL} stream
  * protocol handlers.
- * <p>
- * It is used by the {@code URL} class to create a
- * {@code URLStreamHandler} for a specific protocol.
+ *
+ * <p> A URL stream handler factory is used as specified in the
+ * {@linkplain java.net.URL#URL(String,String,int,String) URL constructor}.
  *
  * @author  Arthur van Hoff
  * @see     java.net.URL
--- a/jdk/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/spi/URLStreamHandlerProvider.java	Wed Jul 05 20:54:58 2017 +0200
@@ -41,6 +41,9 @@
  * fully-qualified concrete URL stream handler provider class names, one per
  * line.
  *
+ * <p> URL stream handler providers are located at runtime, as specified in the
+ * {@linkplain java.net.URL#URL(String,String,int,String) URL constructor}.
+ *
  * @since 1.9
  */
 public abstract class URLStreamHandlerProvider
--- a/jdk/src/java.base/share/classes/java/util/AbstractQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/AbstractQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -38,16 +38,16 @@
 /**
  * This class provides skeletal implementations of some {@link Queue}
  * operations. The implementations in this class are appropriate when
- * the base implementation does <em>not</em> allow <tt>null</tt>
+ * the base implementation does <em>not</em> allow {@code null}
  * elements.  Methods {@link #add add}, {@link #remove remove}, and
  * {@link #element element} are based on {@link #offer offer}, {@link
  * #poll poll}, and {@link #peek peek}, respectively, but throw
- * exceptions instead of indicating failure via <tt>false</tt> or
- * <tt>null</tt> returns.
+ * exceptions instead of indicating failure via {@code false} or
+ * {@code null} returns.
  *
- * <p>A <tt>Queue</tt> implementation that extends this class must
+ * <p>A {@code Queue} implementation that extends this class must
  * minimally define a method {@link Queue#offer} which does not permit
- * insertion of <tt>null</tt> elements, along with methods {@link
+ * insertion of {@code null} elements, along with methods {@link
  * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and
  * {@link Collection#iterator}.  Typically, additional methods will be
  * overridden as well.  If these requirements cannot be met, consider
@@ -59,7 +59,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public abstract class AbstractQueue<E>
     extends AbstractCollection<E>
@@ -74,14 +74,14 @@
     /**
      * Inserts the specified element into this queue if it is possible to do so
      * immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
+     * {@code true} upon success and throwing an {@code IllegalStateException}
      * if no space is currently available.
      *
-     * <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds,
-     * else throws an <tt>IllegalStateException</tt>.
+     * <p>This implementation returns {@code true} if {@code offer} succeeds,
+     * else throws an {@code IllegalStateException}.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws IllegalStateException if the element cannot be added at this
      *         time due to capacity restrictions
      * @throws ClassCastException if the class of the specified element
@@ -103,7 +103,7 @@
      * from {@link #poll poll} only in that it throws an exception if this
      * queue is empty.
      *
-     * <p>This implementation returns the result of <tt>poll</tt>
+     * <p>This implementation returns the result of {@code poll}
      * unless the queue is empty.
      *
      * @return the head of this queue
@@ -122,7 +122,7 @@
      * differs from {@link #peek peek} only in that it throws an exception if
      * this queue is empty.
      *
-     * <p>This implementation returns the result of <tt>peek</tt>
+     * <p>This implementation returns the result of {@code peek}
      * unless the queue is empty.
      *
      * @return the head of this queue
@@ -141,7 +141,7 @@
      * The queue will be empty after this call returns.
      *
      * <p>This implementation repeatedly invokes {@link #poll poll} until it
-     * returns <tt>null</tt>.
+     * returns {@code null}.
      */
     public void clear() {
         while (poll() != null)
@@ -151,7 +151,7 @@
     /**
      * Adds all of the elements in the specified collection to this
      * queue.  Attempts to addAll of a queue to itself result in
-     * <tt>IllegalArgumentException</tt>. Further, the behavior of
+     * {@code IllegalArgumentException}. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
@@ -159,12 +159,12 @@
      * and adds each element returned by the iterator to this
      * queue, in turn.  A runtime exception encountered while
      * trying to add an element (including, in particular, a
-     * <tt>null</tt> element) may result in only some of the elements
+     * {@code null} element) may result in only some of the elements
      * having been successfully added when the associated exception is
      * thrown.
      *
      * @param c collection containing elements to be added to this queue
-     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @return {@code true} if this queue changed as a result of the call
      * @throws ClassCastException if the class of an element of the specified
      *         collection prevents it from being added to this queue
      * @throws NullPointerException if the specified collection contains a
--- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java	Wed Jul 05 20:54:58 2017 +0200
@@ -47,16 +47,18 @@
  * when used as a queue.
  *
  * <p>Most {@code ArrayDeque} operations run in amortized constant time.
- * Exceptions include {@link #remove(Object) remove}, {@link
- * #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
- * removeLastOccurrence}, {@link #contains contains}, {@link #iterator
- * iterator.remove()}, and the bulk operations, all of which run in linear
- * time.
+ * Exceptions include
+ * {@link #remove(Object) remove},
+ * {@link #removeFirstOccurrence removeFirstOccurrence},
+ * {@link #removeLastOccurrence removeLastOccurrence},
+ * {@link #contains contains},
+ * {@link #iterator iterator.remove()},
+ * and the bulk operations, all of which run in linear time.
  *
- * <p>The iterators returned by this class's {@code iterator} method are
- * <i>fail-fast</i>: If the deque is modified at any time after the iterator
- * is created, in any way except through the iterator's own {@code remove}
- * method, the iterator will generally throw a {@link
+ * <p>The iterators returned by this class's {@link #iterator() iterator}
+ * method are <em>fail-fast</em>: If the deque is modified at any time after
+ * the iterator is created, in any way except through the iterator's own
+ * {@code remove} method, the iterator will generally throw a {@link
  * ConcurrentModificationException}.  Thus, in the face of concurrent
  * modification, the iterator fails quickly and cleanly, rather than risking
  * arbitrary, non-deterministic behavior at an undetermined time in the
@@ -80,7 +82,7 @@
  *
  * @author  Josh Bloch and Doug Lea
  * @since   1.6
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
  */
 public class ArrayDeque<E> extends AbstractCollection<E>
                            implements Deque<E>, Cloneable, Serializable
@@ -136,8 +138,8 @@
             initialCapacity |= (initialCapacity >>> 16);
             initialCapacity++;
 
-            if (initialCapacity < 0)   // Too many elements, must back off
-                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
+            if (initialCapacity < 0)    // Too many elements, must back off
+                initialCapacity >>>= 1; // Good luck allocating 2^30 elements
         }
         elements = new Object[initialCapacity];
     }
@@ -163,24 +165,6 @@
     }
 
     /**
-     * Copies the elements from our element array into the specified array,
-     * in order (from first to last element in the deque).  It is assumed
-     * that the array is large enough to hold all elements in the deque.
-     *
-     * @return its argument
-     */
-    private <T> T[] copyElements(T[] a) {
-        if (head < tail) {
-            System.arraycopy(elements, head, a, 0, size());
-        } else if (head > tail) {
-            int headPortionLen = elements.length - head;
-            System.arraycopy(elements, head, a, 0, headPortionLen);
-            System.arraycopy(elements, 0, a, headPortionLen, tail);
-        }
-        return a;
-    }
-
-    /**
      * Constructs an empty array deque with an initial capacity
      * sufficient to hold 16 elements.
      */
@@ -292,25 +276,27 @@
     }
 
     public E pollFirst() {
-        int h = head;
+        final Object[] elements = this.elements;
+        final int h = head;
         @SuppressWarnings("unchecked")
         E result = (E) elements[h];
         // Element is null if deque empty
-        if (result == null)
-            return null;
-        elements[h] = null;     // Must null out slot
-        head = (h + 1) & (elements.length - 1);
+        if (result != null) {
+            elements[h] = null; // Must null out slot
+            head = (h + 1) & (elements.length - 1);
+        }
         return result;
     }
 
     public E pollLast() {
-        int t = (tail - 1) & (elements.length - 1);
+        final Object[] elements = this.elements;
+        final int t = (tail - 1) & (elements.length - 1);
         @SuppressWarnings("unchecked")
         E result = (E) elements[t];
-        if (result == null)
-            return null;
-        elements[t] = null;
-        tail = t;
+        if (result != null) {
+            elements[t] = null;
+            tail = t;
+        }
         return result;
     }
 
@@ -360,17 +346,15 @@
      * @return {@code true} if the deque contained the specified element
      */
     public boolean removeFirstOccurrence(Object o) {
-        if (o == null)
-            return false;
-        int mask = elements.length - 1;
-        int i = head;
-        Object x;
-        while ( (x = elements[i]) != null) {
-            if (o.equals(x)) {
-                delete(i);
-                return true;
+        if (o != null) {
+            int mask = elements.length - 1;
+            int i = head;
+            for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
+                if (o.equals(x)) {
+                    delete(i);
+                    return true;
+                }
             }
-            i = (i + 1) & mask;
         }
         return false;
     }
@@ -388,17 +372,15 @@
      * @return {@code true} if the deque contained the specified element
      */
     public boolean removeLastOccurrence(Object o) {
-        if (o == null)
-            return false;
-        int mask = elements.length - 1;
-        int i = (tail - 1) & mask;
-        Object x;
-        while ( (x = elements[i]) != null) {
-            if (o.equals(x)) {
-                delete(i);
-                return true;
+        if (o != null) {
+            int mask = elements.length - 1;
+            int i = (tail - 1) & mask;
+            for (Object x; (x = elements[i]) != null; i = (i - 1) & mask) {
+                if (o.equals(x)) {
+                    delete(i);
+                    return true;
+                }
             }
-            i = (i - 1) & mask;
         }
         return false;
     }
@@ -535,7 +517,7 @@
      *
      * @return true if elements moved backwards
      */
-    private boolean delete(int i) {
+    boolean delete(int i) {
         checkInvariants();
         final Object[] elements = this.elements;
         final int mask = elements.length - 1;
@@ -671,12 +653,12 @@
         }
     }
 
+    /**
+     * This class is nearly a mirror-image of DeqIterator, using tail
+     * instead of head for initial cursor, and head instead of tail
+     * for fence.
+     */
     private class DescendingIterator implements Iterator<E> {
-        /*
-         * This class is nearly a mirror-image of DeqIterator, using
-         * tail instead of head for initial cursor, and head instead of
-         * tail for fence.
-         */
         private int cursor = tail;
         private int fence = head;
         private int lastRet = -1;
@@ -717,15 +699,13 @@
      * @return {@code true} if this deque contains the specified element
      */
     public boolean contains(Object o) {
-        if (o == null)
-            return false;
-        int mask = elements.length - 1;
-        int i = head;
-        Object x;
-        while ( (x = elements[i]) != null) {
-            if (o.equals(x))
-                return true;
-            i = (i + 1) & mask;
+        if (o != null) {
+            int mask = elements.length - 1;
+            int i = head;
+            for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
+                if (o.equals(x))
+                    return true;
+            }
         }
         return false;
     }
@@ -779,7 +759,14 @@
      * @return an array containing all of the elements in this deque
      */
     public Object[] toArray() {
-        return copyElements(new Object[size()]);
+        final int head = this.head;
+        final int tail = this.tail;
+        boolean wrap = (tail < head);
+        int end = wrap ? tail + elements.length : tail;
+        Object[] a = Arrays.copyOfRange(elements, head, end);
+        if (wrap)
+            System.arraycopy(elements, 0, a, elements.length - head, tail);
+        return a;
     }
 
     /**
@@ -804,7 +791,7 @@
      * The following code can be used to dump the deque into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -820,13 +807,22 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        int size = size();
-        if (a.length < size)
-            a = (T[])java.lang.reflect.Array.newInstance(
-                    a.getClass().getComponentType(), size);
-        copyElements(a);
-        if (a.length > size)
-            a[size] = null;
+        final int head = this.head;
+        final int tail = this.tail;
+        boolean wrap = (tail < head);
+        int size = (tail - head) + (wrap ? elements.length : 0);
+        int firstLeg = size - (wrap ? tail : 0);
+        int len = a.length;
+        if (size > len) {
+            a = (T[]) Arrays.copyOfRange(elements, head, head + size,
+                                         a.getClass());
+        } else {
+            System.arraycopy(elements, head, a, 0, firstLeg);
+            if (size < len)
+                a[size] = null;
+        }
+        if (wrap)
+            System.arraycopy(elements, 0, a, firstLeg, tail);
         return a;
     }
 
@@ -853,6 +849,8 @@
     /**
      * Saves this deque to a stream (that is, serializes it).
      *
+     * @param s the stream
+     * @throws java.io.IOException if an I/O error occurs
      * @serialData The current size ({@code int}) of the deque,
      * followed by all of its elements (each an object reference) in
      * first-to-last order.
@@ -872,6 +870,10 @@
 
     /**
      * Reconstitutes this deque from a stream (that is, deserializes it).
+     * @param s the stream
+     * @throws ClassNotFoundException if the class of a serialized object
+     *         could not be found
+     * @throws java.io.IOException if an I/O error occurs
      */
     private void readObject(java.io.ObjectInputStream s)
             throws java.io.IOException, ClassNotFoundException {
@@ -910,7 +912,7 @@
         private int fence;  // -1 until first use
         private int index;  // current index, modified on traverse/split
 
-        /** Creates new spliterator covering the given array and range */
+        /** Creates new spliterator covering the given array and range. */
         DeqSpliterator(ArrayDeque<E> deq, int origin, int fence) {
             this.deq = deq;
             this.index = origin;
@@ -932,7 +934,7 @@
                 if (h > t)
                     t += n;
                 int m = ((h + t) >>> 1) & (n - 1);
-                return new DeqSpliterator<>(deq, h, index = m);
+                return new DeqSpliterator<E>(deq, h, index = m);
             }
             return null;
         }
@@ -957,7 +959,7 @@
                 throw new NullPointerException();
             Object[] a = deq.elements;
             int m = a.length - 1, f = getFence(), i = index;
-            if (i != fence) {
+            if (i != f) {
                 @SuppressWarnings("unchecked") E e = (E)a[i];
                 index = (i + 1) & m;
                 if (e == null)
--- a/jdk/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -22,20 +21,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package java.util;
 
 /*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
  * Written by Doug Lea with assistance from members of JCP JSR-166
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-import java.util.concurrent.ForkJoinPool;
+package java.util;
+
 import java.util.concurrent.CountedCompleter;
+import java.util.concurrent.ForkJoinPool;
 import java.util.function.BinaryOperator;
+import java.util.function.DoubleBinaryOperator;
 import java.util.function.IntBinaryOperator;
 import java.util.function.LongBinaryOperator;
-import java.util.function.DoubleBinaryOperator;
 
 /**
  * ForkJoin tasks to perform Arrays.parallelPrefix operations.
@@ -44,7 +49,7 @@
  * @since 1.8
  */
 class ArrayPrefixHelpers {
-    private ArrayPrefixHelpers() {}; // non-instantiable
+    private ArrayPrefixHelpers() {} // non-instantiable
 
     /*
      * Parallel prefix (aka cumulate, scan) task classes
@@ -113,8 +118,8 @@
             this.lo = this.origin = lo; this.hi = this.fence = hi;
             int p;
             this.threshold =
-                    (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
-                    <= MIN_PARTITION ? MIN_PARTITION : p;
+                (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+                <= MIN_PARTITION ? MIN_PARTITION : p;
         }
 
         /** Subtask constructor */
@@ -141,9 +146,9 @@
                     if (lt == null) {                // first pass
                         int mid = (l + h) >>> 1;
                         f = rt = t.right =
-                                new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
-                        t = lt = t.left  =
-                                new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
+                            new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
+                        t = lt = t.left =
+                            new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
                     }
                     else {                           // possibly refork
                         T pin = t.in;
@@ -183,7 +188,7 @@
                     for (int b;;) {
                         if (((b = t.getPendingCount()) & FINISHED) != 0)
                             break outer;                      // already done
-                        state = ((b & CUMULATE) != 0? FINISHED :
+                        state = ((b & CUMULATE) != 0 ? FINISHED :
                                  (l > org) ? SUMMED : (SUMMED|FINISHED));
                         if (t.compareAndSetPendingCount(b, b|state))
                             break;
@@ -265,8 +270,8 @@
             this.lo = this.origin = lo; this.hi = this.fence = hi;
             int p;
             this.threshold =
-                    (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
-                    <= MIN_PARTITION ? MIN_PARTITION : p;
+                (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+                <= MIN_PARTITION ? MIN_PARTITION : p;
         }
 
         /** Subtask constructor */
@@ -293,9 +298,9 @@
                     if (lt == null) {                // first pass
                         int mid = (l + h) >>> 1;
                         f = rt = t.right =
-                                new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
-                        t = lt = t.left  =
-                                new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
+                            new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
+                        t = lt = t.left =
+                            new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
                     }
                     else {                           // possibly refork
                         long pin = t.in;
@@ -335,7 +340,7 @@
                     for (int b;;) {
                         if (((b = t.getPendingCount()) & FINISHED) != 0)
                             break outer;                      // already done
-                        state = ((b & CUMULATE) != 0? FINISHED :
+                        state = ((b & CUMULATE) != 0 ? FINISHED :
                                  (l > org) ? SUMMED : (SUMMED|FINISHED));
                         if (t.compareAndSetPendingCount(b, b|state))
                             break;
@@ -415,8 +420,8 @@
             this.lo = this.origin = lo; this.hi = this.fence = hi;
             int p;
             this.threshold =
-                    (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
-                    <= MIN_PARTITION ? MIN_PARTITION : p;
+                (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+                <= MIN_PARTITION ? MIN_PARTITION : p;
         }
 
         /** Subtask constructor */
@@ -443,9 +448,9 @@
                     if (lt == null) {                // first pass
                         int mid = (l + h) >>> 1;
                         f = rt = t.right =
-                                new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
-                        t = lt = t.left  =
-                                new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
+                            new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
+                        t = lt = t.left =
+                            new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
                     }
                     else {                           // possibly refork
                         double pin = t.in;
@@ -485,7 +490,7 @@
                     for (int b;;) {
                         if (((b = t.getPendingCount()) & FINISHED) != 0)
                             break outer;                      // already done
-                        state = ((b & CUMULATE) != 0? FINISHED :
+                        state = ((b & CUMULATE) != 0 ? FINISHED :
                                  (l > org) ? SUMMED : (SUMMED|FINISHED));
                         if (t.compareAndSetPendingCount(b, b|state))
                             break;
@@ -565,8 +570,8 @@
             this.lo = this.origin = lo; this.hi = this.fence = hi;
             int p;
             this.threshold =
-                    (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
-                    <= MIN_PARTITION ? MIN_PARTITION : p;
+                (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+                <= MIN_PARTITION ? MIN_PARTITION : p;
         }
 
         /** Subtask constructor */
@@ -593,9 +598,9 @@
                     if (lt == null) {                // first pass
                         int mid = (l + h) >>> 1;
                         f = rt = t.right =
-                                new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
-                        t = lt = t.left  =
-                                new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
+                            new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
+                        t = lt = t.left =
+                            new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
                     }
                     else {                           // possibly refork
                         int pin = t.in;
@@ -635,7 +640,7 @@
                     for (int b;;) {
                         if (((b = t.getPendingCount()) & FINISHED) != 0)
                             break outer;                      // already done
-                        state = ((b & CUMULATE) != 0? FINISHED :
+                        state = ((b & CUMULATE) != 0 ? FINISHED :
                                  (l > org) ? SUMMED : (SUMMED|FINISHED));
                         if (t.compareAndSetPendingCount(b, b|state))
                             break;
--- a/jdk/src/java.base/share/classes/java/util/Collections.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java	Wed Jul 05 20:54:58 2017 +0200
@@ -537,8 +537,9 @@
      * Copies all of the elements from one list into another.  After the
      * operation, the index of each copied element in the destination list
      * will be identical to its index in the source list.  The destination
-     * list must be at least as long as the source list.  If it is longer, the
-     * remaining elements in the destination list are unaffected. <p>
+     * list's size must be greater than or equal to the source list's size.
+     * If it is greater, the remaining elements in the destination list are
+     * unaffected. <p>
      *
      * This method runs in linear time.
      *
--- a/jdk/src/java.base/share/classes/java/util/Deque.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Deque.java	Wed Jul 05 20:54:58 2017 +0200
@@ -188,7 +188,7 @@
  * @author Doug Lea
  * @author Josh Bloch
  * @since  1.6
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
  */
 public interface Deque<E> extends Queue<E> {
     /**
@@ -344,8 +344,7 @@
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
      * More formally, removes the first element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
-     * (if such an element exists).
+     * {@code Objects.equals(o, e)} (if such an element exists).
      * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
@@ -353,10 +352,10 @@
      * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null and this
      *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeFirstOccurrence(Object o);
 
@@ -364,8 +363,7 @@
      * Removes the last occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
      * More formally, removes the last element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
-     * (if such an element exists).
+     * {@code Objects.equals(o, e)} (if such an element exists).
      * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
@@ -373,10 +371,10 @@
      * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null and this
      *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeLastOccurrence(Object o);
 
@@ -521,8 +519,7 @@
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
      * More formally, removes the first element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
-     * (if such an element exists).
+     * {@code Objects.equals(o, e)} (if such an element exists).
      * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
@@ -532,27 +529,26 @@
      * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null and this
      *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
     /**
      * Returns {@code true} if this deque contains the specified element.
      * More formally, returns {@code true} if and only if this deque contains
-     * at least one element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     * at least one element {@code e} such that {@code Objects.equals(o, e)}.
      *
      * @param o element whose presence in this deque is to be tested
      * @return {@code true} if this deque contains the specified element
-     * @throws ClassCastException if the type of the specified element
+     * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null and this
      *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean contains(Object o);
 
@@ -561,7 +557,7 @@
      *
      * @return the number of elements in this deque
      */
-    public int size();
+    int size();
 
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
--- a/jdk/src/java.base/share/classes/java/util/NavigableMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/NavigableMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -38,30 +38,32 @@
 /**
  * A {@link SortedMap} extended with navigation methods returning the
  * closest matches for given search targets. Methods
- * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
- * and {@code higherEntry} return {@code Map.Entry} objects
+ * {@link #lowerEntry}, {@link #floorEntry}, {@link #ceilingEntry},
+ * and {@link #higherEntry} return {@code Map.Entry} objects
  * associated with keys respectively less than, less than or equal,
  * greater than or equal, and greater than a given key, returning
  * {@code null} if there is no such key.  Similarly, methods
- * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
- * {@code higherKey} return only the associated keys. All of these
+ * {@link #lowerKey}, {@link #floorKey}, {@link #ceilingKey}, and
+ * {@link #higherKey} return only the associated keys. All of these
  * methods are designed for locating, not traversing entries.
  *
  * <p>A {@code NavigableMap} may be accessed and traversed in either
- * ascending or descending key order.  The {@code descendingMap}
+ * ascending or descending key order.  The {@link #descendingMap}
  * method returns a view of the map with the senses of all relational
  * and directional methods inverted. The performance of ascending
  * operations and views is likely to be faster than that of descending
- * ones.  Methods {@code subMap}, {@code headMap},
- * and {@code tailMap} differ from the like-named {@code
- * SortedMap} methods in accepting additional arguments describing
- * whether lower and upper bounds are inclusive versus exclusive.
- * Submaps of any {@code NavigableMap} must implement the {@code
- * NavigableMap} interface.
+ * ones.  Methods
+ * {@link #subMap(Object, boolean, Object, boolean) subMap(K, boolean, K, boolean)},
+ * {@link #headMap(Object, boolean) headMap(K, boolean)}, and
+ * {@link #tailMap(Object, boolean) tailMap(K, boolean)}
+ * differ from the like-named {@code SortedMap} methods in accepting
+ * additional arguments describing whether lower and upper bounds are
+ * inclusive versus exclusive.  Submaps of any {@code NavigableMap}
+ * must implement the {@code NavigableMap} interface.
  *
- * <p>This interface additionally defines methods {@code firstEntry},
- * {@code pollFirstEntry}, {@code lastEntry}, and
- * {@code pollLastEntry} that return and/or remove the least and
+ * <p>This interface additionally defines methods {@link #firstEntry},
+ * {@link #pollFirstEntry}, {@link #lastEntry}, and
+ * {@link #pollLastEntry} that return and/or remove the least and
  * greatest mappings, if any exist, else returning {@code null}.
  *
  * <p>Implementations of entry-returning methods are expected to
@@ -80,7 +82,7 @@
  * implement {@code NavigableMap}, but extensions and implementations
  * of this interface are encouraged to override these methods to return
  * {@code NavigableMap}.  Similarly,
- * {@link #keySet()} can be overriden to return {@code NavigableSet}.
+ * {@link #keySet()} can be overridden to return {@link NavigableSet}.
  *
  * <p>This interface is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -254,7 +256,7 @@
      * operation), the results of the iteration are undefined.
      *
      * <p>The returned map has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code m.descendingMap().descendingMap()} returns a
      * view of {@code m} essentially equivalent to {@code m}.
      *
--- a/jdk/src/java.base/share/classes/java/util/NavigableSet.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/NavigableSet.java	Wed Jul 05 20:54:58 2017 +0200
@@ -37,26 +37,30 @@
 
 /**
  * A {@link SortedSet} extended with navigation methods reporting
- * closest matches for given search targets. Methods {@code lower},
- * {@code floor}, {@code ceiling}, and {@code higher} return elements
+ * closest matches for given search targets. Methods {@link #lower},
+ * {@link #floor}, {@link #ceiling}, and {@link #higher} return elements
  * respectively less than, less than or equal, greater than or equal,
  * and greater than a given element, returning {@code null} if there
- * is no such element.  A {@code NavigableSet} may be accessed and
- * traversed in either ascending or descending order.  The {@code
- * descendingSet} method returns a view of the set with the senses of
- * all relational and directional methods inverted. The performance of
- * ascending operations and views is likely to be faster than that of
- * descending ones.  This interface additionally defines methods
- * {@code pollFirst} and {@code pollLast} that return and remove the
- * lowest and highest element, if one exists, else returning {@code
- * null}.  Methods {@code subSet}, {@code headSet},
- * and {@code tailSet} differ from the like-named {@code
- * SortedSet} methods in accepting additional arguments describing
- * whether lower and upper bounds are inclusive versus exclusive.
- * Subsets of any {@code NavigableSet} must implement the {@code
- * NavigableSet} interface.
+ * is no such element.
  *
- * <p> The return values of navigation methods may be ambiguous in
+ * <p>A {@code NavigableSet} may be accessed and traversed in either
+ * ascending or descending order.  The {@link #descendingSet} method
+ * returns a view of the set with the senses of all relational and
+ * directional methods inverted. The performance of ascending
+ * operations and views is likely to be faster than that of descending
+ * ones.  This interface additionally defines methods {@link
+ * #pollFirst} and {@link #pollLast} that return and remove the lowest
+ * and highest element, if one exists, else returning {@code null}.
+ * Methods
+ * {@link #subSet(Object, boolean, Object, boolean) subSet(E, boolean, E, boolean)},
+ * {@link #headSet(Object, boolean) headSet(E, boolean)}, and
+ * {@link #tailSet(Object, boolean) tailSet(E, boolean)}
+ * differ from the like-named {@code SortedSet} methods in accepting
+ * additional arguments describing whether lower and upper bounds are
+ * inclusive versus exclusive.  Subsets of any {@code NavigableSet}
+ * must implement the {@code NavigableSet} interface.
+ *
+ * <p>The return values of navigation methods may be ambiguous in
  * implementations that permit {@code null} elements. However, even
  * in this case the result can be disambiguated by checking
  * {@code contains(null)}. To avoid such issues, implementations of
@@ -172,7 +176,7 @@
      * the iteration are undefined.
      *
      * <p>The returned set has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code s.descendingSet().descendingSet()} returns a
      * view of {@code s} essentially equivalent to {@code s}.
      *
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -77,7 +77,7 @@
  *
  * @since 1.5
  * @author Josh Bloch, Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class PriorityQueue<E> extends AbstractQueue<E>
     implements java.io.Serializable {
@@ -99,7 +99,7 @@
     /**
      * The number of elements in the priority queue.
      */
-    private int size = 0;
+    int size;
 
     /**
      * The comparator, or null if priority queue uses elements'
@@ -111,7 +111,7 @@
      * The number of times this priority queue has been
      * <i>structurally modified</i>.  See AbstractList for gory details.
      */
-    transient int modCount = 0; // non-private to simplify nested class access
+    transient int modCount;     // non-private to simplify nested class access
 
     /**
      * Creates a {@code PriorityQueue} with the default initial
@@ -448,7 +448,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -489,7 +489,7 @@
          * Index (into queue array) of element to be returned by
          * subsequent call to next.
          */
-        private int cursor = 0;
+        private int cursor;
 
         /**
          * Index of element returned by most recent call to next,
@@ -509,13 +509,13 @@
          * We expect that most iterations, even those involving removals,
          * will not need to store elements in this field.
          */
-        private ArrayDeque<E> forgetMeNot = null;
+        private ArrayDeque<E> forgetMeNot;
 
         /**
          * Element returned by the most recent call to next iff that
          * element was drawn from the forgetMeNot list.
          */
-        private E lastRetElt = null;
+        private E lastRetElt;
 
         /**
          * The modCount value that the iterator believes that the backing
@@ -609,7 +609,7 @@
      * avoid missing traversing elements.
      */
     @SuppressWarnings("unchecked")
-    private E removeAt(int i) {
+    E removeAt(int i) {
         // assert i >= 0 && i < size;
         modCount++;
         int s = --size;
@@ -756,6 +756,7 @@
      *             emitted (int), followed by all of its elements
      *             (each an {@code Object}) in the proper order.
      * @param s the stream
+     * @throws java.io.IOException if an I/O error occurs
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -775,6 +776,9 @@
      * (that is, deserializes it).
      *
      * @param s the stream
+     * @throws ClassNotFoundException if the class of a serialized object
+     *         could not be found
+     * @throws java.io.IOException if an I/O error occurs
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
@@ -822,9 +826,9 @@
         private int fence;            // -1 until first use
         private int expectedModCount; // initialized when fence set
 
-        /** Creates new spliterator covering the given range */
+        /** Creates new spliterator covering the given range. */
         PriorityQueueSpliterator(PriorityQueue<E> pq, int origin, int fence,
-                             int expectedModCount) {
+                                 int expectedModCount) {
             this.pq = pq;
             this.index = origin;
             this.fence = fence;
--- a/jdk/src/java.base/share/classes/java/util/Queue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Queue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -139,7 +139,7 @@
  * @see java.util.concurrent.PriorityBlockingQueue
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public interface Queue<E> extends Collection<E> {
     /**
--- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java	Wed Jul 05 20:54:58 2017 +0200
@@ -26,13 +26,13 @@
 package java.util;
 
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
 import java.util.function.LongConsumer;
-import java.util.function.DoubleConsumer;
-import java.util.stream.StreamSupport;
+import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
-import java.util.stream.DoubleStream;
+import java.util.stream.StreamSupport;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
@@ -52,15 +52,15 @@
  * types and ranges, but similar properties are expected to hold, at
  * least approximately, for others as well. The <em>period</em>
  * (length of any series of generated values before it repeats) is at
- * least 2<sup>64</sup>. </li>
+ * least 2<sup>64</sup>.
  *
- * <li> Method {@link #split} constructs and returns a new
+ * <li>Method {@link #split} constructs and returns a new
  * SplittableRandom instance that shares no mutable state with the
  * current instance. However, with very high probability, the
  * values collectively generated by the two objects have the same
  * statistical properties as if the same quantity of values were
  * generated by a single thread using a single {@code
- * SplittableRandom} object.  </li>
+ * SplittableRandom} object.
  *
  * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
  * They are designed to be split, not shared, across threads. For
@@ -71,7 +71,7 @@
  *
  * <li>This class provides additional methods for generating random
  * streams, that employ the above techniques when used in {@code
- * stream.parallel()} mode.</li>
+ * stream.parallel()} mode.
  *
  * </ul>
  *
@@ -240,9 +240,9 @@
     }
 
     // IllegalArgumentException messages
-    static final String BadBound = "bound must be positive";
-    static final String BadRange = "bound must be greater than origin";
-    static final String BadSize  = "size must be non-negative";
+    static final String BAD_BOUND = "bound must be positive";
+    static final String BAD_RANGE = "bound must be greater than origin";
+    static final String BAD_SIZE  = "size must be non-negative";
 
     /*
      * Internal versions of nextX methods used by streams, as well as
@@ -416,7 +416,7 @@
      */
     public int nextInt(int bound) {
         if (bound <= 0)
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         // Specialize internalNextInt for origin 0
         int r = mix32(nextSeed());
         int m = bound - 1;
@@ -444,7 +444,7 @@
      */
     public int nextInt(int origin, int bound) {
         if (origin >= bound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextInt(origin, bound);
     }
 
@@ -468,7 +468,7 @@
      */
     public long nextLong(long bound) {
         if (bound <= 0)
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         // Specialize internalNextLong for origin 0
         long r = mix64(nextSeed());
         long m = bound - 1;
@@ -496,7 +496,7 @@
      */
     public long nextLong(long origin, long bound) {
         if (origin >= bound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextLong(origin, bound);
     }
 
@@ -522,7 +522,7 @@
      */
     public double nextDouble(double bound) {
         if (!(bound > 0.0))
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
         return (result < bound) ?  result : // correct for rounding
             Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
@@ -541,7 +541,7 @@
      */
     public double nextDouble(double origin, double bound) {
         if (!(origin < bound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextDouble(origin, bound);
     }
 
@@ -569,7 +569,7 @@
      */
     public IntStream ints(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (this, 0L, streamSize, Integer.MAX_VALUE, 0),
@@ -610,9 +610,9 @@
     public IntStream ints(long streamSize, int randomNumberOrigin,
                           int randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -636,7 +636,7 @@
      */
     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -655,7 +655,7 @@
      */
     public LongStream longs(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (this, 0L, streamSize, Long.MAX_VALUE, 0L),
@@ -696,9 +696,9 @@
     public LongStream longs(long streamSize, long randomNumberOrigin,
                             long randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -722,7 +722,7 @@
      */
     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -741,7 +741,7 @@
      */
     public DoubleStream doubles(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
@@ -784,9 +784,9 @@
     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
                                 double randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -810,7 +810,7 @@
      */
     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
         if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -825,7 +825,8 @@
      * approach. The long and double versions of this class are
      * identical except for types.
      */
-    static final class RandomIntsSpliterator implements Spliterator.OfInt {
+    private static final class RandomIntsSpliterator
+            implements Spliterator.OfInt {
         final SplittableRandom rng;
         long index;
         final long fence;
@@ -880,7 +881,8 @@
     /**
      * Spliterator for long streams.
      */
-    static final class RandomLongsSpliterator implements Spliterator.OfLong {
+    private static final class RandomLongsSpliterator
+            implements Spliterator.OfLong {
         final SplittableRandom rng;
         long index;
         final long fence;
@@ -936,7 +938,8 @@
     /**
      * Spliterator for double streams.
      */
-    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+    private static final class RandomDoublesSpliterator
+            implements Spliterator.OfDouble {
         final SplittableRandom rng;
         long index;
         final long fence;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,7 +34,13 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * Provides default implementations of {@link ExecutorService}
@@ -51,7 +57,7 @@
  * <p><b>Extension example</b>. Here is a sketch of a class
  * that customizes {@link ThreadPoolExecutor} to use
  * a {@code CustomTask} class instead of the default {@code FutureTask}:
- *  <pre> {@code
+ * <pre> {@code
  * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
  *
  *   static class CustomTask<V> implements RunnableFuture<V> {...}
@@ -146,7 +152,7 @@
         int ntasks = tasks.size();
         if (ntasks == 0)
             throw new IllegalArgumentException();
-        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
+        ArrayList<Future<T>> futures = new ArrayList<>(ntasks);
         ExecutorCompletionService<T> ecs =
             new ExecutorCompletionService<T>(this);
 
@@ -179,7 +185,7 @@
                     else if (active == 0)
                         break;
                     else if (timed) {
-                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
+                        f = ecs.poll(nanos, NANOSECONDS);
                         if (f == null)
                             throw new TimeoutException();
                         nanos = deadline - System.nanoTime();
@@ -204,8 +210,7 @@
             throw ee;
 
         } finally {
-            for (int i = 0, size = futures.size(); i < size; i++)
-                futures.get(i).cancel(true);
+            cancelAll(futures);
         }
     }
 
@@ -229,8 +234,7 @@
         throws InterruptedException {
         if (tasks == null)
             throw new NullPointerException();
-        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
-        boolean done = false;
+        ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
         try {
             for (Callable<T> t : tasks) {
                 RunnableFuture<T> f = newTaskFor(t);
@@ -240,19 +244,15 @@
             for (int i = 0, size = futures.size(); i < size; i++) {
                 Future<T> f = futures.get(i);
                 if (!f.isDone()) {
-                    try {
-                        f.get();
-                    } catch (CancellationException ignore) {
-                    } catch (ExecutionException ignore) {
-                    }
+                    try { f.get(); }
+                    catch (CancellationException ignore) {}
+                    catch (ExecutionException ignore) {}
                 }
             }
-            done = true;
             return futures;
-        } finally {
-            if (!done)
-                for (int i = 0, size = futures.size(); i < size; i++)
-                    futures.get(i).cancel(true);
+        } catch (Throwable t) {
+            cancelAll(futures);
+            throw t;
         }
     }
 
@@ -261,47 +261,52 @@
         throws InterruptedException {
         if (tasks == null)
             throw new NullPointerException();
-        long nanos = unit.toNanos(timeout);
-        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
-        boolean done = false;
-        try {
+        final long nanos = unit.toNanos(timeout);
+        final long deadline = System.nanoTime() + nanos;
+        ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
+        int j = 0;
+        timedOut: try {
             for (Callable<T> t : tasks)
                 futures.add(newTaskFor(t));
 
-            final long deadline = System.nanoTime() + nanos;
             final int size = futures.size();
 
             // Interleave time checks and calls to execute in case
             // executor doesn't have any/much parallelism.
             for (int i = 0; i < size; i++) {
+                if (((i == 0) ? nanos : deadline - System.nanoTime()) <= 0L)
+                    break timedOut;
                 execute((Runnable)futures.get(i));
-                nanos = deadline - System.nanoTime();
-                if (nanos <= 0L)
-                    return futures;
             }
 
-            for (int i = 0; i < size; i++) {
-                Future<T> f = futures.get(i);
+            for (; j < size; j++) {
+                Future<T> f = futures.get(j);
                 if (!f.isDone()) {
-                    if (nanos <= 0L)
-                        return futures;
-                    try {
-                        f.get(nanos, TimeUnit.NANOSECONDS);
-                    } catch (CancellationException ignore) {
-                    } catch (ExecutionException ignore) {
-                    } catch (TimeoutException toe) {
-                        return futures;
+                    try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
+                    catch (CancellationException ignore) {}
+                    catch (ExecutionException ignore) {}
+                    catch (TimeoutException timedOut) {
+                        break timedOut;
                     }
-                    nanos = deadline - System.nanoTime();
                 }
             }
-            done = true;
             return futures;
-        } finally {
-            if (!done)
-                for (int i = 0, size = futures.size(); i < size; i++)
-                    futures.get(i).cancel(true);
+        } catch (Throwable t) {
+            cancelAll(futures);
+            throw t;
         }
+        // Timed out before all the tasks could be completed; cancel remaining
+        cancelAll(futures, j);
+        return futures;
     }
 
+    private static <T> void cancelAll(ArrayList<Future<T>> futures) {
+        cancelAll(futures, 0);
+    }
+
+    /** Cancels all futures with index at least j. */
+    private static <T> void cancelAll(ArrayList<Future<T>> futures, int j) {
+        for (int size = futures.size(); j < size; j++)
+            futures.get(j).cancel(true);
+    }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,15 +34,18 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+
+import java.lang.ref.WeakReference;
 import java.util.AbstractQueue;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.Spliterator;
 import java.util.Spliterators;
-import java.util.Spliterator;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * A bounded {@linkplain BlockingQueue blocking queue} backed by an
@@ -77,7 +80,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
@@ -121,12 +124,12 @@
      * are known not to be any.  Allows queue operations to update
      * iterator state.
      */
-    transient Itrs itrs = null;
+    transient Itrs itrs;
 
     // Internal helper methods
 
     /**
-     * Circularly decrement i.
+     * Circularly decrements array index i.
      */
     final int dec(int i) {
         return ((i == 0) ? items.length : i) - 1;
@@ -141,16 +144,6 @@
     }
 
     /**
-     * Throws NullPointerException if argument is null.
-     *
-     * @param v the element
-     */
-    private static void checkNotNull(Object v) {
-        if (v == null)
-            throw new NullPointerException();
-    }
-
-    /**
      * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
@@ -159,8 +152,7 @@
         // assert items[putIndex] == null;
         final Object[] items = this.items;
         items[putIndex] = x;
-        if (++putIndex == items.length)
-            putIndex = 0;
+        if (++putIndex == items.length) putIndex = 0;
         count++;
         notEmpty.signal();
     }
@@ -176,8 +168,7 @@
         @SuppressWarnings("unchecked")
         E x = (E) items[takeIndex];
         items[takeIndex] = null;
-        if (++takeIndex == items.length)
-            takeIndex = 0;
+        if (++takeIndex == items.length) takeIndex = 0;
         count--;
         if (itrs != null)
             itrs.elementDequeued();
@@ -198,8 +189,7 @@
         if (removeIndex == takeIndex) {
             // removing front item; just advance
             items[takeIndex] = null;
-            if (++takeIndex == items.length)
-                takeIndex = 0;
+            if (++takeIndex == items.length) takeIndex = 0;
             count--;
             if (itrs != null)
                 itrs.elementDequeued();
@@ -207,19 +197,15 @@
             // an "interior" remove
 
             // slide over all others up through putIndex.
-            final int putIndex = this.putIndex;
-            for (int i = removeIndex;;) {
-                int next = i + 1;
-                if (next == items.length)
-                    next = 0;
-                if (next != putIndex) {
-                    items[i] = items[next];
-                    i = next;
-                } else {
-                    items[i] = null;
-                    this.putIndex = i;
+            for (int i = removeIndex, putIndex = this.putIndex;;) {
+                int pred = i;
+                if (++i == items.length) i = 0;
+                if (i == putIndex) {
+                    items[pred] = null;
+                    this.putIndex = pred;
                     break;
                 }
+                items[pred] = items[i];
             }
             count--;
             if (itrs != null)
@@ -283,10 +269,8 @@
         try {
             int i = 0;
             try {
-                for (E e : c) {
-                    checkNotNull(e);
-                    items[i++] = e;
-                }
+                for (E e : c)
+                    items[i++] = Objects.requireNonNull(e);
             } catch (ArrayIndexOutOfBoundsException ex) {
                 throw new IllegalArgumentException();
             }
@@ -322,7 +306,7 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        checkNotNull(e);
+        Objects.requireNonNull(e);
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
@@ -345,7 +329,7 @@
      * @throws NullPointerException {@inheritDoc}
      */
     public void put(E e) throws InterruptedException {
-        checkNotNull(e);
+        Objects.requireNonNull(e);
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
@@ -368,13 +352,13 @@
     public boolean offer(E e, long timeout, TimeUnit unit)
         throws InterruptedException {
 
-        checkNotNull(e);
+        Objects.requireNonNull(e);
         long nanos = unit.toNanos(timeout);
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
             while (count == items.length) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -413,7 +397,7 @@
         lock.lockInterruptibly();
         try {
             while (count == 0) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -492,11 +476,11 @@
      */
     public boolean remove(Object o) {
         if (o == null) return false;
-        final Object[] items = this.items;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             if (count > 0) {
+                final Object[] items = this.items;
                 final int putIndex = this.putIndex;
                 int i = takeIndex;
                 do {
@@ -504,8 +488,7 @@
                         removeAt(i);
                         return true;
                     }
-                    if (++i == items.length)
-                        i = 0;
+                    if (++i == items.length) i = 0;
                 } while (i != putIndex);
             }
             return false;
@@ -524,18 +507,17 @@
      */
     public boolean contains(Object o) {
         if (o == null) return false;
-        final Object[] items = this.items;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             if (count > 0) {
+                final Object[] items = this.items;
                 final int putIndex = this.putIndex;
                 int i = takeIndex;
                 do {
                     if (o.equals(items[i]))
                         return true;
-                    if (++i == items.length)
-                        i = 0;
+                    if (++i == items.length) i = 0;
                 } while (i != putIndex);
             }
             return false;
@@ -558,23 +540,18 @@
      * @return an array containing all of the elements in this queue
      */
     public Object[] toArray() {
-        Object[] a;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            final int count = this.count;
-            a = new Object[count];
-            int n = items.length - takeIndex;
-            if (count <= n)
-                System.arraycopy(items, takeIndex, a, 0, count);
-            else {
-                System.arraycopy(items, takeIndex, a, 0, n);
-                System.arraycopy(items, 0, a, n, count - n);
-            }
+            final Object[] items = this.items;
+            final int end = takeIndex + count;
+            final Object[] a = Arrays.copyOfRange(items, takeIndex, end);
+            if (end != putIndex)
+                System.arraycopy(items, 0, a, items.length - takeIndex, putIndex);
+            return a;
         } finally {
             lock.unlock();
         }
-        return a;
     }
 
     /**
@@ -598,7 +575,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -614,53 +591,30 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        final Object[] items = this.items;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
+            final Object[] items = this.items;
             final int count = this.count;
-            final int len = a.length;
-            if (len < count)
-                a = (T[])java.lang.reflect.Array.newInstance(
-                    a.getClass().getComponentType(), count);
-            int n = items.length - takeIndex;
-            if (count <= n)
-                System.arraycopy(items, takeIndex, a, 0, count);
-            else {
-                System.arraycopy(items, takeIndex, a, 0, n);
-                System.arraycopy(items, 0, a, n, count - n);
+            final int firstLeg = Math.min(items.length - takeIndex, count);
+            if (a.length < count) {
+                a = (T[]) Arrays.copyOfRange(items, takeIndex, takeIndex + count,
+                                             a.getClass());
+            } else {
+                System.arraycopy(items, takeIndex, a, 0, firstLeg);
+                if (a.length > count)
+                    a[count] = null;
             }
-            if (len > count)
-                a[count] = null;
+            if (firstLeg < count)
+                System.arraycopy(items, 0, a, firstLeg, putIndex);
+            return a;
         } finally {
             lock.unlock();
         }
-        return a;
     }
 
     public String toString() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int k = count;
-            if (k == 0)
-                return "[]";
-
-            final Object[] items = this.items;
-            StringBuilder sb = new StringBuilder();
-            sb.append('[');
-            for (int i = takeIndex; ; ) {
-                Object e = items[i];
-                sb.append(e == this ? "(this Collection)" : e);
-                if (--k == 0)
-                    return sb.append(']').toString();
-                sb.append(',').append(' ');
-                if (++i == items.length)
-                    i = 0;
-            }
-        } finally {
-            lock.unlock();
-        }
+        return Helpers.collectionToString(this);
     }
 
     /**
@@ -668,18 +622,17 @@
      * The queue will be empty after this call returns.
      */
     public void clear() {
-        final Object[] items = this.items;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             int k = count;
             if (k > 0) {
+                final Object[] items = this.items;
                 final int putIndex = this.putIndex;
                 int i = takeIndex;
                 do {
                     items[i] = null;
-                    if (++i == items.length)
-                        i = 0;
+                    if (++i == items.length) i = 0;
                 } while (i != putIndex);
                 takeIndex = putIndex;
                 count = 0;
@@ -710,7 +663,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        checkNotNull(c);
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -728,8 +681,7 @@
                     E x = (E) items[take];
                     c.add(x);
                     items[take] = null;
-                    if (++take == items.length)
-                        take = 0;
+                    if (++take == items.length) take = 0;
                     i++;
                 }
                 return n;
@@ -832,13 +784,13 @@
         }
 
         /** Incremented whenever takeIndex wraps around to 0 */
-        int cycles = 0;
+        int cycles;
 
         /** Linked list of weak iterator references */
         private Node head;
 
         /** Used to expunge stale iterators */
-        private Node sweeper = null;
+        private Node sweeper;
 
         private static final int SHORT_SWEEP_PROBES = 4;
         private static final int LONG_SWEEP_PROBES = 16;
@@ -1095,10 +1047,8 @@
 
         private int incCursor(int index) {
             // assert lock.getHoldCount() == 1;
-            if (++index == items.length)
-                index = 0;
-            if (index == putIndex)
-                index = NONE;
+            if (++index == items.length) index = 0;
+            if (index == putIndex) index = NONE;
             return index;
         }
 
@@ -1314,17 +1264,18 @@
             if (isDetached())
                 return true;
 
-            final int cycles = itrs.cycles;
             final int takeIndex = ArrayBlockingQueue.this.takeIndex;
-            final int prevCycles = this.prevCycles;
             final int prevTakeIndex = this.prevTakeIndex;
             final int len = items.length;
-            int cycleDiff = cycles - prevCycles;
-            if (removedIndex < takeIndex)
-                cycleDiff++;
+            // distance from prevTakeIndex to removedIndex
             final int removedDistance =
-                (cycleDiff * len) + (removedIndex - prevTakeIndex);
-            // assert removedDistance >= 0;
+                len * (itrs.cycles - this.prevCycles
+                       + ((removedIndex < takeIndex) ? 1 : 0))
+                + (removedIndex - prevTakeIndex);
+            // assert itrs.cycles - this.prevCycles >= 0;
+            // assert itrs.cycles - this.prevCycles <= 1;
+            // assert removedDistance > 0;
+            // assert removedIndex != takeIndex;
             int cursor = this.cursor;
             if (cursor >= 0) {
                 int x = distance(cursor, prevTakeIndex, len);
@@ -1353,7 +1304,7 @@
                 else if (x > removedDistance)
                     this.nextIndex = nextIndex = dec(nextIndex);
             }
-            else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
+            if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
                 this.prevTakeIndex = DETACHED;
                 return true;
             }
@@ -1410,8 +1361,9 @@
      */
     public Spliterator<E> spliterator() {
         return Spliterators.spliterator
-            (this, Spliterator.ORDERED | Spliterator.NONNULL |
-             Spliterator.CONCURRENT);
+            (this, (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT));
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,7 +34,10 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 /**
  * A {@link Deque} that additionally supports blocking operations that wait
@@ -195,7 +198,7 @@
  *
  * @since 1.6
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
  */
 public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
     /*
@@ -401,9 +404,9 @@
      * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeFirstOccurrence(Object o);
 
@@ -419,9 +422,9 @@
      * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeLastOccurrence(Object o);
 
@@ -596,9 +599,9 @@
      * @return {@code true} if this deque changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -611,18 +614,18 @@
      * @return {@code true} if this deque contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
-    public boolean contains(Object o);
+    boolean contains(Object o);
 
     /**
      * Returns the number of elements in this deque.
      *
      * @return the number of elements in this deque
      */
-    public int size();
+    int size();
 
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -127,7 +127,7 @@
  * Usage example, based on a typical producer-consumer scenario.
  * Note that a {@code BlockingQueue} can safely be used with multiple
  * producers and multiple consumers.
- *  <pre> {@code
+ * <pre> {@code
  * class Producer implements Runnable {
  *   private final BlockingQueue queue;
  *   Producer(BlockingQueue q) { queue = q; }
@@ -175,7 +175,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public interface BlockingQueue<E> extends Queue<E> {
     /**
@@ -303,9 +303,9 @@
      * @return {@code true} if this queue changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -318,11 +318,11 @@
      * @return {@code true} if this queue contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
-    public boolean contains(Object o);
+    boolean contains(Object o);
 
     /**
      * Removes all available elements from this queue and adds them
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,23 +34,13 @@
  */
 
 package java.util.concurrent;
-import java.util.function.Supplier;
-import java.util.function.Consumer;
+
+import java.util.concurrent.locks.LockSupport;
 import java.util.function.BiConsumer;
-import java.util.function.Function;
 import java.util.function.BiFunction;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.locks.LockSupport;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
 
 /**
  * A {@link Future} that may be explicitly completed (setting its
@@ -71,19 +61,32 @@
  * <li>Actions supplied for dependent completions of
  * <em>non-async</em> methods may be performed by the thread that
  * completes the current CompletableFuture, or by any other caller of
- * a completion method.</li>
+ * a completion method.
  *
  * <li>All <em>async</em> methods without an explicit Executor
  * argument are performed using the {@link ForkJoinPool#commonPool()}
  * (unless it does not support a parallelism level of at least two, in
- * which case, a new Thread is created to run each task).  To simplify
- * monitoring, debugging, and tracking, all generated asynchronous
- * tasks are instances of the marker interface {@link
- * AsynchronousCompletionTask}. </li>
+ * which case, a new Thread is created to run each task).  This may be
+ * overridden for non-static methods in subclasses by defining method
+ * {@link #defaultExecutor()}. To simplify monitoring, debugging,
+ * and tracking, all generated asynchronous tasks are instances of the
+ * marker interface {@link AsynchronousCompletionTask}.  Operations
+ * with time-delays can use adapter methods defined in this class, for
+ * example: {@code supplyAsync(supplier, delayedExecutor(timeout,
+ * timeUnit))}.  To support methods with delays and timeouts, this
+ * class maintains at most one daemon thread for triggering and
+ * cancelling actions, not for running them.
  *
  * <li>All CompletionStage methods are implemented independently of
  * other public methods, so the behavior of one method is not impacted
- * by overrides of others in subclasses.  </li> </ul>
+ * by overrides of others in subclasses.
+ *
+ * <li>All CompletionStage methods return CompletableFutures.  To
+ * restrict usages to only those methods defined in interface
+ * CompletionStage, use method {@link #minimalCompletionStage}. Or to
+ * ensure only that clients do not themselves modify a future, use
+ * method {@link #copy}.
+ * </ul>
  *
  * <p>CompletableFuture also implements {@link Future} with the following
  * policies: <ul>
@@ -94,7 +97,7 @@
  * completion.  Method {@link #cancel cancel} has the same effect as
  * {@code completeExceptionally(new CancellationException())}. Method
  * {@link #isCompletedExceptionally} can be used to determine if a
- * CompletableFuture completed in any exceptional fashion.</li>
+ * CompletableFuture completed in any exceptional fashion.
  *
  * <li>In case of exceptional completion with a CompletionException,
  * methods {@link #get()} and {@link #get(long, TimeUnit)} throw an
@@ -102,10 +105,38 @@
  * corresponding CompletionException.  To simplify usage in most
  * contexts, this class also defines methods {@link #join()} and
  * {@link #getNow} that instead throw the CompletionException directly
- * in these cases.</li> </ul>
+ * in these cases.
+ * </ul>
+ *
+ * <p>Arguments used to pass a completion result (that is, for
+ * parameters of type {@code T}) for methods accepting them may be
+ * null, but passing a null value for any other parameter will result
+ * in a {@link NullPointerException} being thrown.
+ *
+ * <p>Subclasses of this class should normally override the "virtual
+ * constructor" method {@link #newIncompleteFuture}, which establishes
+ * the concrete type returned by CompletionStage methods. For example,
+ * here is a class that substitutes a different default Executor and
+ * disables the {@code obtrude} methods:
+ *
+ * <pre> {@code
+ * class MyCompletableFuture<T> extends CompletableFuture<T> {
+ *   static final Executor myExecutor = ...;
+ *   public MyCompletableFuture() { }
+ *   public <U> CompletableFuture<U> newIncompleteFuture() {
+ *     return new MyCompletableFuture<U>(); }
+ *   public Executor defaultExecutor() {
+ *     return myExecutor; }
+ *   public void obtrudeValue(T value) {
+ *     throw new UnsupportedOperationException(); }
+ *   public void obtrudeException(Throwable ex) {
+ *     throw new UnsupportedOperationException(); }
+ * }}</pre>
  *
  * @author Doug Lea
  * @since 1.8
+ * @param <T> The result type returned by this future's {@code join}
+ * and {@code get} methods
  */
 public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
 
@@ -150,9 +181,7 @@
      *   fields for source(s), actions, and dependent. They are
      *   boringly similar, differing from others only with respect to
      *   underlying functional forms. We do this so that users don't
-     *   encounter layers of adaptors in common usages. We also
-     *   include "Relay" classes/methods that don't correspond to user
-     *   methods; they copy results from one stage to another.
+     *   encounter layers of adapters in common usages.
      *
      * * Boolean CompletableFuture method x(...) (for example
      *   uniApply) takes all of the arguments needed to check that an
@@ -219,18 +248,18 @@
     volatile Completion stack;    // Top of Treiber stack of dependent actions
 
     final boolean internalComplete(Object r) { // CAS from null to r
-        return UNSAFE.compareAndSwapObject(this, RESULT, null, r);
+        return U.compareAndSwapObject(this, RESULT, null, r);
     }
 
     final boolean casStack(Completion cmp, Completion val) {
-        return UNSAFE.compareAndSwapObject(this, STACK, cmp, val);
+        return U.compareAndSwapObject(this, STACK, cmp, val);
     }
 
     /** Returns true if successfully pushed c onto stack. */
     final boolean tryPushStack(Completion c) {
         Completion h = stack;
         lazySetNext(c, h);
-        return UNSAFE.compareAndSwapObject(this, STACK, h, c);
+        return U.compareAndSwapObject(this, STACK, h, c);
     }
 
     /** Unconditionally pushes c onto stack, retrying if necessary. */
@@ -250,8 +279,8 @@
 
     /** Completes with the null value, unless already completed. */
     final boolean completeNull() {
-        return UNSAFE.compareAndSwapObject(this, RESULT, null,
-                                           NIL);
+        return U.compareAndSwapObject(this, RESULT, null,
+                                      NIL);
     }
 
     /** Returns the encoding of the given non-exceptional value. */
@@ -261,8 +290,8 @@
 
     /** Completes with a non-exceptional result, unless already completed. */
     final boolean completeValue(T t) {
-        return UNSAFE.compareAndSwapObject(this, RESULT, null,
-                                           (t == null) ? NIL : t);
+        return U.compareAndSwapObject(this, RESULT, null,
+                                      (t == null) ? NIL : t);
     }
 
     /**
@@ -276,8 +305,8 @@
 
     /** Completes with an exceptional result, unless already completed. */
     final boolean completeThrowable(Throwable x) {
-        return UNSAFE.compareAndSwapObject(this, RESULT, null,
-                                           encodeThrowable(x));
+        return U.compareAndSwapObject(this, RESULT, null,
+                                      encodeThrowable(x));
     }
 
     /**
@@ -304,8 +333,8 @@
      * existing CompletionException.
      */
     final boolean completeThrowable(Throwable x, Object r) {
-        return UNSAFE.compareAndSwapObject(this, RESULT, null,
-                                           encodeThrowable(x, r));
+        return U.compareAndSwapObject(this, RESULT, null,
+                                      encodeThrowable(x, r));
     }
 
     /**
@@ -334,8 +363,8 @@
      * If exceptional, r is first coerced to a CompletionException.
      */
     final boolean completeRelay(Object r) {
-        return UNSAFE.compareAndSwapObject(this, RESULT, null,
-                                           encodeRelay(r));
+        return U.compareAndSwapObject(this, RESULT, null,
+                                      encodeRelay(r));
     }
 
     /**
@@ -390,14 +419,14 @@
     public static interface AsynchronousCompletionTask {
     }
 
-    private static final boolean useCommonPool =
+    private static final boolean USE_COMMON_POOL =
         (ForkJoinPool.getCommonPoolParallelism() > 1);
 
     /**
      * Default executor -- ForkJoinPool.commonPool() unless it cannot
      * support parallelism.
      */
-    private static final Executor asyncPool = useCommonPool ?
+    private static final Executor ASYNC_POOL = USE_COMMON_POOL ?
         ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
 
     /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
@@ -407,11 +436,11 @@
 
     /**
      * Null-checks user executor argument, and translates uses of
-     * commonPool to asyncPool in case parallelism disabled.
+     * commonPool to ASYNC_POOL in case parallelism disabled.
      */
     static Executor screenExecutor(Executor e) {
-        if (!useCommonPool && e == ForkJoinPool.commonPool())
-            return asyncPool;
+        if (!USE_COMMON_POOL && e == ForkJoinPool.commonPool())
+            return ASYNC_POOL;
         if (e == null) throw new NullPointerException();
         return e;
     }
@@ -421,6 +450,12 @@
     static final int ASYNC  =  1;
     static final int NESTED = -1;
 
+    /**
+     * Spins before blocking in waitingGet
+     */
+    static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
+                              1 << 8 : 0);
+
     /* ------------- Base Completion classes and operations -------------- */
 
     @SuppressWarnings("serial")
@@ -440,13 +475,13 @@
         abstract boolean isLive();
 
         public final void run()                { tryFire(ASYNC); }
-        public final boolean exec()            { tryFire(ASYNC); return true; }
+        public final boolean exec()            { tryFire(ASYNC); return false; }
         public final Void getRawResult()       { return null; }
         public final void setRawResult(Void v) {}
     }
 
     static void lazySetNext(Completion c, Completion next) {
-        UNSAFE.putOrderedObject(c, NEXT, next);
+        U.putOrderedObject(c, NEXT, next);
     }
 
     /**
@@ -610,7 +645,7 @@
     private <V> CompletableFuture<V> uniApplyStage(
         Executor e, Function<? super T,? extends V> f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<V> d =  new CompletableFuture<V>();
+        CompletableFuture<V> d = newIncompleteFuture();
         if (e != null || !d.uniApply(this, f, null)) {
             UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
             push(c);
@@ -665,7 +700,7 @@
     private CompletableFuture<Void> uniAcceptStage(Executor e,
                                                    Consumer<? super T> f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.uniAccept(this, f, null)) {
             UniAccept<T> c = new UniAccept<T>(e, d, this, f);
             push(c);
@@ -713,7 +748,7 @@
 
     private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.uniRun(this, f, null)) {
             UniRun<T> c = new UniRun<T>(e, d, this, f);
             push(c);
@@ -774,7 +809,7 @@
     private CompletableFuture<T> uniWhenCompleteStage(
         Executor e, BiConsumer<? super T, ? super Throwable> f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<T> d = new CompletableFuture<T>();
+        CompletableFuture<T> d = newIncompleteFuture();
         if (e != null || !d.uniWhenComplete(this, f, null)) {
             UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
             push(c);
@@ -830,7 +865,7 @@
     private <V> CompletableFuture<V> uniHandleStage(
         Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<V> d = new CompletableFuture<V>();
+        CompletableFuture<V> d = newIncompleteFuture();
         if (e != null || !d.uniHandle(this, f, null)) {
             UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
             push(c);
@@ -880,7 +915,7 @@
     private CompletableFuture<T> uniExceptionallyStage(
         Function<Throwable, ? extends T> f) {
         if (f == null) throw new NullPointerException();
-        CompletableFuture<T> d = new CompletableFuture<T>();
+        CompletableFuture<T> d = newIncompleteFuture();
         if (!d.uniExceptionally(this, f, null)) {
             UniExceptionally<T> c = new UniExceptionally<T>(d, this, f);
             push(c);
@@ -912,6 +947,30 @@
         return true;
     }
 
+    private CompletableFuture<T> uniCopyStage() {
+        Object r;
+        CompletableFuture<T> d = newIncompleteFuture();
+        if ((r = result) != null)
+            d.completeRelay(r);
+        else {
+            UniRelay<T> c = new UniRelay<T>(d, this);
+            push(c);
+            c.tryFire(SYNC);
+        }
+        return d;
+    }
+
+    private MinimalStage<T> uniAsMinimalStage() {
+        Object r;
+        if ((r = result) != null)
+            return new MinimalStage<T>(encodeRelay(r));
+        MinimalStage<T> d = new MinimalStage<T>();
+        UniRelay<T> c = new UniRelay<T>(d, this);
+        push(c);
+        c.tryFire(SYNC);
+        return d;
+    }
+
     @SuppressWarnings("serial")
     static final class UniCompose<T,V> extends UniCompletion<T,V> {
         Function<? super T, ? extends CompletionStage<V>> fn;
@@ -967,31 +1026,32 @@
     private <V> CompletableFuture<V> uniComposeStage(
         Executor e, Function<? super T, ? extends CompletionStage<V>> f) {
         if (f == null) throw new NullPointerException();
-        Object r; Throwable x;
+        Object r, s; Throwable x;
+        CompletableFuture<V> d = newIncompleteFuture();
         if (e == null && (r = result) != null) {
-            // try to return function result directly
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
-                    return new CompletableFuture<V>(encodeThrowable(x, r));
+                    d.result = encodeThrowable(x, r);
+                    return d;
                 }
                 r = null;
             }
             try {
                 @SuppressWarnings("unchecked") T t = (T) r;
                 CompletableFuture<V> g = f.apply(t).toCompletableFuture();
-                Object s = g.result;
-                if (s != null)
-                    return new CompletableFuture<V>(encodeRelay(s));
-                CompletableFuture<V> d = new CompletableFuture<V>();
-                UniRelay<V> copy = new UniRelay<V>(d, g);
-                g.push(copy);
-                copy.tryFire(SYNC);
+                if ((s = g.result) != null)
+                    d.completeRelay(s);
+                else {
+                    UniRelay<V> c = new UniRelay<V>(d, g);
+                    g.push(c);
+                    c.tryFire(SYNC);
+                }
                 return d;
             } catch (Throwable ex) {
-                return new CompletableFuture<V>(encodeThrowable(ex));
+                d.result = encodeThrowable(ex);
+                return d;
             }
         }
-        CompletableFuture<V> d = new CompletableFuture<V>();
         UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f);
         push(c);
         c.tryFire(SYNC);
@@ -1116,7 +1176,7 @@
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<V> d = new CompletableFuture<V>();
+        CompletableFuture<V> d = newIncompleteFuture();
         if (e != null || !d.biApply(this, b, f, null)) {
             BiApply<T,U,V> c = new BiApply<T,U,V>(e, d, this, b, f);
             bipush(b, c);
@@ -1188,7 +1248,7 @@
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.biAccept(this, b, f, null)) {
             BiAccept<T,U> c = new BiAccept<T,U>(e, d, this, b, f);
             bipush(b, c);
@@ -1247,7 +1307,7 @@
         CompletableFuture<?> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.biRun(this, b, f, null)) {
             BiRun<T,?> c = new BiRun<>(e, d, this, b, f);
             bipush(b, c);
@@ -1302,7 +1362,7 @@
             if ((a = (lo == mid ? cfs[lo] :
                       andTree(cfs, lo, mid))) == null ||
                 (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
-                      andTree(cfs, mid+1, hi)))  == null)
+                      andTree(cfs, mid+1, hi))) == null)
                 throw new NullPointerException();
             if (!d.biRelay(a, b)) {
                 BiRelay<?,?> c = new BiRelay<>(d, a, b);
@@ -1388,7 +1448,7 @@
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<V> d = new CompletableFuture<V>();
+        CompletableFuture<V> d = newIncompleteFuture();
         if (e != null || !d.orApply(this, b, f, null)) {
             OrApply<T,U,V> c = new OrApply<T,U,V>(e, d, this, b, f);
             orpush(b, c);
@@ -1452,7 +1512,7 @@
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.orAccept(this, b, f, null)) {
             OrAccept<T,U> c = new OrAccept<T,U>(e, d, this, b, f);
             orpush(b, c);
@@ -1510,7 +1570,7 @@
         CompletableFuture<?> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
+        CompletableFuture<Void> d = newIncompleteFuture();
         if (e != null || !d.orRun(this, b, f, null)) {
             OrRun<T,?> c = new OrRun<>(e, d, this, b, f);
             orpush(b, c);
@@ -1556,7 +1616,7 @@
             if ((a = (lo == mid ? cfs[lo] :
                       orTree(cfs, lo, mid))) == null ||
                 (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
-                      orTree(cfs, mid+1, hi)))  == null)
+                      orTree(cfs, mid+1, hi))) == null)
                 throw new NullPointerException();
             if (!d.orRelay(a, b)) {
                 OrRelay<?,?> c = new OrRelay<>(d, a, b);
@@ -1571,9 +1631,9 @@
 
     @SuppressWarnings("serial")
     static final class AsyncSupply<T> extends ForkJoinTask<Void>
-            implements Runnable, AsynchronousCompletionTask {
-        CompletableFuture<T> dep; Supplier<T> fn;
-        AsyncSupply(CompletableFuture<T> dep, Supplier<T> fn) {
+        implements Runnable, AsynchronousCompletionTask {
+        CompletableFuture<T> dep; Supplier<? extends T> fn;
+        AsyncSupply(CompletableFuture<T> dep, Supplier<? extends T> fn) {
             this.dep = dep; this.fn = fn;
         }
 
@@ -1582,7 +1642,7 @@
         public final boolean exec() { run(); return true; }
 
         public void run() {
-            CompletableFuture<T> d; Supplier<T> f;
+            CompletableFuture<T> d; Supplier<? extends T> f;
             if ((d = dep) != null && (f = fn) != null) {
                 dep = null; fn = null;
                 if (d.result == null) {
@@ -1607,7 +1667,7 @@
 
     @SuppressWarnings("serial")
     static final class AsyncRun extends ForkJoinTask<Void>
-            implements Runnable, AsynchronousCompletionTask {
+        implements Runnable, AsynchronousCompletionTask {
         CompletableFuture<Void> dep; Runnable fn;
         AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
             this.dep = dep; this.fn = fn;
@@ -1651,14 +1711,15 @@
     @SuppressWarnings("serial")
     static final class Signaller extends Completion
         implements ForkJoinPool.ManagedBlocker {
-        long nanos;                    // wait time if timed
+        long nanos;                    // remaining wait time if timed
         final long deadline;           // non-zero if timed
-        volatile int interruptControl; // > 0: interruptible, < 0: interrupted
+        final boolean interruptible;
+        boolean interrupted;
         volatile Thread thread;
 
         Signaller(boolean interruptible, long nanos, long deadline) {
             this.thread = Thread.currentThread();
-            this.interruptControl = interruptible ? 1 : 0;
+            this.interruptible = interruptible;
             this.nanos = nanos;
             this.deadline = deadline;
         }
@@ -1671,29 +1732,22 @@
             return null;
         }
         public boolean isReleasable() {
-            if (thread == null)
-                return true;
-            if (Thread.interrupted()) {
-                int i = interruptControl;
-                interruptControl = -1;
-                if (i > 0)
-                    return true;
-            }
-            if (deadline != 0L &&
-                (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
-                thread = null;
-                return true;
-            }
-            return false;
+            if (Thread.interrupted())
+                interrupted = true;
+            return ((interrupted && interruptible) ||
+                    (deadline != 0L &&
+                     (nanos <= 0L ||
+                      (nanos = deadline - System.nanoTime()) <= 0L)) ||
+                    thread == null);
         }
         public boolean block() {
-            if (isReleasable())
-                return true;
-            else if (deadline == 0L)
-                LockSupport.park(this);
-            else if (nanos > 0L)
-                LockSupport.parkNanos(this, nanos);
-            return isReleasable();
+            while (!isReleasable()) {
+                if (deadline == 0L)
+                    LockSupport.park(this);
+                else
+                    LockSupport.parkNanos(this, nanos);
+            }
+            return true;
         }
         final boolean isLive() { return thread != null; }
     }
@@ -1705,13 +1759,10 @@
     private Object waitingGet(boolean interruptible) {
         Signaller q = null;
         boolean queued = false;
-        int spins = -1;
+        int spins = SPINS;
         Object r;
         while ((r = result) == null) {
-            if (spins < 0)
-                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
-                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
-            else if (spins > 0) {
+            if (spins > 0) {
                 if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                     --spins;
             }
@@ -1719,29 +1770,27 @@
                 q = new Signaller(interruptible, 0L, 0L);
             else if (!queued)
                 queued = tryPushStack(q);
-            else if (interruptible && q.interruptControl < 0) {
-                q.thread = null;
-                cleanStack();
-                return null;
-            }
-            else if (q.thread != null && result == null) {
+            else {
                 try {
                     ForkJoinPool.managedBlock(q);
-                } catch (InterruptedException ie) {
-                    q.interruptControl = -1;
+                } catch (InterruptedException ie) { // currently cannot happen
+                    q.interrupted = true;
                 }
+                if (q.interrupted && interruptible)
+                    break;
             }
         }
         if (q != null) {
             q.thread = null;
-            if (q.interruptControl < 0) {
+            if (q.interrupted) {
                 if (interruptible)
-                    r = null; // report interruption
+                    cleanStack();
                 else
                     Thread.currentThread().interrupt();
             }
         }
-        postComplete();
+        if (r != null)
+            postComplete();
         return r;
     }
 
@@ -1752,37 +1801,39 @@
     private Object timedGet(long nanos) throws TimeoutException {
         if (Thread.interrupted())
             return null;
-        if (nanos <= 0L)
-            throw new TimeoutException();
-        long d = System.nanoTime() + nanos;
-        Signaller q = new Signaller(true, nanos, d == 0L ? 1L : d); // avoid 0
-        boolean queued = false;
-        Object r;
-        // We intentionally don't spin here (as waitingGet does) because
-        // the call to nanoTime() above acts much like a spin.
-        while ((r = result) == null) {
-            if (!queued)
-                queued = tryPushStack(q);
-            else if (q.interruptControl < 0 || q.nanos <= 0L) {
-                q.thread = null;
-                cleanStack();
-                if (q.interruptControl < 0)
-                    return null;
-                throw new TimeoutException();
-            }
-            else if (q.thread != null && result == null) {
-                try {
-                    ForkJoinPool.managedBlock(q);
-                } catch (InterruptedException ie) {
-                    q.interruptControl = -1;
+        if (nanos > 0L) {
+            long d = System.nanoTime() + nanos;
+            long deadline = (d == 0L) ? 1L : d; // avoid 0
+            Signaller q = null;
+            boolean queued = false;
+            Object r;
+            while ((r = result) == null) { // similar to untimed, without spins
+                if (q == null)
+                    q = new Signaller(true, nanos, deadline);
+                else if (!queued)
+                    queued = tryPushStack(q);
+                else if (q.nanos <= 0L)
+                    break;
+                else {
+                    try {
+                        ForkJoinPool.managedBlock(q);
+                    } catch (InterruptedException ie) {
+                        q.interrupted = true;
+                    }
+                    if (q.interrupted)
+                        break;
                 }
             }
+            if (q != null)
+                q.thread = null;
+            if (r != null)
+                postComplete();
+            else
+                cleanStack();
+            if (r != null || (q != null && q.interrupted))
+                return r;
         }
-        if (q.interruptControl < 0)
-            r = null;
-        q.thread = null;
-        postComplete();
-        return r;
+        throw new TimeoutException();
     }
 
     /* ------------- public methods -------------- */
@@ -1796,7 +1847,7 @@
     /**
      * Creates a new complete CompletableFuture with given encoded result.
      */
-    private CompletableFuture(Object r) {
+    CompletableFuture(Object r) {
         this.result = r;
     }
 
@@ -1811,7 +1862,7 @@
      * @return the new CompletableFuture
      */
     public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
-        return asyncSupplyStage(asyncPool, supplier);
+        return asyncSupplyStage(ASYNC_POOL, supplier);
     }
 
     /**
@@ -1840,7 +1891,7 @@
      * @return the new CompletableFuture
      */
     public static CompletableFuture<Void> runAsync(Runnable runnable) {
-        return asyncRunStage(asyncPool, runnable);
+        return asyncRunStage(ASYNC_POOL, runnable);
     }
 
     /**
@@ -1985,7 +2036,7 @@
 
     public <U> CompletableFuture<U> thenApplyAsync(
         Function<? super T,? extends U> fn) {
-        return uniApplyStage(asyncPool, fn);
+        return uniApplyStage(defaultExecutor(), fn);
     }
 
     public <U> CompletableFuture<U> thenApplyAsync(
@@ -1998,7 +2049,7 @@
     }
 
     public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
-        return uniAcceptStage(asyncPool, action);
+        return uniAcceptStage(defaultExecutor(), action);
     }
 
     public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
@@ -2011,7 +2062,7 @@
     }
 
     public CompletableFuture<Void> thenRunAsync(Runnable action) {
-        return uniRunStage(asyncPool, action);
+        return uniRunStage(defaultExecutor(), action);
     }
 
     public CompletableFuture<Void> thenRunAsync(Runnable action,
@@ -2028,7 +2079,7 @@
     public <U,V> CompletableFuture<V> thenCombineAsync(
         CompletionStage<? extends U> other,
         BiFunction<? super T,? super U,? extends V> fn) {
-        return biApplyStage(asyncPool, other, fn);
+        return biApplyStage(defaultExecutor(), other, fn);
     }
 
     public <U,V> CompletableFuture<V> thenCombineAsync(
@@ -2046,7 +2097,7 @@
     public <U> CompletableFuture<Void> thenAcceptBothAsync(
         CompletionStage<? extends U> other,
         BiConsumer<? super T, ? super U> action) {
-        return biAcceptStage(asyncPool, other, action);
+        return biAcceptStage(defaultExecutor(), other, action);
     }
 
     public <U> CompletableFuture<Void> thenAcceptBothAsync(
@@ -2062,7 +2113,7 @@
 
     public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
                                                      Runnable action) {
-        return biRunStage(asyncPool, other, action);
+        return biRunStage(defaultExecutor(), other, action);
     }
 
     public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
@@ -2078,7 +2129,7 @@
 
     public <U> CompletableFuture<U> applyToEitherAsync(
         CompletionStage<? extends T> other, Function<? super T, U> fn) {
-        return orApplyStage(asyncPool, other, fn);
+        return orApplyStage(defaultExecutor(), other, fn);
     }
 
     public <U> CompletableFuture<U> applyToEitherAsync(
@@ -2094,7 +2145,7 @@
 
     public CompletableFuture<Void> acceptEitherAsync(
         CompletionStage<? extends T> other, Consumer<? super T> action) {
-        return orAcceptStage(asyncPool, other, action);
+        return orAcceptStage(defaultExecutor(), other, action);
     }
 
     public CompletableFuture<Void> acceptEitherAsync(
@@ -2110,7 +2161,7 @@
 
     public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
                                                        Runnable action) {
-        return orRunStage(asyncPool, other, action);
+        return orRunStage(defaultExecutor(), other, action);
     }
 
     public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
@@ -2126,7 +2177,7 @@
 
     public <U> CompletableFuture<U> thenComposeAsync(
         Function<? super T, ? extends CompletionStage<U>> fn) {
-        return uniComposeStage(asyncPool, fn);
+        return uniComposeStage(defaultExecutor(), fn);
     }
 
     public <U> CompletableFuture<U> thenComposeAsync(
@@ -2142,7 +2193,7 @@
 
     public CompletableFuture<T> whenCompleteAsync(
         BiConsumer<? super T, ? super Throwable> action) {
-        return uniWhenCompleteStage(asyncPool, action);
+        return uniWhenCompleteStage(defaultExecutor(), action);
     }
 
     public CompletableFuture<T> whenCompleteAsync(
@@ -2157,7 +2208,7 @@
 
     public <U> CompletableFuture<U> handleAsync(
         BiFunction<? super T, Throwable, ? extends U> fn) {
-        return uniHandleStage(asyncPool, fn);
+        return uniHandleStage(defaultExecutor(), fn);
     }
 
     public <U> CompletableFuture<U> handleAsync(
@@ -2196,6 +2247,7 @@
         return uniExceptionallyStage(fn);
     }
 
+
     /* ------------- Arbitrary-arity constructions -------------- */
 
     /**
@@ -2353,10 +2405,12 @@
      */
     public String toString() {
         Object r = result;
-        int count;
+        int count = 0; // avoid call to getNumberOfDependents in case disabled
+        for (Completion p = stack; p != null; p = p.next)
+            ++count;
         return super.toString() +
             ((r == null) ?
-             (((count = getNumberOfDependents()) == 0) ?
+             ((count == 0) ?
               "[Not completed]" :
               "[Not completed, " + count + " dependents]") :
              (((r instanceof AltResult) && ((AltResult)r).ex != null) ?
@@ -2364,22 +2418,381 @@
               "[Completed normally]"));
     }
 
+    // jdk9 additions
+
+    /**
+     * Returns a new incomplete CompletableFuture of the type to be
+     * returned by a CompletionStage method. Subclasses should
+     * normally override this method to return an instance of the same
+     * class as this CompletableFuture. The default implementation
+     * returns an instance of class CompletableFuture.
+     *
+     * @param <U> the type of the value
+     * @return a new CompletableFuture
+     * @since 1.9
+     */
+    public <U> CompletableFuture<U> newIncompleteFuture() {
+        return new CompletableFuture<U>();
+    }
+
+    /**
+     * Returns the default Executor used for async methods that do not
+     * specify an Executor. This class uses the {@link
+     * ForkJoinPool#commonPool()} if it supports more than one
+     * parallel thread, or else an Executor using one thread per async
+     * task.  This method may be overridden in subclasses to return
+     * an Executor that provides at least one independent thread.
+     *
+     * @return the executor
+     * @since 1.9
+     */
+    public Executor defaultExecutor() {
+        return ASYNC_POOL;
+    }
+
+    /**
+     * Returns a new CompletableFuture that is completed normally with
+     * the same value as this CompletableFuture when it completes
+     * normally. If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture completes exceptionally
+     * with a CompletionException with this exception as cause. The
+     * behavior is equivalent to {@code thenApply(x -> x)}. This
+     * method may be useful as a form of "defensive copying", to
+     * prevent clients from completing, while still being able to
+     * arrange dependent actions.
+     *
+     * @return the new CompletableFuture
+     * @since 1.9
+     */
+    public CompletableFuture<T> copy() {
+        return uniCopyStage();
+    }
+
+    /**
+     * Returns a new CompletionStage that is completed normally with
+     * the same value as this CompletableFuture when it completes
+     * normally, and cannot be independently completed or otherwise
+     * used in ways not defined by the methods of interface {@link
+     * CompletionStage}.  If this CompletableFuture completes
+     * exceptionally, then the returned CompletionStage completes
+     * exceptionally with a CompletionException with this exception as
+     * cause.
+     *
+     * @return the new CompletionStage
+     * @since 1.9
+     */
+    public CompletionStage<T> minimalCompletionStage() {
+        return uniAsMinimalStage();
+    }
+
+    /**
+     * Completes this CompletableFuture with the result of
+     * the given Supplier function invoked from an asynchronous
+     * task using the given executor.
+     *
+     * @param supplier a function returning the value to be used
+     * to complete this CompletableFuture
+     * @param executor the executor to use for asynchronous execution
+     * @return this CompletableFuture
+     * @since 1.9
+     */
+    public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier,
+                                              Executor executor) {
+        if (supplier == null || executor == null)
+            throw new NullPointerException();
+        executor.execute(new AsyncSupply<T>(this, supplier));
+        return this;
+    }
+
+    /**
+     * Completes this CompletableFuture with the result of the given
+     * Supplier function invoked from an asynchronous task using the
+     * default executor.
+     *
+     * @param supplier a function returning the value to be used
+     * to complete this CompletableFuture
+     * @return this CompletableFuture
+     * @since 1.9
+     */
+    public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier) {
+        return completeAsync(supplier, defaultExecutor());
+    }
+
+    /**
+     * Exceptionally completes this CompletableFuture with
+     * a {@link TimeoutException} if not otherwise completed
+     * before the given timeout.
+     *
+     * @param timeout how long to wait before completing exceptionally
+     *        with a TimeoutException, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return this CompletableFuture
+     * @since 1.9
+     */
+    public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit) {
+        if (unit == null)
+            throw new NullPointerException();
+        if (result == null)
+            whenComplete(new Canceller(Delayer.delay(new Timeout(this),
+                                                     timeout, unit)));
+        return this;
+    }
+
+    /**
+     * Completes this CompletableFuture with the given value if not
+     * otherwise completed before the given timeout.
+     *
+     * @param value the value to use upon timeout
+     * @param timeout how long to wait before completing normally
+     *        with the given value, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return this CompletableFuture
+     * @since 1.9
+     */
+    public CompletableFuture<T> completeOnTimeout(T value, long timeout,
+                                                  TimeUnit unit) {
+        if (unit == null)
+            throw new NullPointerException();
+        if (result == null)
+            whenComplete(new Canceller(Delayer.delay(
+                                           new DelayedCompleter<T>(this, value),
+                                           timeout, unit)));
+        return this;
+    }
+
+    /**
+     * Returns a new Executor that submits a task to the given base
+     * executor after the given delay (or no delay if non-positive).
+     * Each delay commences upon invocation of the returned executor's
+     * {@code execute} method.
+     *
+     * @param delay how long to delay, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code delay} parameter
+     * @param executor the base executor
+     * @return the new delayed executor
+     * @since 1.9
+     */
+    public static Executor delayedExecutor(long delay, TimeUnit unit,
+                                           Executor executor) {
+        if (unit == null || executor == null)
+            throw new NullPointerException();
+        return new DelayedExecutor(delay, unit, executor);
+    }
+
+    /**
+     * Returns a new Executor that submits a task to the default
+     * executor after the given delay (or no delay if non-positive).
+     * Each delay commences upon invocation of the returned executor's
+     * {@code execute} method.
+     *
+     * @param delay how long to delay, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code delay} parameter
+     * @return the new delayed executor
+     * @since 1.9
+     */
+    public static Executor delayedExecutor(long delay, TimeUnit unit) {
+        if (unit == null)
+            throw new NullPointerException();
+        return new DelayedExecutor(delay, unit, ASYNC_POOL);
+    }
+
+    /**
+     * Returns a new CompletionStage that is already completed with
+     * the given value and supports only those methods in
+     * interface {@link CompletionStage}.
+     *
+     * @param value the value
+     * @param <U> the type of the value
+     * @return the completed CompletionStage
+     * @since 1.9
+     */
+    public static <U> CompletionStage<U> completedStage(U value) {
+        return new MinimalStage<U>((value == null) ? NIL : value);
+    }
+
+    /**
+     * Returns a new CompletableFuture that is already completed
+     * exceptionally with the given exception.
+     *
+     * @param ex the exception
+     * @param <U> the type of the value
+     * @return the exceptionally completed CompletableFuture
+     * @since 1.9
+     */
+    public static <U> CompletableFuture<U> failedFuture(Throwable ex) {
+        if (ex == null) throw new NullPointerException();
+        return new CompletableFuture<U>(new AltResult(ex));
+    }
+
+    /**
+     * Returns a new CompletionStage that is already completed
+     * exceptionally with the given exception and supports only those
+     * methods in interface {@link CompletionStage}.
+     *
+     * @param ex the exception
+     * @param <U> the type of the value
+     * @return the exceptionally completed CompletionStage
+     * @since 1.9
+     */
+    public static <U> CompletionStage<U> failedStage(Throwable ex) {
+        if (ex == null) throw new NullPointerException();
+        return new MinimalStage<U>(new AltResult(ex));
+    }
+
+    /**
+     * Singleton delay scheduler, used only for starting and
+     * cancelling tasks.
+     */
+    static final class Delayer {
+        static ScheduledFuture<?> delay(Runnable command, long delay,
+                                        TimeUnit unit) {
+            return delayer.schedule(command, delay, unit);
+        }
+
+        static final class DaemonThreadFactory implements ThreadFactory {
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(r);
+                t.setDaemon(true);
+                t.setName("CompletableFutureDelayScheduler");
+                return t;
+            }
+        }
+
+        static final ScheduledThreadPoolExecutor delayer;
+        static {
+            (delayer = new ScheduledThreadPoolExecutor(
+                1, new DaemonThreadFactory())).
+                setRemoveOnCancelPolicy(true);
+        }
+    }
+
+    // Little class-ified lambdas to better support monitoring
+
+    static final class DelayedExecutor implements Executor {
+        final long delay;
+        final TimeUnit unit;
+        final Executor executor;
+        DelayedExecutor(long delay, TimeUnit unit, Executor executor) {
+            this.delay = delay; this.unit = unit; this.executor = executor;
+        }
+        public void execute(Runnable r) {
+            Delayer.delay(new TaskSubmitter(executor, r), delay, unit);
+        }
+    }
+
+    /** Action to submit user task */
+    static final class TaskSubmitter implements Runnable {
+        final Executor executor;
+        final Runnable action;
+        TaskSubmitter(Executor executor, Runnable action) {
+            this.executor = executor;
+            this.action = action;
+        }
+        public void run() { executor.execute(action); }
+    }
+
+    /** Action to completeExceptionally on timeout */
+    static final class Timeout implements Runnable {
+        final CompletableFuture<?> f;
+        Timeout(CompletableFuture<?> f) { this.f = f; }
+        public void run() {
+            if (f != null && !f.isDone())
+                f.completeExceptionally(new TimeoutException());
+        }
+    }
+
+    /** Action to complete on timeout */
+    static final class DelayedCompleter<U> implements Runnable {
+        final CompletableFuture<U> f;
+        final U u;
+        DelayedCompleter(CompletableFuture<U> f, U u) { this.f = f; this.u = u; }
+        public void run() {
+            if (f != null)
+                f.complete(u);
+        }
+    }
+
+    /** Action to cancel unneeded timeouts */
+    static final class Canceller implements BiConsumer<Object, Throwable> {
+        final Future<?> f;
+        Canceller(Future<?> f) { this.f = f; }
+        public void accept(Object ignore, Throwable ex) {
+            if (ex == null && f != null && !f.isDone())
+                f.cancel(false);
+        }
+    }
+
+    /**
+     * A subclass that just throws UOE for most non-CompletionStage methods.
+     */
+    static final class MinimalStage<T> extends CompletableFuture<T> {
+        MinimalStage() { }
+        MinimalStage(Object r) { super(r); }
+        @Override public <U> CompletableFuture<U> newIncompleteFuture() {
+            return new MinimalStage<U>(); }
+        @Override public T get() {
+            throw new UnsupportedOperationException(); }
+        @Override public T get(long timeout, TimeUnit unit) {
+            throw new UnsupportedOperationException(); }
+        @Override public T getNow(T valueIfAbsent) {
+            throw new UnsupportedOperationException(); }
+        @Override public T join() {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean complete(T value) {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean completeExceptionally(Throwable ex) {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean cancel(boolean mayInterruptIfRunning) {
+            throw new UnsupportedOperationException(); }
+        @Override public void obtrudeValue(T value) {
+            throw new UnsupportedOperationException(); }
+        @Override public void obtrudeException(Throwable ex) {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean isDone() {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean isCancelled() {
+            throw new UnsupportedOperationException(); }
+        @Override public boolean isCompletedExceptionally() {
+            throw new UnsupportedOperationException(); }
+        @Override public int getNumberOfDependents() {
+            throw new UnsupportedOperationException(); }
+        @Override public CompletableFuture<T> completeAsync
+            (Supplier<? extends T> supplier, Executor executor) {
+            throw new UnsupportedOperationException(); }
+        @Override public CompletableFuture<T> completeAsync
+            (Supplier<? extends T> supplier) {
+            throw new UnsupportedOperationException(); }
+        @Override public CompletableFuture<T> orTimeout
+            (long timeout, TimeUnit unit) {
+            throw new UnsupportedOperationException(); }
+        @Override public CompletableFuture<T> completeOnTimeout
+            (T value, long timeout, TimeUnit unit) {
+            throw new UnsupportedOperationException(); }
+    }
+
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long RESULT;
     private static final long STACK;
     private static final long NEXT;
     static {
         try {
-            final sun.misc.Unsafe u;
-            UNSAFE = u = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = CompletableFuture.class;
-            RESULT = u.objectFieldOffset(k.getDeclaredField("result"));
-            STACK = u.objectFieldOffset(k.getDeclaredField("stack"));
-            NEXT = u.objectFieldOffset
+            RESULT = U.objectFieldOffset
+                (CompletableFuture.class.getDeclaredField("result"));
+            STACK = U.objectFieldOffset
+                (CompletableFuture.class.getDeclaredField("stack"));
+            NEXT = U.objectFieldOffset
                 (Completion.class.getDeclaredField("next"));
-        } catch (Exception x) {
-            throw new Error(x);
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
         }
+
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,12 +34,11 @@
  */
 
 package java.util.concurrent;
-import java.util.function.Supplier;
-import java.util.function.Consumer;
+
 import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
 import java.util.function.Function;
-import java.util.function.BiFunction;
-import java.util.concurrent.Executor;
 
 /**
  * A stage of a possibly asynchronous computation, that performs an
@@ -56,9 +55,9 @@
  * For example, {@code stage.thenApply(x -> square(x)).thenAccept(x ->
  * System.out.print(x)).thenRun(() -> System.out.println())}. An
  * additional form (<em>compose</em>) applies functions of stages
- * themselves, rather than their results. </li>
+ * themselves, rather than their results.
  *
- * <li> One stage's execution may be triggered by completion of a
+ * <li>One stage's execution may be triggered by completion of a
  * single stage, or both of two stages, or either of two stages.
  * Dependencies on a single stage are arranged using methods with
  * prefix <em>then</em>. Those triggered by completion of
@@ -66,9 +65,9 @@
  * effects, using correspondingly named methods. Those triggered by
  * <em>either</em> of two stages make no guarantees about which of the
  * results or effects are used for the dependent stage's
- * computation.</li>
+ * computation.
  *
- * <li> Dependencies among stages control the triggering of
+ * <li>Dependencies among stages control the triggering of
  * computations, but do not otherwise guarantee any particular
  * ordering. Additionally, execution of a new stage's computations may
  * be arranged in any of three ways: default execution, default
@@ -81,7 +80,7 @@
  * properties, and might not even support concurrent execution, but
  * are arranged for processing in a way that accommodates asynchrony.
  *
- * <li> Two method forms support processing whether the triggering
+ * <li>Two method forms support processing whether the triggering
  * stage completed normally or exceptionally: Method {@link
  * #whenComplete whenComplete} allows injection of an action
  * regardless of outcome, otherwise preserving the outcome in its
@@ -100,7 +99,7 @@
  * stage completes normally or exceptionally. In the case of method
  * {@code whenComplete}, when the supplied action itself encounters an
  * exception, then the stage exceptionally completes with this
- * exception if not already completed exceptionally.</li>
+ * exception if not already completed exceptionally.
  *
  * </ul>
  *
@@ -587,7 +586,7 @@
 
     /**
      * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed with this stage as the argument
+     * normally, is executed with this stage's result as the argument
      * to the supplied function.
      *
      * See the {@link CompletionStage} documentation for rules
@@ -603,7 +602,7 @@
     /**
      * Returns a new CompletionStage that, when this stage completes
      * normally, is executed using this stage's default asynchronous
-     * execution facility, with this stage as the argument to the
+     * execution facility, with this stage's result as the argument to the
      * supplied function.
      *
      * See the {@link CompletionStage} documentation for rules
@@ -652,12 +651,14 @@
      * Returns a new CompletionStage with the same result or exception as
      * this stage, that executes the given action when this stage completes.
      *
-     * <p>When this stage is complete, the given action is invoked with the
-     * result (or {@code null} if none) and the exception (or {@code null}
-     * if none) of this stage as arguments.  The returned stage is completed
-     * when the action returns.  If the supplied action itself encounters an
-     * exception, then the returned stage exceptionally completes with this
-     * exception unless this stage also completed exceptionally.
+     * <p>When this stage is complete, the given action is invoked
+     * with the result (or {@code null} if none) and the exception (or
+     * {@code null} if none) of this stage as arguments.  The returned
+     * stage is completed when the action returns.  If the supplied
+     * action itself encounters an exception, then the returned stage
+     * exceptionally completes with this exception unless this stage
+     * also completed exceptionally (in which case, the returned stage
+     * exceptionally completes with the original exception).
      *
      * @param action the action to perform
      * @return the new CompletionStage
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -42,7 +42,6 @@
 import java.util.AbstractMap;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -51,14 +50,11 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.Spliterator;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
 import java.util.function.Consumer;
 import java.util.function.DoubleBinaryOperator;
 import java.util.function.Function;
@@ -154,43 +150,43 @@
  * being concurrently updated by other threads; for example, when
  * computing a snapshot summary of the values in a shared registry.
  * There are three kinds of operation, each with four forms, accepting
- * functions with Keys, Values, Entries, and (Key, Value) arguments
- * and/or return values. Because the elements of a ConcurrentHashMap
- * are not ordered in any particular way, and may be processed in
- * different orders in different parallel executions, the correctness
- * of supplied functions should not depend on any ordering, or on any
- * other objects or values that may transiently change while
- * computation is in progress; and except for forEach actions, should
- * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry}
- * objects do not support method {@code setValue}.
+ * functions with keys, values, entries, and (key, value) pairs as
+ * arguments and/or return values. Because the elements of a
+ * ConcurrentHashMap are not ordered in any particular way, and may be
+ * processed in different orders in different parallel executions, the
+ * correctness of supplied functions should not depend on any
+ * ordering, or on any other objects or values that may transiently
+ * change while computation is in progress; and except for forEach
+ * actions, should ideally be side-effect-free. Bulk operations on
+ * {@link java.util.Map.Entry} objects do not support method {@code
+ * setValue}.
  *
  * <ul>
- * <li> forEach: Perform a given action on each element.
+ * <li>forEach: Performs a given action on each element.
  * A variant form applies a given transformation on each element
- * before performing the action.</li>
+ * before performing the action.
  *
- * <li> search: Return the first available non-null result of
+ * <li>search: Returns the first available non-null result of
  * applying a given function on each element; skipping further
- * search when a result is found.</li>
+ * search when a result is found.
  *
- * <li> reduce: Accumulate each element.  The supplied reduction
+ * <li>reduce: Accumulates each element.  The supplied reduction
  * function cannot rely on ordering (more formally, it should be
  * both associative and commutative).  There are five variants:
  *
  * <ul>
  *
- * <li> Plain reductions. (There is not a form of this method for
+ * <li>Plain reductions. (There is not a form of this method for
  * (key, value) function arguments since there is no corresponding
- * return type.)</li>
+ * return type.)
  *
- * <li> Mapped reductions that accumulate the results of a given
- * function applied to each element.</li>
+ * <li>Mapped reductions that accumulate the results of a given
+ * function applied to each element.
  *
- * <li> Reductions to scalar doubles, longs, and ints, using a
- * given basis value.</li>
+ * <li>Reductions to scalar doubles, longs, and ints, using a
+ * given basis value.
  *
  * </ul>
- * </li>
  * </ul>
  *
  * <p>These bulk operations accept a {@code parallelismThreshold}
@@ -576,7 +572,7 @@
      * The number of bits used for generation stamp in sizeCtl.
      * Must be at least 6 for 32bit arrays.
      */
-    private static int RESIZE_STAMP_BITS = 16;
+    private static final int RESIZE_STAMP_BITS = 16;
 
     /**
      * The maximum number of threads that can help resize.
@@ -604,7 +600,7 @@
     private static final ObjectStreamField[] serialPersistentFields = {
         new ObjectStreamField("segments", Segment[].class),
         new ObjectStreamField("segmentMask", Integer.TYPE),
-        new ObjectStreamField("segmentShift", Integer.TYPE)
+        new ObjectStreamField("segmentShift", Integer.TYPE),
     };
 
     /* ---------------- Nodes -------------- */
@@ -630,10 +626,12 @@
             this.next = next;
         }
 
-        public final K getKey()       { return key; }
-        public final V getValue()     { return val; }
-        public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
-        public final String toString(){ return key + "=" + val; }
+        public final K getKey()     { return key; }
+        public final V getValue()   { return val; }
+        public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
+        public final String toString() {
+            return Helpers.mapEntryToString(key, val);
+        }
         public final V setValue(V value) {
             throw new UnsupportedOperationException();
         }
@@ -1057,6 +1055,8 @@
                                     p.val = value;
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0) {
@@ -1159,6 +1159,8 @@
                                 }
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (validated) {
@@ -1366,7 +1368,7 @@
 
     /**
      * Stripped-down version of helper class used in previous version,
-     * declared for the sake of serialization compatibility
+     * declared for the sake of serialization compatibility.
      */
     static class Segment<K,V> extends ReentrantLock implements Serializable {
         private static final long serialVersionUID = 2249069246763182397L;
@@ -1401,9 +1403,10 @@
             new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
         for (int i = 0; i < segments.length; ++i)
             segments[i] = new Segment<K,V>(LOAD_FACTOR);
-        s.putFields().put("segments", segments);
-        s.putFields().put("segmentShift", segmentShift);
-        s.putFields().put("segmentMask", segmentMask);
+        java.io.ObjectOutputStream.PutField streamFields = s.putFields();
+        streamFields.put("segments", segments);
+        streamFields.put("segmentShift", segmentShift);
+        streamFields.put("segmentMask", segmentMask);
         s.writeFields();
 
         Node<K,V>[] t;
@@ -1620,9 +1623,9 @@
     }
 
     /**
-     * Helper method for EntrySet.removeIf
+     * Helper method for EntrySetView.removeIf.
      */
-    boolean removeEntryIf(Predicate<? super Entry<K, V>> function) {
+    boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
         if (function == null) throw new NullPointerException();
         Node<K,V>[] t;
         boolean removed = false;
@@ -1640,9 +1643,9 @@
     }
 
     /**
-     * Helper method for Values.removeIf
+     * Helper method for ValuesView.removeIf.
      */
-    boolean removeValueIf(Predicate<? super  V> function) {
+    boolean removeValueIf(Predicate<? super V> function) {
         if (function == null) throw new NullPointerException();
         Node<K,V>[] t;
         boolean removed = false;
@@ -1716,7 +1719,7 @@
                         if (fh >= 0) {
                             binCount = 1;
                             for (Node<K,V> e = f;; ++binCount) {
-                                K ek; V ev;
+                                K ek;
                                 if (e.hash == h &&
                                     ((ek = e.key) == key ||
                                      (ek != null && key.equals(ek)))) {
@@ -1726,6 +1729,8 @@
                                 Node<K,V> pred = e;
                                 if ((e = e.next) == null) {
                                     if ((val = mappingFunction.apply(key)) != null) {
+                                        if (pred.next != null)
+                                            throw new IllegalStateException("Recursive update");
                                         added = true;
                                         pred.next = new Node<K,V>(h, key, val, null);
                                     }
@@ -1745,6 +1750,8 @@
                                 t.putTreeVal(h, key, val);
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0) {
@@ -1840,6 +1847,8 @@
                                 }
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0)
@@ -1931,6 +1940,8 @@
                                 if ((e = e.next) == null) {
                                     val = remappingFunction.apply(key, null);
                                     if (val != null) {
+                                        if (pred.next != null)
+                                            throw new IllegalStateException("Recursive update");
                                         delta = 1;
                                         pred.next =
                                             new Node<K,V>(h, key, val, null);
@@ -1963,6 +1974,8 @@
                                     setTabAt(tab, i, untreeify(t.first));
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0) {
@@ -2072,6 +2085,8 @@
                                     setTabAt(tab, i, untreeify(t.first));
                             }
                         }
+                        else if (f instanceof ReservationNode)
+                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0) {
@@ -2089,12 +2104,13 @@
     // Hashtable legacy methods
 
     /**
-     * Legacy method testing if some key maps into the specified value
-     * in this table.  This method is identical in functionality to
+     * Tests if some key maps into the specified value in this table.
+     *
+     * <p>Note that this method is identical in functionality to
      * {@link #containsValue(Object)}, and exists solely to ensure
      * full compatibility with class {@link java.util.Hashtable},
      * which supported this method prior to introduction of the
-     * Java Collections framework.
+     * Java Collections Framework.
      *
      * @param  value a value to search for
      * @return {@code true} if and only if some key maps to the
@@ -2235,7 +2251,7 @@
     }
 
     /**
-     * A place-holder node used in computeIfAbsent and compute
+     * A place-holder node used in computeIfAbsent and compute.
      */
     static final class ReservationNode<K,V> extends Node<K,V> {
         ReservationNode() {
@@ -2384,17 +2400,8 @@
                 break;
             else if (tab == table) {
                 int rs = resizeStamp(n);
-                if (sc < 0) {
-                    Node<K,V>[] nt;
-                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
-                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
-                        transferIndex <= 0)
-                        break;
-                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
-                        transfer(tab, nt);
-                }
-                else if (U.compareAndSwapInt(this, SIZECTL, sc,
-                                             (rs << RESIZE_STAMP_SHIFT) + 2))
+                if (U.compareAndSwapInt(this, SIZECTL, sc,
+                                        (rs << RESIZE_STAMP_SHIFT) + 2))
                     transfer(tab, null);
             }
         }
@@ -2649,7 +2656,7 @@
      * too small, in which case resizes instead.
      */
     private final void treeifyBin(Node<K,V>[] tab, int index) {
-        Node<K,V> b; int n, sc;
+        Node<K,V> b; int n;
         if (tab != null) {
             if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
                 tryPresize(n << 1);
@@ -2693,7 +2700,7 @@
     /* ---------------- TreeNodes -------------- */
 
     /**
-     * Nodes for use in TreeBins
+     * Nodes for use in TreeBins.
      */
     static final class TreeNode<K,V> extends Node<K,V> {
         TreeNode<K,V> parent;  // red-black tree links
@@ -2719,7 +2726,7 @@
         final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) {
             if (k != null) {
                 TreeNode<K,V> p = this;
-                do  {
+                do {
                     int ph, dir; K pk; TreeNode<K,V> q;
                     TreeNode<K,V> pl = p.left, pr = p.right;
                     if ((ph = p.hash) > h)
@@ -2812,7 +2819,7 @@
                                   (kc = comparableClassFor(k)) == null) ||
                                  (dir = compareComparables(kc, k, pk)) == 0)
                             dir = tieBreakOrder(k, pk);
-                            TreeNode<K,V> xp = p;
+                        TreeNode<K,V> xp = p;
                         if ((p = (dir <= 0) ? p.left : p.right) == null) {
                             x.parent = xp;
                             if (dir <= 0)
@@ -3165,7 +3172,7 @@
 
         static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
                                                    TreeNode<K,V> x) {
-            for (TreeNode<K,V> xp, xpl, xpr;;)  {
+            for (TreeNode<K,V> xp, xpl, xpr;;) {
                 if (x == null || x == root)
                     return root;
                 else if ((xp = x.parent) == null) {
@@ -3256,7 +3263,7 @@
         }
 
         /**
-         * Recursive invariant check
+         * Checks invariants recursively for the tree of Nodes rooted at t.
          */
         static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
             TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
@@ -3280,15 +3287,13 @@
             return true;
         }
 
-        private static final sun.misc.Unsafe U;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
         private static final long LOCKSTATE;
         static {
             try {
-                U = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = TreeBin.class;
                 LOCKSTATE = U.objectFieldOffset
-                    (k.getDeclaredField("lockState"));
-            } catch (Exception e) {
+                    (TreeBin.class.getDeclaredField("lockState"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -3503,7 +3508,7 @@
     }
 
     /**
-     * Exported Entry for EntryIterator
+     * Exported Entry for EntryIterator.
      */
     static final class MapEntry<K,V> implements Map.Entry<K,V> {
         final K key; // non-null
@@ -3517,7 +3522,9 @@
         public K getKey()        { return key; }
         public V getValue()      { return val; }
         public int hashCode()    { return key.hashCode() ^ val.hashCode(); }
-        public String toString() { return key + "=" + val; }
+        public String toString() {
+            return Helpers.mapEntryToString(key, val);
+        }
 
         public boolean equals(Object o) {
             Object k, v; Map.Entry<?,?> e;
@@ -3554,7 +3561,7 @@
             this.est = est;
         }
 
-        public Spliterator<K> trySplit() {
+        public KeySpliterator<K,V> trySplit() {
             int i, f, h;
             return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
                 new KeySpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -3593,7 +3600,7 @@
             this.est = est;
         }
 
-        public Spliterator<V> trySplit() {
+        public ValueSpliterator<K,V> trySplit() {
             int i, f, h;
             return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
                 new ValueSpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -3633,7 +3640,7 @@
             this.est = est;
         }
 
-        public Spliterator<Map.Entry<K,V>> trySplit() {
+        public EntrySpliterator<K,V> trySplit() {
             int i, f, h;
             return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
                 new EntrySpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -4445,19 +4452,19 @@
         public abstract boolean contains(Object o);
         public abstract boolean remove(Object o);
 
-        private static final String oomeMsg = "Required array size too large";
+        private static final String OOME_MSG = "Required array size too large";
 
         public final Object[] toArray() {
             long sz = map.mappingCount();
             if (sz > MAX_ARRAY_SIZE)
-                throw new OutOfMemoryError(oomeMsg);
+                throw new OutOfMemoryError(OOME_MSG);
             int n = (int)sz;
             Object[] r = new Object[n];
             int i = 0;
             for (E e : this) {
                 if (i == n) {
                     if (n >= MAX_ARRAY_SIZE)
-                        throw new OutOfMemoryError(oomeMsg);
+                        throw new OutOfMemoryError(OOME_MSG);
                     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
                         n = MAX_ARRAY_SIZE;
                     else
@@ -4473,7 +4480,7 @@
         public final <T> T[] toArray(T[] a) {
             long sz = map.mappingCount();
             if (sz > MAX_ARRAY_SIZE)
-                throw new OutOfMemoryError(oomeMsg);
+                throw new OutOfMemoryError(OOME_MSG);
             int m = (int)sz;
             T[] r = (a.length >= m) ? a :
                 (T[])java.lang.reflect.Array
@@ -4483,7 +4490,7 @@
             for (E e : this) {
                 if (i == n) {
                     if (n >= MAX_ARRAY_SIZE)
-                        throw new OutOfMemoryError(oomeMsg);
+                        throw new OutOfMemoryError(OOME_MSG);
                     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
                         n = MAX_ARRAY_SIZE;
                     else
@@ -4803,7 +4810,7 @@
             return added;
         }
 
-        public boolean removeIf(Predicate<? super Entry<K, V>> filter) {
+        public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
             return map.removeEntryIf(filter);
         }
 
@@ -4878,7 +4885,7 @@
         }
 
         /**
-         * Same as Traverser version
+         * Same as Traverser version.
          */
         final Node<K,V> advance() {
             Node<K,V> e;
@@ -6323,38 +6330,40 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
     private static final long CELLSBUSY;
     private static final long CELLVALUE;
-    private static final long ABASE;
+    private static final int ABASE;
     private static final int ASHIFT;
 
     static {
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ConcurrentHashMap.class;
             SIZECTL = U.objectFieldOffset
-                (k.getDeclaredField("sizeCtl"));
+                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
             TRANSFERINDEX = U.objectFieldOffset
-                (k.getDeclaredField("transferIndex"));
+                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
             BASECOUNT = U.objectFieldOffset
-                (k.getDeclaredField("baseCount"));
+                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
             CELLSBUSY = U.objectFieldOffset
-                (k.getDeclaredField("cellsBusy"));
-            Class<?> ck = CounterCell.class;
+                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
+
             CELLVALUE = U.objectFieldOffset
-                (ck.getDeclaredField("value"));
-            Class<?> ak = Node[].class;
-            ABASE = U.arrayBaseOffset(ak);
-            int scale = U.arrayIndexScale(ak);
+                (CounterCell.class.getDeclaredField("value"));
+
+            ABASE = U.arrayBaseOffset(Node[].class);
+            int scale = U.arrayIndexScale(Node[].class);
             if ((scale & (scale - 1)) != 0)
-                throw new Error("data type scale not a power of two");
+                throw new Error("array index scale not a power of two");
             ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (Exception e) {
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
+
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,11 +36,12 @@
 package java.util.concurrent;
 
 import java.util.AbstractCollection;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Queue;
 import java.util.Spliterator;
 import java.util.Spliterators;
@@ -87,7 +88,7 @@
  * @since 1.7
  * @author Doug Lea
  * @author Martin Buchholz
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
  */
 public class ConcurrentLinkedDeque<E>
     extends AbstractCollection<E>
@@ -300,47 +301,45 @@
          * only be seen after publication via casNext or casPrev.
          */
         Node(E item) {
-            UNSAFE.putObject(this, itemOffset, item);
+            U.putObject(this, ITEM, item);
         }
 
         boolean casItem(E cmp, E val) {
-            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+            return U.compareAndSwapObject(this, ITEM, cmp, val);
         }
 
         void lazySetNext(Node<E> val) {
-            UNSAFE.putOrderedObject(this, nextOffset, val);
+            U.putOrderedObject(this, NEXT, val);
         }
 
         boolean casNext(Node<E> cmp, Node<E> val) {
-            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+            return U.compareAndSwapObject(this, NEXT, cmp, val);
         }
 
         void lazySetPrev(Node<E> val) {
-            UNSAFE.putOrderedObject(this, prevOffset, val);
+            U.putOrderedObject(this, PREV, val);
         }
 
         boolean casPrev(Node<E> cmp, Node<E> val) {
-            return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
+            return U.compareAndSwapObject(this, PREV, cmp, val);
         }
 
         // Unsafe mechanics
 
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long prevOffset;
-        private static final long itemOffset;
-        private static final long nextOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long PREV;
+        private static final long ITEM;
+        private static final long NEXT;
 
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = Node.class;
-                prevOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("prev"));
-                itemOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("item"));
-                nextOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("next"));
-            } catch (Exception e) {
+                PREV = U.objectFieldOffset
+                    (Node.class.getDeclaredField("prev"));
+                ITEM = U.objectFieldOffset
+                    (Node.class.getDeclaredField("item"));
+                NEXT = U.objectFieldOffset
+                    (Node.class.getDeclaredField("next"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -350,8 +349,7 @@
      * Links e as first element.
      */
     private void linkFirst(E e) {
-        checkNotNull(e);
-        final Node<E> newNode = new Node<E>(e);
+        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
 
         restartFromHead:
         for (;;)
@@ -383,8 +381,7 @@
      * Links e as last element.
      */
     private void linkLast(E e) {
-        checkNotNull(e);
-        final Node<E> newNode = new Node<E>(e);
+        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
 
         restartFromTail:
         for (;;)
@@ -789,16 +786,6 @@
     // Minor convenience utilities
 
     /**
-     * Throws NullPointerException if argument is null.
-     *
-     * @param v the element
-     */
-    private static void checkNotNull(Object v) {
-        if (v == null)
-            throw new NullPointerException();
-    }
-
-    /**
      * Returns element unless it is null, in which case throws
      * NoSuchElementException.
      *
@@ -812,22 +799,6 @@
     }
 
     /**
-     * Creates an array list and fills it with elements of this list.
-     * Used by toArray.
-     *
-     * @return the array list
-     */
-    private ArrayList<E> toArrayList() {
-        ArrayList<E> list = new ArrayList<E>();
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null)
-                list.add(item);
-        }
-        return list;
-    }
-
-    /**
      * Constructs an empty deque.
      */
     public ConcurrentLinkedDeque() {
@@ -847,8 +818,7 @@
         // Copy c into a private chain of Nodes
         Node<E> h = null, t = null;
         for (E e : c) {
-            checkNotNull(e);
-            Node<E> newNode = new Node<E>(e);
+            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
             else {
@@ -1046,16 +1016,19 @@
     public void push(E e)     { addFirst(e); }
 
     /**
-     * Removes the first element {@code e} such that
-     * {@code o.equals(e)}, if such an element exists in this deque.
+     * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
+     * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
      * @return {@code true} if the deque contained the specified element
      * @throws NullPointerException if the specified element is null
      */
     public boolean removeFirstOccurrence(Object o) {
-        checkNotNull(o);
+        Objects.requireNonNull(o);
         for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.item;
             if (item != null && o.equals(item) && p.casItem(item, null)) {
@@ -1067,16 +1040,19 @@
     }
 
     /**
-     * Removes the last element {@code e} such that
-     * {@code o.equals(e)}, if such an element exists in this deque.
+     * Removes the last occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
+     * More formally, removes the last element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
+     * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
      * @return {@code true} if the deque contained the specified element
      * @throws NullPointerException if the specified element is null
      */
     public boolean removeLastOccurrence(Object o) {
-        checkNotNull(o);
+        Objects.requireNonNull(o);
         for (Node<E> p = last(); p != null; p = pred(p)) {
             E item = p.item;
             if (item != null && o.equals(item) && p.casItem(item, null)) {
@@ -1088,18 +1064,20 @@
     }
 
     /**
-     * Returns {@code true} if this deque contains at least one
-     * element {@code e} such that {@code o.equals(e)}.
+     * Returns {@code true} if this deque contains the specified element.
+     * More formally, returns {@code true} if and only if this deque contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o element whose presence in this deque is to be tested
      * @return {@code true} if this deque contains the specified element
      */
     public boolean contains(Object o) {
-        if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null && o.equals(item))
-                return true;
+        if (o != null) {
+            for (Node<E> p = first(); p != null; p = succ(p)) {
+                E item = p.item;
+                if (item != null && o.equals(item))
+                    return true;
+            }
         }
         return false;
     }
@@ -1130,19 +1108,28 @@
      * @return the number of elements in this deque
      */
     public int size() {
-        int count = 0;
-        for (Node<E> p = first(); p != null; p = succ(p))
-            if (p.item != null)
-                // Collection.size() spec says to max out
-                if (++count == Integer.MAX_VALUE)
-                    break;
-        return count;
+        restartFromHead: for (;;) {
+            int count = 0;
+            for (Node<E> p = first(); p != null;) {
+                if (p.item != null)
+                    if (++count == Integer.MAX_VALUE)
+                        break;  // @see Collection.size()
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            return count;
+        }
     }
 
     /**
-     * Removes the first element {@code e} such that
-     * {@code o.equals(e)}, if such an element exists in this deque.
+     * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
+     * (or equivalently, if this deque changed as a result of the call).
+     *
+     * <p>This method is equivalent to {@link #removeFirstOccurrence(Object)}.
      *
      * @param o element to be removed from this deque, if present
      * @return {@code true} if the deque contained the specified element
@@ -1172,8 +1159,7 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            checkNotNull(e);
-            Node<E> newNode = new Node<E>(e);
+            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
@@ -1224,6 +1210,62 @@
             ;
     }
 
+    public String toString() {
+        String[] a = null;
+        restartFromHead: for (;;) {
+            int charLength = 0;
+            int size = 0;
+            for (Node<E> p = first(); p != null;) {
+                E item = p.item;
+                if (item != null) {
+                    if (a == null)
+                        a = new String[4];
+                    else if (size == a.length)
+                        a = Arrays.copyOf(a, 2 * size);
+                    String s = item.toString();
+                    a[size++] = s;
+                    charLength += s.length();
+                }
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+
+            if (size == 0)
+                return "[]";
+
+            return Helpers.toString(a, size, charLength);
+        }
+    }
+
+    private Object[] toArrayInternal(Object[] a) {
+        Object[] x = a;
+        restartFromHead: for (;;) {
+            int size = 0;
+            for (Node<E> p = first(); p != null;) {
+                E item = p.item;
+                if (item != null) {
+                    if (x == null)
+                        x = new Object[4];
+                    else if (size == x.length)
+                        x = Arrays.copyOf(x, 2 * (size + 4));
+                    x[size++] = item;
+                }
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            if (x == null)
+                return new Object[0];
+            else if (a != null && size <= a.length) {
+                if (a != x)
+                    System.arraycopy(x, 0, a, 0, size);
+                if (size < a.length)
+                    a[size] = null;
+                return a;
+            }
+            return (size == x.length) ? x : Arrays.copyOf(x, size);
+        }
+    }
+
     /**
      * Returns an array containing all of the elements in this deque, in
      * proper sequence (from first to last element).
@@ -1238,7 +1280,7 @@
      * @return an array containing all of the elements in this deque
      */
     public Object[] toArray() {
-        return toArrayList().toArray();
+        return toArrayInternal(null);
     }
 
     /**
@@ -1264,7 +1306,7 @@
      * The following code can be used to dump the deque into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -1278,8 +1320,10 @@
      *         this deque
      * @throws NullPointerException if the specified array is null
      */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        return toArrayList().toArray(a);
+        if (a == null) throw new NullPointerException();
+        return (T[]) toArrayInternal(a);
     }
 
     /**
@@ -1346,7 +1390,7 @@
             Node<E> p = (nextNode == null) ? startNode() : nextNode(nextNode);
             for (;; p = nextNode(p)) {
                 if (p == null) {
-                    // p might be active end or TERMINATOR node; both are OK
+                    // might be at active end or TERMINATOR node; both are OK
                     nextNode = null;
                     nextItem = null;
                     break;
@@ -1426,8 +1470,9 @@
                     if (i > 0) {
                         batch = i;
                         return Spliterators.spliterator
-                            (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                             Spliterator.CONCURRENT);
+                            (a, 0, i, (Spliterator.ORDERED |
+                                       Spliterator.NONNULL |
+                                       Spliterator.CONCURRENT));
                     }
                 }
             }
@@ -1539,8 +1584,7 @@
 
         // Read in elements until trailing null sentinel found
         Node<E> h = null, t = null;
-        Object item;
-        while ((item = s.readObject()) != null) {
+        for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
             Node<E> newNode = new Node<E>((E) item);
             if (h == null)
@@ -1555,31 +1599,29 @@
     }
 
     private boolean casHead(Node<E> cmp, Node<E> val) {
-        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+        return U.compareAndSwapObject(this, HEAD, cmp, val);
     }
 
     private boolean casTail(Node<E> cmp, Node<E> val) {
-        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+        return U.compareAndSwapObject(this, TAIL, cmp, val);
     }
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long headOffset;
-    private static final long tailOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long HEAD;
+    private static final long TAIL;
     static {
         PREV_TERMINATOR = new Node<Object>();
         PREV_TERMINATOR.next = PREV_TERMINATOR;
         NEXT_TERMINATOR = new Node<Object>();
         NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ConcurrentLinkedDeque.class;
-            headOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("head"));
-            tailOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("tail"));
-        } catch (Exception e) {
+            HEAD = U.objectFieldOffset
+                (ConcurrentLinkedDeque.class.getDeclaredField("head"));
+            TAIL = U.objectFieldOffset
+                (ConcurrentLinkedDeque.class.getDeclaredField("tail"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,10 +36,11 @@
 package java.util.concurrent;
 
 import java.util.AbstractQueue;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Queue;
 import java.util.Spliterator;
 import java.util.Spliterators;
@@ -60,9 +61,9 @@
  * does not permit the use of {@code null} elements.
  *
  * <p>This implementation employs an efficient <em>non-blocking</em>
- * algorithm based on one described in <a
- * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
- * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
+ * algorithm based on one described in
+ * <a href="http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf">
+ * Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue
  * Algorithms</a> by Maged M. Michael and Michael L. Scott.
  *
  * <p>Iterators are <i>weakly consistent</i>, returning elements
@@ -100,7 +101,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
         implements Queue<E>, java.io.Serializable {
@@ -180,45 +181,28 @@
     private static class Node<E> {
         volatile E item;
         volatile Node<E> next;
-
-        /**
-         * Constructs a new node.  Uses relaxed write because item can
-         * only be seen after publication via casNext.
-         */
-        Node(E item) {
-            UNSAFE.putObject(this, itemOffset, item);
-        }
-
-        boolean casItem(E cmp, E val) {
-            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
-        }
-
-        void lazySetNext(Node<E> val) {
-            UNSAFE.putOrderedObject(this, nextOffset, val);
-        }
+    }
 
-        boolean casNext(Node<E> cmp, Node<E> val) {
-            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
-        }
-
-        // Unsafe mechanics
-
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long itemOffset;
-        private static final long nextOffset;
+    /**
+     * Returns a new node holding item.  Uses relaxed write because item
+     * can only be seen after piggy-backing publication via casNext.
+     */
+    static <E> Node<E> newNode(E item) {
+        Node<E> node = new Node<E>();
+        U.putObject(node, ITEM, item);
+        return node;
+    }
 
-        static {
-            try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = Node.class;
-                itemOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("item"));
-                nextOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("next"));
-            } catch (Exception e) {
-                throw new Error(e);
-            }
-        }
+    static <E> boolean casItem(Node<E> node, E cmp, E val) {
+        return U.compareAndSwapObject(node, ITEM, cmp, val);
+    }
+
+    static <E> void lazySetNext(Node<E> node, Node<E> val) {
+        U.putOrderedObject(node, NEXT, val);
+    }
+
+    static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
+        return U.compareAndSwapObject(node, NEXT, cmp, val);
     }
 
     /**
@@ -233,7 +217,7 @@
      * - it is permitted for tail to lag behind head, that is, for tail
      *   to not be reachable from head!
      */
-    private transient volatile Node<E> head;
+    transient volatile Node<E> head;
 
     /**
      * A node from which the last node on list (that is, the unique
@@ -253,7 +237,7 @@
      * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
     public ConcurrentLinkedQueue() {
-        head = tail = new Node<E>(null);
+        head = tail = newNode(null);
     }
 
     /**
@@ -268,17 +252,16 @@
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
         Node<E> h = null, t = null;
         for (E e : c) {
-            checkNotNull(e);
-            Node<E> newNode = new Node<E>(e);
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
+                lazySetNext(t, newNode);
                 t = newNode;
             }
         }
         if (h == null)
-            h = t = new Node<E>(null);
+            h = t = newNode(null);
         head = h;
         tail = t;
     }
@@ -302,8 +285,9 @@
      * as sentinel for succ(), below.
      */
     final void updateHead(Node<E> h, Node<E> p) {
+        // assert h != null && p != null && (h == p || h.item == null);
         if (h != p && casHead(h, p))
-            h.lazySetNext(h);
+            lazySetNext(h, h);
     }
 
     /**
@@ -324,14 +308,13 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        checkNotNull(e);
-        final Node<E> newNode = new Node<E>(e);
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         for (Node<E> t = tail, p = t;;) {
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (p.casNext(null, newNode)) {
+                if (casNext(p, null, newNode)) {
                     // Successful CAS is the linearization point
                     // for e to become an element of this queue,
                     // and for newNode to become "live".
@@ -359,7 +342,7 @@
             for (Node<E> h = head, p = h, q;;) {
                 E item = p.item;
 
-                if (item != null && p.casItem(item, null)) {
+                if (item != null && casItem(p, item, null)) {
                     // Successful CAS is the linearization point
                     // for item to be removed from this queue.
                     if (p != h) // hop two nodes at a time
@@ -446,13 +429,17 @@
      * @return the number of elements in this queue
      */
     public int size() {
-        int count = 0;
-        for (Node<E> p = first(); p != null; p = succ(p))
-            if (p.item != null)
-                // Collection.size() spec says to max out
-                if (++count == Integer.MAX_VALUE)
-                    break;
-        return count;
+        restartFromHead: for (;;) {
+            int count = 0;
+            for (Node<E> p = first(); p != null;) {
+                if (p.item != null)
+                    if (++count == Integer.MAX_VALUE)
+                        break;  // @see Collection.size()
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            return count;
+        }
     }
 
     /**
@@ -464,11 +451,12 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null && o.equals(item))
-                return true;
+        if (o != null) {
+            for (Node<E> p = first(); p != null; p = succ(p)) {
+                E item = p.item;
+                if (item != null && o.equals(item))
+                    return true;
+            }
         }
         return false;
     }
@@ -485,19 +473,25 @@
      * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
-        if (o == null) return false;
-        Node<E> pred = null;
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null &&
-                o.equals(item) &&
-                p.casItem(item, null)) {
-                Node<E> next = succ(p);
-                if (pred != null && next != null)
-                    pred.casNext(p, next);
-                return true;
+        if (o != null) {
+            Node<E> next, pred = null;
+            for (Node<E> p = first(); p != null; pred = p, p = next) {
+                boolean removed = false;
+                E item = p.item;
+                if (item != null) {
+                    if (!o.equals(item)) {
+                        next = succ(p);
+                        continue;
+                    }
+                    removed = casItem(p, item, null);
+                }
+
+                next = succ(p);
+                if (pred != null && next != null) // unlink
+                    casNext(pred, p, next);
+                if (removed)
+                    return true;
             }
-            pred = p;
         }
         return false;
     }
@@ -522,12 +516,11 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            checkNotNull(e);
-            Node<E> newNode = new Node<E>(e);
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                last.lazySetNext(newNode);
+                lazySetNext(last, newNode);
                 last = newNode;
             }
         }
@@ -539,7 +532,7 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (p.casNext(null, beginningOfTheEnd)) {
+                if (casNext(p, null, beginningOfTheEnd)) {
                     // Successful CAS is the linearization point
                     // for all elements to be added to this queue.
                     if (!casTail(t, last)) {
@@ -565,6 +558,62 @@
         }
     }
 
+    public String toString() {
+        String[] a = null;
+        restartFromHead: for (;;) {
+            int charLength = 0;
+            int size = 0;
+            for (Node<E> p = first(); p != null;) {
+                E item = p.item;
+                if (item != null) {
+                    if (a == null)
+                        a = new String[4];
+                    else if (size == a.length)
+                        a = Arrays.copyOf(a, 2 * size);
+                    String s = item.toString();
+                    a[size++] = s;
+                    charLength += s.length();
+                }
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+
+            if (size == 0)
+                return "[]";
+
+            return Helpers.toString(a, size, charLength);
+        }
+    }
+
+    private Object[] toArrayInternal(Object[] a) {
+        Object[] x = a;
+        restartFromHead: for (;;) {
+            int size = 0;
+            for (Node<E> p = first(); p != null;) {
+                E item = p.item;
+                if (item != null) {
+                    if (x == null)
+                        x = new Object[4];
+                    else if (size == x.length)
+                        x = Arrays.copyOf(x, 2 * (size + 4));
+                    x[size++] = item;
+                }
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            if (x == null)
+                return new Object[0];
+            else if (a != null && size <= a.length) {
+                if (a != x)
+                    System.arraycopy(x, 0, a, 0, size);
+                if (size < a.length)
+                    a[size] = null;
+                return a;
+            }
+            return (size == x.length) ? x : Arrays.copyOf(x, size);
+        }
+    }
+
     /**
      * Returns an array containing all of the elements in this queue, in
      * proper sequence.
@@ -579,14 +628,7 @@
      * @return an array containing all of the elements in this queue
      */
     public Object[] toArray() {
-        // Use ArrayList to deal with resizing.
-        ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null)
-                al.add(item);
-        }
-        return al.toArray();
+        return toArrayInternal(null);
     }
 
     /**
@@ -610,7 +652,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -626,28 +668,8 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        // try to use sent-in array
-        int k = 0;
-        Node<E> p;
-        for (p = first(); p != null && k < a.length; p = succ(p)) {
-            E item = p.item;
-            if (item != null)
-                a[k++] = (T)item;
-        }
-        if (p == null) {
-            if (k < a.length)
-                a[k] = null;
-            return a;
-        }
-
-        // If won't fit, use ArrayList version
-        ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> q = first(); q != null; q = succ(q)) {
-            E item = q.item;
-            if (item != null)
-                al.add(item);
-        }
-        return al.toArray(a);
+        if (a == null) throw new NullPointerException();
+        return (T[]) toArrayInternal(a);
     }
 
     /**
@@ -683,54 +705,47 @@
         private Node<E> lastRet;
 
         Itr() {
-            advance();
-        }
-
-        /**
-         * Moves to next valid node and returns item to return for
-         * next(), or null if no such.
-         */
-        private E advance() {
-            lastRet = nextNode;
-            E x = nextItem;
-
-            Node<E> pred, p;
-            if (nextNode == null) {
-                p = first();
-                pred = null;
-            } else {
-                pred = nextNode;
-                p = succ(nextNode);
-            }
-
-            for (;;) {
-                if (p == null) {
-                    nextNode = null;
-                    nextItem = null;
-                    return x;
+            restartFromHead: for (;;) {
+                Node<E> h, p, q;
+                for (p = h = head;; p = q) {
+                    E item;
+                    if ((item = p.item) != null) {
+                        nextNode = p;
+                        nextItem = item;
+                        break;
+                    }
+                    else if ((q = p.next) == null)
+                        break;
+                    else if (p == q)
+                        continue restartFromHead;
                 }
-                E item = p.item;
-                if (item != null) {
-                    nextNode = p;
-                    nextItem = item;
-                    return x;
-                } else {
-                    // skip over nulls
-                    Node<E> next = succ(p);
-                    if (pred != null && next != null)
-                        pred.casNext(p, next);
-                    p = next;
-                }
+                updateHead(h, p);
+                return;
             }
         }
 
         public boolean hasNext() {
-            return nextNode != null;
+            return nextItem != null;
         }
 
         public E next() {
-            if (nextNode == null) throw new NoSuchElementException();
-            return advance();
+            final Node<E> pred = nextNode;
+            if (pred == null) throw new NoSuchElementException();
+            // assert nextItem != null;
+            lastRet = pred;
+            E item = null;
+
+            for (Node<E> p = succ(pred), q;; p = q) {
+                if (p == null || (item = p.item) != null) {
+                    nextNode = p;
+                    E x = nextItem;
+                    nextItem = item;
+                    return x;
+                }
+                // unlink deleted nodes
+                if ((q = succ(p)) != null)
+                    casNext(pred, p, q);
+            }
         }
 
         public void remove() {
@@ -780,19 +795,18 @@
 
         // Read in elements until trailing null sentinel found
         Node<E> h = null, t = null;
-        Object item;
-        while ((item = s.readObject()) != null) {
+        for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = new Node<E>((E) item);
+            Node<E> newNode = newNode((E) item);
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
+                lazySetNext(t, newNode);
                 t = newNode;
             }
         }
         if (h == null)
-            h = t = new Node<E>(null);
+            h = t = newNode(null);
         head = h;
         tail = t;
     }
@@ -829,8 +843,9 @@
                 if (i > 0) {
                     batch = i;
                     return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                         Spliterator.CONCURRENT);
+                        (a, 0, i, (Spliterator.ORDERED |
+                                   Spliterator.NONNULL |
+                                   Spliterator.CONCURRENT));
                 }
             }
             return null;
@@ -904,38 +919,32 @@
         return new CLQSpliterator<E>(this);
     }
 
-    /**
-     * Throws NullPointerException if argument is null.
-     *
-     * @param v the element
-     */
-    private static void checkNotNull(Object v) {
-        if (v == null)
-            throw new NullPointerException();
-    }
-
     private boolean casTail(Node<E> cmp, Node<E> val) {
-        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+        return U.compareAndSwapObject(this, TAIL, cmp, val);
     }
 
     private boolean casHead(Node<E> cmp, Node<E> val) {
-        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+        return U.compareAndSwapObject(this, HEAD, cmp, val);
     }
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long headOffset;
-    private static final long tailOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long HEAD;
+    private static final long TAIL;
+    private static final long ITEM;
+    private static final long NEXT;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ConcurrentLinkedQueue.class;
-            headOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("head"));
-            tailOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("tail"));
-        } catch (Exception e) {
+            HEAD = U.objectFieldOffset
+                (ConcurrentLinkedQueue.class.getDeclaredField("head"));
+            TAIL = U.objectFieldOffset
+                (ConcurrentLinkedQueue.class.getDeclaredField("tail"));
+            ITEM = U.objectFieldOffset
+                (Node.class.getDeclaredField("item"));
+            NEXT = U.objectFieldOffset
+                (Node.class.getDeclaredField("next"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,7 +89,7 @@
         return ((v = get(key)) != null) ? v : defaultValue;
     }
 
-   /**
+    /**
      * {@inheritDoc}
      *
      * @implSpec The default implementation is equivalent to, for this
@@ -181,10 +181,10 @@
      *         is not supported by this map
      * @throws ClassCastException if the key or value is of an inappropriate
      *         type for this map
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified key or value is null,
      *         and this map does not permit null keys or values
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object key, Object value);
 
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentNavigableMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentNavigableMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,7 +34,9 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+
+import java.util.NavigableMap;
+import java.util.NavigableSet;
 
 /**
  * A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
@@ -101,7 +103,7 @@
      * reflected in the descending map, and vice-versa.
      *
      * <p>The returned map has an ordering equivalent to
-     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
+     * {@link java.util.Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code m.descendingMap().descendingMap()} returns a
      * view of {@code m} essentially equivalent to {@code m}.
      *
@@ -125,7 +127,7 @@
      *
      * @return a navigable set view of the keys in this map
      */
-    public NavigableSet<K> navigableKeySet();
+    NavigableSet<K> navigableKeySet();
 
     /**
      * Returns a {@link NavigableSet} view of the keys contained in this map.
@@ -163,5 +165,5 @@
      *
      * @return a reverse order navigable set view of the keys in this map
      */
-    public NavigableSet<K> descendingKeySet();
+    NavigableSet<K> descendingKeySet();
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.io.Serializable;
 import java.util.AbstractCollection;
 import java.util.AbstractMap;
@@ -50,13 +51,10 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.SortedMap;
-import java.util.SortedSet;
 import java.util.Spliterator;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
-import java.util.function.BiConsumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -359,9 +357,9 @@
     private static final long serialVersionUID = -8627078645895051609L;
 
     /**
-     * Special value used to identify base-level header
+     * Special value used to identify base-level header.
      */
-    private static final Object BASE_HEADER = new Object();
+    static final Object BASE_HEADER = new Object();
 
     /**
      * The topmost head index of the skiplist.
@@ -377,11 +375,11 @@
     final Comparator<? super K> comparator;
 
     /** Lazily initialized key set */
-    private transient KeySet<K> keySet;
+    private transient KeySet<K,V> keySet;
     /** Lazily initialized entry set */
     private transient EntrySet<K,V> entrySet;
     /** Lazily initialized values collection */
-    private transient Values<V> values;
+    private transient Values<K,V> values;
     /** Lazily initialized descending key set */
     private transient ConcurrentNavigableMap<K,V> descendingMap;
 
@@ -400,10 +398,10 @@
     }
 
     /**
-     * compareAndSet head node
+     * compareAndSet head node.
      */
     private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
-        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+        return U.compareAndSwapObject(this, HEAD, cmp, val);
     }
 
     /* ---------------- Nodes -------------- */
@@ -443,17 +441,17 @@
         }
 
         /**
-         * compareAndSet value field
+         * compareAndSet value field.
          */
         boolean casValue(Object cmp, Object val) {
-            return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
+            return U.compareAndSwapObject(this, VALUE, cmp, val);
         }
 
         /**
-         * compareAndSet next field
+         * compareAndSet next field.
          */
         boolean casNext(Node<K,V> cmp, Node<K,V> val) {
-            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+            return U.compareAndSwapObject(this, NEXT, cmp, val);
         }
 
         /**
@@ -534,21 +532,19 @@
             return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
         }
 
-        // UNSAFE mechanics
+        // Unsafe mechanics
 
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long valueOffset;
-        private static final long nextOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long VALUE;
+        private static final long NEXT;
 
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = Node.class;
-                valueOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("value"));
-                nextOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("next"));
-            } catch (Exception e) {
+                VALUE = U.objectFieldOffset
+                    (Node.class.getDeclaredField("value"));
+                NEXT = U.objectFieldOffset
+                    (Node.class.getDeclaredField("next"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -578,10 +574,10 @@
         }
 
         /**
-         * compareAndSet right field
+         * compareAndSet right field.
          */
         final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
-            return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val);
+            return U.compareAndSwapObject(this, RIGHT, cmp, val);
         }
 
         /**
@@ -618,15 +614,13 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long rightOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long RIGHT;
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = Index.class;
-                rightOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("right"));
-            } catch (Exception e) {
+                RIGHT = U.objectFieldOffset
+                    (Index.class.getDeclaredField("right"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -730,10 +724,10 @@
      *
      * The traversal loops in doPut, doRemove, and findNear all
      * include the same three kinds of checks. And specialized
-     * versions appear in findFirst, and findLast and their
-     * variants. They can't easily share code because each uses the
-     * reads of fields held in locals occurring in the orders they
-     * were performed.
+     * versions appear in findFirst, and findLast and their variants.
+     * They can't easily share code because each uses the reads of
+     * fields held in locals occurring in the orders they were
+     * performed.
      *
      * @param key the key
      * @return node holding key, or null if no such
@@ -1364,7 +1358,7 @@
 
         // Track the current rightmost node at each level. Uses an
         // ArrayList to avoid committing to initial or maximum level.
-        ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+        ArrayList<Index<K,V>> preds = new ArrayList<>();
 
         // initialize
         for (int i = 0; i <= h.level; ++i)
@@ -1461,12 +1455,12 @@
          * distinct because readObject calls can't be nicely adapted
          * as the kind of iterator needed by buildFromSorted. (They
          * can be, but doing so requires type cheats and/or creation
-         * of adaptor classes.) It is simpler to just adapt the code.
+         * of adapter classes.) It is simpler to just adapt the code.
          */
 
         HeadIndex<K,V> h = head;
         Node<K,V> basepred = h.node;
-        ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+        ArrayList<Index<K,V>> preds = new ArrayList<>();
         for (int i = 0; i <= h.level; ++i)
             preds.add(null);
         Index<K,V> q = h;
@@ -1833,13 +1827,13 @@
      * @return a navigable set view of the keys in this map
      */
     public NavigableSet<K> keySet() {
-        KeySet<K> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<K>(this));
+        KeySet<K,V> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet<>(this));
     }
 
     public NavigableSet<K> navigableKeySet() {
-        KeySet<K> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<K>(this));
+        KeySet<K,V> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet<>(this));
     }
 
     /**
@@ -1862,8 +1856,8 @@
      * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
      */
     public Collection<V> values() {
-        Values<V> vs = values;
-        return (vs != null) ? vs : (values = new Values<V>(this));
+        Values<K,V> vs = values;
+        return (vs != null) ? vs : (values = new Values<>(this));
     }
 
     /**
@@ -2346,20 +2340,6 @@
         }
     }
 
-    // Factory methods for iterators needed by ConcurrentSkipListSet etc
-
-    Iterator<K> keyIterator() {
-        return new KeyIterator();
-    }
-
-    Iterator<V> valueIterator() {
-        return new ValueIterator();
-    }
-
-    Iterator<Map.Entry<K,V>> entryIterator() {
-        return new EntryIterator();
-    }
-
     /* ---------------- View Classes -------------- */
 
     /*
@@ -2376,36 +2356,34 @@
         return list;
     }
 
-    static final class KeySet<E>
-            extends AbstractSet<E> implements NavigableSet<E> {
-        final ConcurrentNavigableMap<E,?> m;
-        KeySet(ConcurrentNavigableMap<E,?> map) { m = map; }
+    static final class KeySet<K,V>
+            extends AbstractSet<K> implements NavigableSet<K> {
+        final ConcurrentNavigableMap<K,V> m;
+        KeySet(ConcurrentNavigableMap<K,V> map) { m = map; }
         public int size() { return m.size(); }
         public boolean isEmpty() { return m.isEmpty(); }
         public boolean contains(Object o) { return m.containsKey(o); }
         public boolean remove(Object o) { return m.remove(o) != null; }
         public void clear() { m.clear(); }
-        public E lower(E e) { return m.lowerKey(e); }
-        public E floor(E e) { return m.floorKey(e); }
-        public E ceiling(E e) { return m.ceilingKey(e); }
-        public E higher(E e) { return m.higherKey(e); }
-        public Comparator<? super E> comparator() { return m.comparator(); }
-        public E first() { return m.firstKey(); }
-        public E last() { return m.lastKey(); }
-        public E pollFirst() {
-            Map.Entry<E,?> e = m.pollFirstEntry();
+        public K lower(K e) { return m.lowerKey(e); }
+        public K floor(K e) { return m.floorKey(e); }
+        public K ceiling(K e) { return m.ceilingKey(e); }
+        public K higher(K e) { return m.higherKey(e); }
+        public Comparator<? super K> comparator() { return m.comparator(); }
+        public K first() { return m.firstKey(); }
+        public K last() { return m.lastKey(); }
+        public K pollFirst() {
+            Map.Entry<K,V> e = m.pollFirstEntry();
             return (e == null) ? null : e.getKey();
         }
-        public E pollLast() {
-            Map.Entry<E,?> e = m.pollLastEntry();
+        public K pollLast() {
+            Map.Entry<K,V> e = m.pollLastEntry();
             return (e == null) ? null : e.getKey();
         }
-        @SuppressWarnings("unchecked")
-        public Iterator<E> iterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
-            else
-                return ((ConcurrentSkipListMap.SubMap<E,Object>)m).keyIterator();
+        public Iterator<K> iterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).new KeyIterator()
+                : ((SubMap<K,V>)m).new SubMapKeyIterator();
         }
         public boolean equals(Object o) {
             if (o == this)
@@ -2423,87 +2401,76 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-        public Iterator<E> descendingIterator() {
+        public Iterator<K> descendingIterator() {
             return descendingSet().iterator();
         }
-        public NavigableSet<E> subSet(E fromElement,
+        public NavigableSet<K> subSet(K fromElement,
                                       boolean fromInclusive,
-                                      E toElement,
+                                      K toElement,
                                       boolean toInclusive) {
-            return new KeySet<E>(m.subMap(fromElement, fromInclusive,
-                                          toElement,   toInclusive));
+            return new KeySet<>(m.subMap(fromElement, fromInclusive,
+                                         toElement,   toInclusive));
         }
-        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
-            return new KeySet<E>(m.headMap(toElement, inclusive));
+        public NavigableSet<K> headSet(K toElement, boolean inclusive) {
+            return new KeySet<>(m.headMap(toElement, inclusive));
         }
-        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
-            return new KeySet<E>(m.tailMap(fromElement, inclusive));
+        public NavigableSet<K> tailSet(K fromElement, boolean inclusive) {
+            return new KeySet<>(m.tailMap(fromElement, inclusive));
         }
-        public NavigableSet<E> subSet(E fromElement, E toElement) {
+        public NavigableSet<K> subSet(K fromElement, K toElement) {
             return subSet(fromElement, true, toElement, false);
         }
-        public NavigableSet<E> headSet(E toElement) {
+        public NavigableSet<K> headSet(K toElement) {
             return headSet(toElement, false);
         }
-        public NavigableSet<E> tailSet(E fromElement) {
+        public NavigableSet<K> tailSet(K fromElement) {
             return tailSet(fromElement, true);
         }
-        public NavigableSet<E> descendingSet() {
-            return new KeySet<E>(m.descendingMap());
+        public NavigableSet<K> descendingSet() {
+            return new KeySet<>(m.descendingMap());
         }
-        @SuppressWarnings("unchecked")
-        public Spliterator<E> spliterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
-            else
-                return (Spliterator<E>)((SubMap<E,?>)m).keyIterator();
+
+        public Spliterator<K> spliterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).keySpliterator()
+                : ((SubMap<K,V>)m).new SubMapKeyIterator();
         }
     }
 
-    static final class Values<E> extends AbstractCollection<E> {
-        final ConcurrentNavigableMap<?, E> m;
-        Values(ConcurrentNavigableMap<?, E> map) {
+    static final class Values<K,V> extends AbstractCollection<V> {
+        final ConcurrentNavigableMap<K,V> m;
+        Values(ConcurrentNavigableMap<K,V> map) {
             m = map;
         }
-        @SuppressWarnings("unchecked")
-        public Iterator<E> iterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<?,E>)m).valueIterator();
-            else
-                return ((SubMap<?,E>)m).valueIterator();
-        }
-        public boolean isEmpty() {
-            return m.isEmpty();
+        public Iterator<V> iterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).new ValueIterator()
+                : ((SubMap<K,V>)m).new SubMapValueIterator();
         }
-        public int size() {
-            return m.size();
-        }
-        public boolean contains(Object o) {
-            return m.containsValue(o);
-        }
-        public void clear() {
-            m.clear();
-        }
+        public int size() { return m.size(); }
+        public boolean isEmpty() { return m.isEmpty(); }
+        public boolean contains(Object o) { return m.containsValue(o); }
+        public void clear() { m.clear(); }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-        @SuppressWarnings("unchecked")
-        public Spliterator<E> spliterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<?,E>)m).valueSpliterator();
-            else
-                return (Spliterator<E>)((SubMap<?,E>)m).valueIterator();
+
+        public Spliterator<V> spliterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).valueSpliterator()
+                : ((SubMap<K,V>)m).new SubMapValueIterator();
         }
-        public boolean removeIf(Predicate<? super E> filter) {
+
+        public boolean removeIf(Predicate<? super V> filter) {
             if (filter == null) throw new NullPointerException();
             if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<?,E>)m).removeValueIf(filter);
+                return ((ConcurrentSkipListMap<K,V>)m).removeValueIf(filter);
             // else use iterator
-            @SuppressWarnings("unchecked") Iterator<Map.Entry<Object,E>> it =
-                    ((SubMap<Object,E>)m).entryIterator();
+            Iterator<Map.Entry<K,V>> it =
+                ((SubMap<K,V>)m).new SubMapEntryIterator();
             boolean removed = false;
             while (it.hasNext()) {
-                Map.Entry<Object,E> e = it.next();
-                E v = e.getValue();
+                Map.Entry<K,V> e = it.next();
+                V v = e.getValue();
                 if (filter.test(v) && m.remove(e.getKey(), v))
                     removed = true;
             }
@@ -2511,24 +2478,22 @@
         }
     }
 
-    static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
-        final ConcurrentNavigableMap<K1, V1> m;
-        EntrySet(ConcurrentNavigableMap<K1, V1> map) {
+    static final class EntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> {
+        final ConcurrentNavigableMap<K,V> m;
+        EntrySet(ConcurrentNavigableMap<K,V> map) {
             m = map;
         }
-        @SuppressWarnings("unchecked")
-        public Iterator<Map.Entry<K1,V1>> iterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator();
-            else
-                return ((SubMap<K1,V1>)m).entryIterator();
+        public Iterator<Map.Entry<K,V>> iterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).new EntryIterator()
+                : ((SubMap<K,V>)m).new SubMapEntryIterator();
         }
 
         public boolean contains(Object o) {
             if (!(o instanceof Map.Entry))
                 return false;
             Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-            V1 v = m.get(e.getKey());
+            V v = m.get(e.getKey());
             return v != null && v.equals(e.getValue());
         }
         public boolean remove(Object o) {
@@ -2563,23 +2528,22 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-        @SuppressWarnings("unchecked")
-        public Spliterator<Map.Entry<K1,V1>> spliterator() {
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator();
-            else
-                return (Spliterator<Map.Entry<K1,V1>>)
-                    ((SubMap<K1,V1>)m).entryIterator();
+
+        public Spliterator<Map.Entry<K,V>> spliterator() {
+            return (m instanceof ConcurrentSkipListMap)
+                ? ((ConcurrentSkipListMap<K,V>)m).entrySpliterator()
+                : ((SubMap<K,V>)m).new SubMapEntryIterator();
         }
-        public boolean removeIf(Predicate<? super Entry<K1, V1>> filter) {
+        public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
             if (filter == null) throw new NullPointerException();
             if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<K1,V1>)m).removeEntryIf(filter);
+                return ((ConcurrentSkipListMap<K,V>)m).removeEntryIf(filter);
             // else use iterator
-            Iterator<Map.Entry<K1,V1>> it = ((SubMap<K1,V1>)m).entryIterator();
+            Iterator<Map.Entry<K,V>> it =
+                ((SubMap<K,V>)m).new SubMapEntryIterator();
             boolean removed = false;
             while (it.hasNext()) {
-                Map.Entry<K1,V1> e = it.next();
+                Map.Entry<K,V> e = it.next();
                 if (filter.test(e) && m.remove(e.getKey(), e.getValue()))
                     removed = true;
             }
@@ -2589,13 +2553,13 @@
 
     /**
      * Submaps returned by {@link ConcurrentSkipListMap} submap operations
-     * represent a subrange of mappings of their underlying
-     * maps. Instances of this class support all methods of their
-     * underlying maps, differing in that mappings outside their range are
-     * ignored, and attempts to add mappings outside their ranges result
-     * in {@link IllegalArgumentException}.  Instances of this class are
-     * constructed only using the {@code subMap}, {@code headMap}, and
-     * {@code tailMap} methods of their underlying maps.
+     * represent a subrange of mappings of their underlying maps.
+     * Instances of this class support all methods of their underlying
+     * maps, differing in that mappings outside their range are ignored,
+     * and attempts to add mappings outside their ranges result in {@link
+     * IllegalArgumentException}.  Instances of this class are constructed
+     * only using the {@code subMap}, {@code headMap}, and {@code tailMap}
+     * methods of their underlying maps.
      *
      * @serial include
      */
@@ -2604,7 +2568,7 @@
         private static final long serialVersionUID = -7647078645895051609L;
 
         /** Underlying map */
-        private final ConcurrentSkipListMap<K,V> m;
+        final ConcurrentSkipListMap<K,V> m;
         /** lower bound key, or null if from start */
         private final K lo;
         /** upper bound key, or null if to end */
@@ -2614,10 +2578,10 @@
         /** inclusion flag for hi */
         private final boolean hiInclusive;
         /** direction */
-        private final boolean isDescending;
+        final boolean isDescending;
 
         // Lazily initialized view holders
-        private transient KeySet<K> keySetView;
+        private transient KeySet<K,V> keySetView;
         private transient Set<Map.Entry<K,V>> entrySetView;
         private transient Collection<V> valuesView;
 
@@ -2790,7 +2754,7 @@
         }
 
         /**
-         * Submap version of ConcurrentSkipListMap.getNearEntry
+         * Submap version of ConcurrentSkipListMap.getNearEntry.
          */
         Map.Entry<K,V> getNearEntry(K key, int rel) {
             Comparator<? super K> cmp = m.comparator;
@@ -3085,18 +3049,18 @@
         /* ---------------- Submap Views -------------- */
 
         public NavigableSet<K> keySet() {
-            KeySet<K> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
+            KeySet<K,V> ks = keySetView;
+            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
         }
 
         public NavigableSet<K> navigableKeySet() {
-            KeySet<K> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
+            KeySet<K,V> ks = keySetView;
+            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
         }
 
         public Collection<V> values() {
             Collection<V> vs = valuesView;
-            return (vs != null) ? vs : (valuesView = new Values<V>(this));
+            return (vs != null) ? vs : (valuesView = new Values<>(this));
         }
 
         public Set<Map.Entry<K,V>> entrySet() {
@@ -3108,21 +3072,9 @@
             return descendingMap().navigableKeySet();
         }
 
-        Iterator<K> keyIterator() {
-            return new SubMapKeyIterator();
-        }
-
-        Iterator<V> valueIterator() {
-            return new SubMapValueIterator();
-        }
-
-        Iterator<Map.Entry<K,V>> entryIterator() {
-            return new SubMapEntryIterator();
-        }
-
         /**
          * Variant of main Iter class to traverse through submaps.
-         * Also serves as back-up Spliterator for views
+         * Also serves as back-up Spliterator for views.
          */
         abstract class SubMapIter<T> implements Iterator<T>, Spliterator<T> {
             /** the last node returned by next() */
@@ -3298,9 +3250,9 @@
     }
 
     /**
-     * Helper method for EntrySet.removeIf
+     * Helper method for EntrySet.removeIf.
      */
-    boolean removeEntryIf(Predicate<? super Entry<K, V>> function) {
+    boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
         if (function == null) throw new NullPointerException();
         boolean removed = false;
         for (Node<K,V> n = findFirst(); n != null; n = n.next) {
@@ -3316,7 +3268,7 @@
     }
 
     /**
-     * Helper method for Values.removeIf
+     * Helper method for Values.removeIf.
      */
     boolean removeValueIf(Predicate<? super V> function) {
         if (function == null) throw new NullPointerException();
@@ -3371,7 +3323,7 @@
             super(comparator, row, origin, fence, est);
         }
 
-        public Spliterator<K> trySplit() {
+        public KeySpliterator<K,V> trySplit() {
             Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3459,7 +3411,7 @@
             super(comparator, row, origin, fence, est);
         }
 
-        public Spliterator<V> trySplit() {
+        public ValueSpliterator<K,V> trySplit() {
             Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3546,7 +3498,7 @@
             super(comparator, row, origin, fence, est);
         }
 
-        public Spliterator<Map.Entry<K,V>> trySplit() {
+        public EntrySpliterator<K,V> trySplit() {
             Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3644,20 +3596,13 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long headOffset;
-    private static final long SECONDARY;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long HEAD;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ConcurrentSkipListMap.class;
-            headOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("head"));
-            Class<?> tk = Thread.class;
-            SECONDARY = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
-
-        } catch (Exception e) {
+            HEAD = U.objectFieldOffset
+                (ConcurrentSkipListMap.class.getDeclaredField("head"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
@@ -323,8 +324,9 @@
      *
      * @param  c collection containing elements to be removed from this set
      * @return {@code true} if this set changed as a result of the call
-     * @throws ClassCastException if the types of one or more elements in this
-     *         set are incompatible with the specified collection
+     * @throws ClassCastException if the class of an element of this set
+     *         is incompatible with the specified collection
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
      */
@@ -384,7 +386,6 @@
 
     /* ---------------- SortedSet operations -------------- */
 
-
     public Comparator<? super E> comparator() {
         return m.comparator();
     }
@@ -498,28 +499,24 @@
      * @return a {@code Spliterator} over the elements in this set
      * @since 1.8
      */
-    @SuppressWarnings("unchecked")
     public Spliterator<E> spliterator() {
-        if (m instanceof ConcurrentSkipListMap)
-            return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
-        else
-            return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator();
+        return (m instanceof ConcurrentSkipListMap)
+            ? ((ConcurrentSkipListMap<E,?>)m).keySpliterator()
+            : ((ConcurrentSkipListMap.SubMap<E,?>)m).new SubMapKeyIterator();
     }
 
     // Support for resetting map in clone
     private void setMap(ConcurrentNavigableMap<E,Object> map) {
-        UNSAFE.putObjectVolatile(this, mapOffset, map);
+        U.putObjectVolatile(this, MAP, map);
     }
 
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long mapOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long MAP;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ConcurrentSkipListSet.class;
-            mapOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("m"));
-        } catch (Exception e) {
+            MAP = U.objectFieldOffset
+                (ConcurrentSkipListSet.class.getDeclaredField("m"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 05 20:54:58 2017 +0200
@@ -33,6 +33,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -46,7 +47,6 @@
 import java.util.RandomAccess;
 import java.util.Spliterator;
 import java.util.Spliterators;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
@@ -86,14 +86,17 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this list
  */
 public class CopyOnWriteArrayList<E>
     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
     private static final long serialVersionUID = 8673264195747942595L;
 
-    /** The lock protecting all mutators */
-    final transient ReentrantLock lock = new ReentrantLock();
+    /**
+     * The lock protecting all mutators.  (We have a mild preference
+     * for builtin monitors over ReentrantLock when either will do.)
+     */
+    final transient Object lock = new Object();
 
     /** The array, accessed only via getArray/setArray. */
     private transient volatile Object[] array;
@@ -172,13 +175,6 @@
     }
 
     /**
-     * Tests for equality, coping with nulls.
-     */
-    private static boolean eq(Object o1, Object o2) {
-        return (o1 == null) ? o2 == null : o1.equals(o2);
-    }
-
-    /**
      * static version of indexOf, to allow repeated calls without
      * needing to re-acquire array each time.
      * @param o element to search for
@@ -224,8 +220,7 @@
     /**
      * Returns {@code true} if this list contains the specified element.
      * More formally, returns {@code true} if and only if this list contains
-     * at least one element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     * at least one element {@code e} such that {@code Objects.equals(o, e)}.
      *
      * @param o element whose presence in this list is to be tested
      * @return {@code true} if this list contains the specified element
@@ -248,7 +243,7 @@
      * this list, searching forwards from {@code index}, or returns -1 if
      * the element is not found.
      * More formally, returns the lowest index {@code i} such that
-     * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
+     * {@code i >= index && Objects.equals(get(i), e)},
      * or -1 if there is no such index.
      *
      * @param e element to search for
@@ -276,7 +271,7 @@
      * this list, searching backwards from {@code index}, or returns -1 if
      * the element is not found.
      * More formally, returns the highest index {@code i} such that
-     * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
+     * {@code i <= index && Objects.equals(get(i), e)},
      * or -1 if there is no such index.
      *
      * @param e element to search for
@@ -353,7 +348,7 @@
      * The following code can be used to dump the list into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -368,7 +363,7 @@
      * @throws NullPointerException if the specified array is null
      */
     @SuppressWarnings("unchecked")
-    public <T> T[] toArray(T a[]) {
+    public <T> T[] toArray(T[] a) {
         Object[] elements = getArray();
         int len = elements.length;
         if (a.length < len)
@@ -388,6 +383,10 @@
         return (E) a[index];
     }
 
+    static String outOfBounds(int index, int size) {
+        return "Index: " + index + ", Size: " + size;
+    }
+
     /**
      * {@inheritDoc}
      *
@@ -404,9 +403,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E set(int index, E element) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             E oldValue = get(elements, index);
 
@@ -420,8 +417,6 @@
                 setArray(elements);
             }
             return oldValue;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -432,17 +427,13 @@
      * @return {@code true} (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             Object[] newElements = Arrays.copyOf(elements, len + 1);
             newElements[len] = e;
             setArray(newElements);
             return true;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -454,14 +445,11 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public void add(int index, E element) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (index > len || index < 0)
-                throw new IndexOutOfBoundsException("Index: "+index+
-                                                    ", Size: "+len);
+                throw new IndexOutOfBoundsException(outOfBounds(index, len));
             Object[] newElements;
             int numMoved = len - index;
             if (numMoved == 0)
@@ -474,8 +462,6 @@
             }
             newElements[index] = element;
             setArray(newElements);
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -487,9 +473,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E remove(int index) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             E oldValue = get(elements, index);
@@ -504,8 +488,6 @@
                 setArray(newElements);
             }
             return oldValue;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -513,8 +495,7 @@
      * Removes the first occurrence of the specified element from this list,
      * if it is present.  If this list does not contain the element, it is
      * unchanged.  More formally, removes the element with the lowest index
-     * {@code i} such that
-     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
+     * {@code i} such that {@code Objects.equals(o, get(i))}
      * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
@@ -533,15 +514,14 @@
      * recent snapshot contains o at the given index.
      */
     private boolean remove(Object o, Object[] snapshot, int index) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] current = getArray();
             int len = current.length;
             if (snapshot != current) findIndex: {
                 int prefix = Math.min(index, len);
                 for (int i = 0; i < prefix; i++) {
-                    if (current[i] != snapshot[i] && eq(o, current[i])) {
+                    if (current[i] != snapshot[i]
+                        && Objects.equals(o, current[i])) {
                         index = i;
                         break findIndex;
                     }
@@ -561,8 +541,6 @@
                              len - index - 1);
             setArray(newElements);
             return true;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -579,9 +557,7 @@
      *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
      */
     void removeRange(int fromIndex, int toIndex) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
 
@@ -598,8 +574,6 @@
                                  fromIndex, numMoved);
                 setArray(newElements);
             }
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -620,16 +594,15 @@
      * recent snapshot does not contain e.
      */
     private boolean addIfAbsent(E e, Object[] snapshot) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] current = getArray();
             int len = current.length;
             if (snapshot != current) {
                 // Optimize for lost race to another addXXX operation
                 int common = Math.min(snapshot.length, len);
                 for (int i = 0; i < common; i++)
-                    if (current[i] != snapshot[i] && eq(e, current[i]))
+                    if (current[i] != snapshot[i]
+                        && Objects.equals(e, current[i]))
                         return false;
                 if (indexOf(e, current, common, len) >= 0)
                         return false;
@@ -638,8 +611,6 @@
             newElements[len] = e;
             setArray(newElements);
             return true;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -672,18 +643,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean removeAll(Collection<?> c) {
         if (c == null) throw new NullPointerException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (len != 0) {
@@ -701,8 +670,6 @@
                 }
             }
             return false;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -715,18 +682,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     *         (<a href="../Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean retainAll(Collection<?> c) {
         if (c == null) throw new NullPointerException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (len != 0) {
@@ -744,8 +709,6 @@
                 }
             }
             return false;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -764,9 +727,7 @@
         Object[] cs = c.toArray();
         if (cs.length == 0)
             return 0;
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             int added = 0;
@@ -783,8 +744,6 @@
                 setArray(newElements);
             }
             return added;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -793,12 +752,8 @@
      * The list will be empty after this call returns.
      */
     public void clear() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             setArray(new Object[0]);
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -817,9 +772,7 @@
             ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
         if (cs.length == 0)
             return false;
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (len == 0 && cs.getClass() == Object[].class)
@@ -830,8 +783,6 @@
                 setArray(newElements);
             }
             return true;
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -853,14 +804,11 @@
      */
     public boolean addAll(int index, Collection<? extends E> c) {
         Object[] cs = c.toArray();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (index > len || index < 0)
-                throw new IndexOutOfBoundsException("Index: "+index+
-                                                    ", Size: "+len);
+                throw new IndexOutOfBoundsException(outOfBounds(index, len));
             if (cs.length == 0)
                 return false;
             int numMoved = len - index;
@@ -877,52 +825,47 @@
             System.arraycopy(cs, 0, newElements, index, cs.length);
             setArray(newElements);
             return true;
-        } finally {
-            lock.unlock();
         }
     }
 
     public void forEach(Consumer<? super E> action) {
         if (action == null) throw new NullPointerException();
-        Object[] elements = getArray();
-        int len = elements.length;
-        for (int i = 0; i < len; ++i) {
-            @SuppressWarnings("unchecked") E e = (E) elements[i];
+        for (Object x : getArray()) {
+            @SuppressWarnings("unchecked") E e = (E) x;
             action.accept(e);
         }
     }
 
     public boolean removeIf(Predicate<? super E> filter) {
         if (filter == null) throw new NullPointerException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    @SuppressWarnings("unchecked") E e = (E) elements[i];
-                    if (!filter.test(e))
-                        temp[newlen++] = e;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
+        synchronized (lock) {
+            final Object[] elements = getArray();
+            final int len = elements.length;
+            int i;
+            for (i = 0; i < len; i++) {
+                @SuppressWarnings("unchecked") E e = (E) elements[i];
+                if (filter.test(e)) {
+                    int newlen = i;
+                    final Object[] newElements = new Object[len - 1];
+                    System.arraycopy(elements, 0, newElements, 0, newlen);
+                    for (i++; i < len; i++) {
+                        @SuppressWarnings("unchecked") E x = (E) elements[i];
+                        if (!filter.test(x))
+                            newElements[newlen++] = x;
+                    }
+                    setArray((newlen == len - 1)
+                             ? newElements // one match => one copy
+                             : Arrays.copyOf(newElements, newlen));
                     return true;
                 }
             }
-            return false;
-        } finally {
-            lock.unlock();
+            return false;       // zero matches => zero copies
         }
     }
 
     public void replaceAll(UnaryOperator<E> operator) {
         if (operator == null) throw new NullPointerException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             Object[] newElements = Arrays.copyOf(elements, len);
@@ -931,22 +874,16 @@
                 newElements[i] = operator.apply(e);
             }
             setArray(newElements);
-        } finally {
-            lock.unlock();
         }
     }
 
     public void sort(Comparator<? super E> c) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             Object[] newElements = Arrays.copyOf(elements, elements.length);
             @SuppressWarnings("unchecked") E[] es = (E[])newElements;
             Arrays.sort(es, c);
             setArray(newElements);
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -1022,7 +959,7 @@
      * be the same if they have the same length and corresponding
      * elements at the same position in the sequence are <em>equal</em>.
      * Two elements {@code e1} and {@code e2} are considered
-     * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
+     * <em>equal</em> if {@code Objects.equals(e1, e2)}.
      *
      * @param o the object to be compared for equality with this list
      * @return {@code true} if the specified object is equal to this list
@@ -1033,12 +970,11 @@
         if (!(o instanceof List))
             return false;
 
-        List<?> list = (List<?>)(o);
+        List<?> list = (List<?>)o;
         Iterator<?> it = list.iterator();
         Object[] elements = getArray();
-        int len = elements.length;
-        for (int i = 0; i < len; ++i)
-            if (!it.hasNext() || !eq(elements[i], it.next()))
+        for (int i = 0, len = elements.length; i < len; i++)
+            if (!it.hasNext() || !Objects.equals(elements[i], it.next()))
                 return false;
         if (it.hasNext())
             return false;
@@ -1054,12 +990,8 @@
      */
     public int hashCode() {
         int hashCode = 1;
-        Object[] elements = getArray();
-        int len = elements.length;
-        for (int i = 0; i < len; ++i) {
-            Object obj = elements[i];
-            hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
-        }
+        for (Object x : getArray())
+            hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode());
         return hashCode;
     }
 
@@ -1103,7 +1035,7 @@
         Object[] elements = getArray();
         int len = elements.length;
         if (index < 0 || index > len)
-            throw new IndexOutOfBoundsException("Index: "+index);
+            throw new IndexOutOfBoundsException(outOfBounds(index, len));
 
         return new COWIterator<E>(elements, index);
     }
@@ -1133,7 +1065,7 @@
         /** Index of element to be returned by subsequent call to next.  */
         private int cursor;
 
-        private COWIterator(Object[] elements, int initialCursor) {
+        COWIterator(Object[] elements, int initialCursor) {
             cursor = initialCursor;
             snapshot = elements;
         }
@@ -1196,13 +1128,12 @@
         }
 
         @Override
+        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            Object[] elements = snapshot;
-            final int size = elements.length;
+            final int size = snapshot.length;
             for (int i = cursor; i < size; i++) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                action.accept(e);
+                action.accept((E) snapshot[i]);
             }
             cursor = size;
         }
@@ -1224,16 +1155,12 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public List<E> subList(int fromIndex, int toIndex) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
+        synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
             if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
                 throw new IndexOutOfBoundsException();
             return new COWSubList<E>(this, fromIndex, toIndex);
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -1264,6 +1191,7 @@
         // only call this holding l's lock
         COWSubList(CopyOnWriteArrayList<E> list,
                    int fromIndex, int toIndex) {
+            // assert Thread.holdsLock(list.lock);
             l = list;
             expectedArray = l.getArray();
             offset = fromIndex;
@@ -1272,94 +1200,72 @@
 
         // only call this holding l's lock
         private void checkForComodification() {
+            // assert Thread.holdsLock(l.lock);
             if (l.getArray() != expectedArray)
                 throw new ConcurrentModificationException();
         }
 
         // only call this holding l's lock
         private void rangeCheck(int index) {
+            // assert Thread.holdsLock(l.lock);
             if (index < 0 || index >= size)
-                throw new IndexOutOfBoundsException("Index: "+index+
-                                                    ",Size: "+size);
+                throw new IndexOutOfBoundsException(outOfBounds(index, size));
         }
 
         public E set(int index, E element) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
                 E x = l.set(index+offset, element);
                 expectedArray = l.getArray();
                 return x;
-            } finally {
-                lock.unlock();
             }
         }
 
         public E get(int index) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
                 return l.get(index+offset);
-            } finally {
-                lock.unlock();
             }
         }
 
         public int size() {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 return size;
-            } finally {
-                lock.unlock();
             }
         }
 
         public void add(int index, E element) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException();
+                    throw new IndexOutOfBoundsException
+                        (outOfBounds(index, size));
                 l.add(index+offset, element);
                 expectedArray = l.getArray();
                 size++;
-            } finally {
-                lock.unlock();
             }
         }
 
         public void clear() {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 l.removeRange(offset, offset+size);
                 expectedArray = l.getArray();
                 size = 0;
-            } finally {
-                lock.unlock();
             }
         }
 
         public E remove(int index) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
                 E result = l.remove(index+offset);
                 expectedArray = l.getArray();
                 size--;
                 return result;
-            } finally {
-                lock.unlock();
             }
         }
 
@@ -1372,41 +1278,29 @@
         }
 
         public Iterator<E> iterator() {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 return new COWSubListIterator<E>(l, 0, offset, size);
-            } finally {
-                lock.unlock();
             }
         }
 
         public ListIterator<E> listIterator(int index) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException("Index: "+index+
-                                                        ", Size: "+size);
+                    throw new IndexOutOfBoundsException
+                        (outOfBounds(index, size));
                 return new COWSubListIterator<E>(l, index, offset, size);
-            } finally {
-                lock.unlock();
             }
         }
 
         public List<E> subList(int fromIndex, int toIndex) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 checkForComodification();
                 if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
                     throw new IndexOutOfBoundsException();
                 return new COWSubList<E>(l, fromIndex + offset,
                                          toIndex + offset);
-            } finally {
-                lock.unlock();
             }
         }
 
@@ -1427,9 +1321,7 @@
 
         public void replaceAll(UnaryOperator<E> operator) {
             if (operator == null) throw new NullPointerException();
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 int lo = offset;
                 int hi = offset + size;
                 Object[] elements = expectedArray;
@@ -1444,15 +1336,11 @@
                     newElements[i] = operator.apply(e);
                 }
                 l.setArray(expectedArray = newElements);
-            } finally {
-                lock.unlock();
             }
         }
 
         public void sort(Comparator<? super E> c) {
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 int lo = offset;
                 int hi = offset + size;
                 Object[] elements = expectedArray;
@@ -1465,17 +1353,13 @@
                 @SuppressWarnings("unchecked") E[] es = (E[])newElements;
                 Arrays.sort(es, lo, hi, c);
                 l.setArray(expectedArray = newElements);
-            } finally {
-                lock.unlock();
             }
         }
 
         public boolean removeAll(Collection<?> c) {
             if (c == null) throw new NullPointerException();
             boolean removed = false;
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 int n = size;
                 if (n > 0) {
                     int lo = offset;
@@ -1504,8 +1388,6 @@
                         l.setArray(expectedArray = newElements);
                     }
                 }
-            } finally {
-                lock.unlock();
             }
             return removed;
         }
@@ -1513,9 +1395,7 @@
         public boolean retainAll(Collection<?> c) {
             if (c == null) throw new NullPointerException();
             boolean removed = false;
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 int n = size;
                 if (n > 0) {
                     int lo = offset;
@@ -1544,8 +1424,6 @@
                         l.setArray(expectedArray = newElements);
                     }
                 }
-            } finally {
-                lock.unlock();
             }
             return removed;
         }
@@ -1553,9 +1431,7 @@
         public boolean removeIf(Predicate<? super E> filter) {
             if (filter == null) throw new NullPointerException();
             boolean removed = false;
-            final ReentrantLock lock = l.lock;
-            lock.lock();
-            try {
+            synchronized (l.lock) {
                 int n = size;
                 if (n > 0) {
                     int lo = offset;
@@ -1584,8 +1460,6 @@
                         l.setArray(expectedArray = newElements);
                     }
                 }
-            } finally {
-                lock.unlock();
             }
             return removed;
         }
@@ -1658,29 +1532,26 @@
         }
 
         @Override
+        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            int s = size;
-            ListIterator<E> i = it;
-            while (nextIndex() < s) {
-                action.accept(i.next());
+            while (nextIndex() < size) {
+                action.accept(it.next());
             }
         }
     }
 
     // Support for resetting lock while deserializing
     private void resetLock() {
-        UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
+        U.putObjectVolatile(this, LOCK, new Object());
     }
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long lockOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long LOCK;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = CopyOnWriteArrayList.class;
-            lockOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("lock"));
-        } catch (Exception e) {
+            LOCK = U.objectFieldOffset
+                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,14 +34,16 @@
  */
 
 package java.util.concurrent;
+
+import java.util.AbstractSet;
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
 import java.util.Set;
-import java.util.AbstractSet;
-import java.util.Iterator;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
-import java.util.function.Consumer;
 
 /**
  * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
@@ -66,12 +68,12 @@
  * copy-on-write set to maintain a set of Handler objects that
  * perform some action upon state updates.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Handler { void handle(); ... }
  *
  * class X {
  *   private final CopyOnWriteArraySet<Handler> handlers
- *     = new CopyOnWriteArraySet<Handler>();
+ *     = new CopyOnWriteArraySet<>();
  *   public void addHandler(Handler h) { handlers.add(h); }
  *
  *   private long internalState;
@@ -91,7 +93,7 @@
  * @see CopyOnWriteArrayList
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this set
  */
 public class CopyOnWriteArraySet<E> extends AbstractSet<E>
         implements java.io.Serializable {
@@ -146,8 +148,7 @@
     /**
      * Returns {@code true} if this set contains the specified element.
      * More formally, returns {@code true} if and only if this set
-     * contains an element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     * contains an element {@code e} such that {@code Objects.equals(o, e)}.
      *
      * @param o element whose presence in this set is to be tested
      * @return {@code true} if this set contains the specified element
@@ -203,7 +204,7 @@
      * The following code can be used to dump the set into a newly allocated
      * array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -232,11 +233,10 @@
     /**
      * Removes the specified element from this set if it is present.
      * More formally, removes an element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
-     * if this set contains such an element.  Returns {@code true} if
-     * this set contained the element (or equivalently, if this set
-     * changed as a result of the call).  (This set will not contain the
-     * element once the call returns.)
+     * {@code Objects.equals(o, e)}, if this set contains such an element.
+     * Returns {@code true} if this set contained the element (or
+     * equivalently, if this set changed as a result of the call).
+     * (This set will not contain the element once the call returns.)
      *
      * @param o object to be removed from this set, if present
      * @return {@code true} if this set contained the specified element
@@ -249,7 +249,7 @@
      * Adds the specified element to this set if it is not already present.
      * More formally, adds the specified element {@code e} to this set if
      * the set contains no element {@code e2} such that
-     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
+     * {@code Objects.equals(e, e2)}.
      * If this set already contains the element, the call leaves the set
      * unchanged and returns {@code false}.
      *
@@ -273,7 +273,44 @@
      * @see #contains(Object)
      */
     public boolean containsAll(Collection<?> c) {
-        return al.containsAll(c);
+        return (c instanceof Set)
+            ? compareSets(al.getArray(), (Set<?>) c) >= 0
+            : al.containsAll(c);
+    }
+
+    /**
+     * Tells whether the objects in snapshot (regarded as a set) are a
+     * superset of the given set.
+     *
+     * @return -1 if snapshot is not a superset, 0 if the two sets
+     * contain precisely the same elements, and 1 if snapshot is a
+     * proper superset of the given set
+     */
+    private static int compareSets(Object[] snapshot, Set<?> set) {
+        // Uses O(n^2) algorithm, that is only appropriate for small
+        // sets, which CopyOnWriteArraySets should be.
+        //
+        // Optimize up to O(n) if the two sets share a long common prefix,
+        // as might happen if one set was created as a copy of the other set.
+
+        final int len = snapshot.length;
+        // Mark matched elements to avoid re-checking
+        final boolean[] matched = new boolean[len];
+
+        // j is the largest int with matched[i] true for { i | 0 <= i < j }
+        int j = 0;
+        outer: for (Object x : set) {
+            for (int i = j; i < len; i++) {
+                if (!matched[i] && Objects.equals(x, snapshot[i])) {
+                    matched[i] = true;
+                    if (i == j)
+                        do { j++; } while (j < len && matched[j]);
+                    continue outer;
+                }
+            }
+            return -1;
+        }
+        return (j == len) ? 0 : 1;
     }
 
     /**
@@ -302,9 +339,11 @@
      * @param  c collection containing elements to be removed from this set
      * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
-     *         is incompatible with the specified collection (optional)
+     *         is incompatible with the specified collection
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this set contains a null element and the
-     *         specified collection does not permit null elements (optional),
+     *         specified collection does not permit null elements
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -323,9 +362,11 @@
      * @param  c collection containing elements to be retained in this set
      * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
-     *         is incompatible with the specified collection (optional)
+     *         is incompatible with the specified collection
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this set contains a null element and the
-     *         specified collection does not permit null elements (optional),
+     *         specified collection does not permit null elements
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -359,41 +400,15 @@
      * number of elements and for every element {@code e1} returned by
      * the iterator over the specified set, there is an element
      * {@code e2} returned by the iterator over this set such that
-     * {@code (e1==null ? e2==null : e1.equals(e2))}.
+     * {@code Objects.equals(e1, e2)}.
      *
      * @param o object to be compared for equality with this set
      * @return {@code true} if the specified object is equal to this set
      */
     public boolean equals(Object o) {
-        if (o == this)
-            return true;
-        if (!(o instanceof Set))
-            return false;
-        Set<?> set = (Set<?>)(o);
-        Iterator<?> it = set.iterator();
-
-        // Uses O(n^2) algorithm that is only appropriate
-        // for small sets, which CopyOnWriteArraySets should be.
-
-        //  Use a single snapshot of underlying array
-        Object[] elements = al.getArray();
-        int len = elements.length;
-        // Mark matched elements to avoid re-checking
-        boolean[] matched = new boolean[len];
-        int k = 0;
-        outer: while (it.hasNext()) {
-            if (++k > len)
-                return false;
-            Object x = it.next();
-            for (int i = 0; i < len; ++i) {
-                if (!matched[i] && eq(x, elements[i])) {
-                    matched[i] = true;
-                    continue outer;
-                }
-            }
-            return false;
-        }
-        return k == len;
+        return (o == this)
+            || ((o instanceof Set)
+                && compareSets(al.getArray(), (Set<?>) o) == 0);
     }
 
     public boolean removeIf(Predicate<? super E> filter) {
@@ -423,11 +438,4 @@
         return Spliterators.spliterator
             (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
     }
-
-    /**
-     * Tests for equality, coping with nulls.
-     */
-    private static boolean eq(Object o1, Object o2) {
-        return (o1 == null) ? o2 == null : o1.equals(o2);
-    }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountDownLatch.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountDownLatch.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
 
 /**
@@ -72,7 +73,7 @@
  * until all workers have completed.
  * </ul>
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Driver { // ...
  *   void main() throws InterruptedException {
  *     CountDownLatch startSignal = new CountDownLatch(1);
@@ -113,7 +114,7 @@
  * will be able to pass through await. (When threads must repeatedly
  * count down in this way, instead use a {@link CyclicBarrier}.)
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Driver2 { // ...
  *   void main() throws InterruptedException {
  *     CountDownLatch doneSignal = new CountDownLatch(N);
@@ -179,7 +180,7 @@
                 int c = getState();
                 if (c == 0)
                     return false;
-                int nextc = c-1;
+                int nextc = c - 1;
                 if (compareAndSetState(c, nextc))
                     return nextc == 0;
             }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Wed Jul 05 20:54:58 2017 +0200
@@ -168,7 +168,8 @@
  * {@code tryComplete}) the pending count is set to one:
  *
  * <pre> {@code
- * class ForEach<E> ...
+ * class ForEach<E> ... {
+ *   ...
  *   public void compute() { // version 2
  *     if (hi - lo >= 2) {
  *       int mid = (lo + hi) >>> 1;
@@ -182,7 +183,7 @@
  *       tryComplete();
  *     }
  *   }
- * }</pre>
+ * }}</pre>
  *
  * As a further improvement, notice that the left task need not even exist.
  * Instead of creating a new one, we can iterate using the original task,
@@ -191,9 +192,10 @@
  * {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
  *
  * <pre> {@code
- * class ForEach<E> ...
+ * class ForEach<E> ... {
+ *   ...
  *   public void compute() { // version 3
- *     int l = lo,  h = hi;
+ *     int l = lo, h = hi;
  *     while (h - l >= 2) {
  *       int mid = (l + h) >>> 1;
  *       addToPendingCount(1);
@@ -204,7 +206,7 @@
  *       op.apply(array[l]);
  *     propagateCompletion();
  *   }
- * }</pre>
+ * }}</pre>
  *
  * Additional improvements of such classes might entail precomputing
  * pending counts so that they can be established in constructors,
@@ -233,7 +235,7 @@
  *   }
  *   public E getRawResult() { return result.get(); }
  *   public void compute() { // similar to ForEach version 3
- *     int l = lo,  h = hi;
+ *     int l = lo, h = hi;
  *     while (result.get() == null && h >= l) {
  *       if (h - l >= 2) {
  *         int mid = (l + h) >>> 1;
@@ -363,7 +365,7 @@
  *     this.next = next;
  *   }
  *   public void compute() {
- *     int l = lo,  h = hi;
+ *     int l = lo, h = hi;
  *     while (h - l >= 2) {
  *       int mid = (l + h) >>> 1;
  *       addToPendingCount(1);
@@ -374,7 +376,7 @@
  *       result = mapper.apply(array[l]);
  *     // process completions by reducing along and advancing subtask links
  *     for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
- *       for (MapReducer t = (MapReducer)c, s = t.forks;  s != null; s = t.forks = s.next)
+ *       for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
  *         t.result = reducer.apply(t.result, s.result);
  *     }
  *   }
@@ -402,8 +404,7 @@
  * // sample use:
  * PacketSender p = new PacketSender();
  * new HeaderBuilder(p, ...).fork();
- * new BodyBuilder(p, ...).fork();
- * }</pre>
+ * new BodyBuilder(p, ...).fork();}</pre>
  *
  * @since 1.8
  * @author Doug Lea
@@ -733,7 +734,7 @@
     }
 
     /**
-     * Returns the result of the computation. By default
+     * Returns the result of the computation.  By default,
      * returns {@code null}, which is appropriate for {@code Void}
      * actions, but in other cases should be overridden, almost
      * always to return a field or function of a field that
@@ -753,14 +754,13 @@
     protected void setRawResult(T t) { }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long PENDING;
     static {
         try {
-            U = sun.misc.Unsafe.getUnsafe();
             PENDING = U.objectFieldOffset
                 (CountedCompleter.class.getDeclaredField("pending"));
-        } catch (Exception e) {
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -54,7 +55,7 @@
  * <p><b>Sample usage:</b> Here is an example of using a barrier in a
  * parallel decomposition design:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Solver {
  *   final int N;
  *   final float[][] data;
@@ -85,7 +86,7 @@
  *       new Runnable() { public void run() { mergeRows(...); }};
  *     barrier = new CyclicBarrier(N, barrierAction);
  *
- *     List<Thread> threads = new ArrayList<Thread>(N);
+ *     List<Thread> threads = new ArrayList<>(N);
  *     for (int i = 0; i < N; i++) {
  *       Thread thread = new Thread(new Worker(i));
  *       threads.add(thread);
@@ -111,7 +112,7 @@
  * {@link #await} returns the arrival index of that thread at the barrier.
  * You can then choose which thread should execute the barrier action, for
  * example:
- *  <pre> {@code
+ * <pre> {@code
  * if (barrier.await() == 0) {
  *   // log the completion of this iteration
  * }}</pre>
@@ -149,7 +150,7 @@
      * but no subsequent reset.
      */
     private static class Generation {
-        boolean broken = false;
+        boolean broken;         // initially false
     }
 
     /** The lock for guarding barrier entry */
@@ -158,7 +159,7 @@
     private final Condition trip = lock.newCondition();
     /** The number of parties */
     private final int parties;
-    /* The command to run when tripped */
+    /** The command to run when tripped */
     private final Runnable barrierCommand;
     /** The current generation */
     private Generation generation = new Generation();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,10 +34,16 @@
  */
 
 package java.util.concurrent;
+
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} of
@@ -65,7 +71,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
     implements BlockingQueue<E> {
@@ -89,7 +95,7 @@
      * signalled.  So waiting threads must be prepared to acquire
      * and lose leadership while waiting.
      */
-    private Thread leader = null;
+    private Thread leader;
 
     /**
      * Condition signalled when a newer element becomes available
@@ -185,10 +191,9 @@
         lock.lock();
         try {
             E first = q.peek();
-            if (first == null || first.getDelay(NANOSECONDS) > 0)
-                return null;
-            else
-                return q.poll();
+            return (first == null || first.getDelay(NANOSECONDS) > 0)
+                ? null
+                : q.poll();
         } finally {
             lock.unlock();
         }
@@ -211,7 +216,7 @@
                     available.await();
                 else {
                     long delay = first.getDelay(NANOSECONDS);
-                    if (delay <= 0)
+                    if (delay <= 0L)
                         return q.poll();
                     first = null; // don't retain ref while waiting
                     if (leader != null)
@@ -253,15 +258,15 @@
             for (;;) {
                 E first = q.peek();
                 if (first == null) {
-                    if (nanos <= 0)
+                    if (nanos <= 0L)
                         return null;
                     else
                         nanos = available.awaitNanos(nanos);
                 } else {
                     long delay = first.getDelay(NANOSECONDS);
-                    if (delay <= 0)
+                    if (delay <= 0L)
                         return q.poll();
-                    if (nanos <= 0)
+                    if (nanos <= 0L)
                         return null;
                     first = null; // don't retain ref while waiting
                     if (nanos < delay || leader != null)
@@ -490,7 +495,7 @@
     }
 
     /**
-     * Identity-based version for use in Itr.remove
+     * Identity-based version for use in Itr.remove.
      */
     void removeEQ(Object o) {
         final ReentrantLock lock = this.lock;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,9 +35,6 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.LockSupport;
 
 /**
  * A synchronization point at which threads can pair and swap elements
@@ -53,9 +50,9 @@
  * to swap buffers between threads so that the thread filling the
  * buffer gets a freshly emptied one when it needs it, handing off the
  * filled one to the thread emptying the buffer.
- *  <pre> {@code
+ * <pre> {@code
  * class FillAndEmpty {
- *   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
+ *   Exchanger<DataBuffer> exchanger = new Exchanger<>();
  *   DataBuffer initialEmptyBuffer = ... a made-up type
  *   DataBuffer initialFullBuffer = ...
  *
@@ -326,7 +323,7 @@
     }
 
     /**
-     * Per-thread state
+     * Per-thread state.
      */
     private final Participant participant;
 
@@ -628,37 +625,33 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long BOUND;
     private static final long SLOT;
     private static final long MATCH;
     private static final long BLOCKER;
     private static final int ABASE;
     static {
-        int s;
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> ek = Exchanger.class;
-            Class<?> nk = Node.class;
-            Class<?> ak = Node[].class;
-            Class<?> tk = Thread.class;
             BOUND = U.objectFieldOffset
-                (ek.getDeclaredField("bound"));
+                (Exchanger.class.getDeclaredField("bound"));
             SLOT = U.objectFieldOffset
-                (ek.getDeclaredField("slot"));
+                (Exchanger.class.getDeclaredField("slot"));
+
             MATCH = U.objectFieldOffset
-                (nk.getDeclaredField("match"));
+                (Node.class.getDeclaredField("match"));
+
             BLOCKER = U.objectFieldOffset
-                (tk.getDeclaredField("parkBlocker"));
-            s = U.arrayIndexScale(ak);
+                (Thread.class.getDeclaredField("parkBlocker"));
+
+            int scale = U.arrayIndexScale(Node[].class);
+            if ((scale & (scale - 1)) != 0 || scale > (1 << ASHIFT))
+                throw new Error("Unsupported array scale");
             // ABASE absorbs padding in front of element 0
-            ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
-
-        } catch (Exception e) {
+            ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
-        if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
-            throw new Error("Unsupported array scale");
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -41,33 +41,31 @@
  * mechanics of how each task will be run, including details of thread
  * use, scheduling, etc.  An {@code Executor} is normally used
  * instead of explicitly creating threads. For example, rather than
- * invoking {@code new Thread(new(RunnableTask())).start()} for each
+ * invoking {@code new Thread(new RunnableTask()).start()} for each
  * of a set of tasks, you might use:
  *
- * <pre>
- * Executor executor = <em>anExecutor</em>;
+ * <pre> {@code
+ * Executor executor = anExecutor();
  * executor.execute(new RunnableTask1());
  * executor.execute(new RunnableTask2());
- * ...
- * </pre>
+ * ...}</pre>
  *
- * However, the {@code Executor} interface does not strictly
- * require that execution be asynchronous. In the simplest case, an
- * executor can run the submitted task immediately in the caller's
- * thread:
+ * However, the {@code Executor} interface does not strictly require
+ * that execution be asynchronous. In the simplest case, an executor
+ * can run the submitted task immediately in the caller's thread:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class DirectExecutor implements Executor {
  *   public void execute(Runnable r) {
  *     r.run();
  *   }
  * }}</pre>
  *
- * More typically, tasks are executed in some thread other
- * than the caller's thread.  The executor below spawns a new thread
- * for each task.
+ * More typically, tasks are executed in some thread other than the
+ * caller's thread.  The executor below spawns a new thread for each
+ * task.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class ThreadPerTaskExecutor implements Executor {
  *   public void execute(Runnable r) {
  *     new Thread(r).start();
@@ -79,9 +77,9 @@
  * serializes the submission of tasks to a second executor,
  * illustrating a composite executor.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class SerialExecutor implements Executor {
- *   final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
+ *   final Queue<Runnable> tasks = new ArrayDeque<>();
  *   final Executor executor;
  *   Runnable active;
  *
@@ -90,7 +88,7 @@
  *   }
  *
  *   public synchronized void execute(final Runnable r) {
- *     tasks.offer(new Runnable() {
+ *     tasks.add(new Runnable() {
  *       public void run() {
  *         try {
  *           r.run();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java	Wed Jul 05 20:54:58 2017 +0200
@@ -56,16 +56,16 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException, ExecutionException {
- *     CompletionService<Result> ecs
- *         = new ExecutorCompletionService<Result>(e);
- *     for (Callable<Result> s : solvers)
- *         ecs.submit(s);
- *     int n = solvers.size();
- *     for (int i = 0; i < n; ++i) {
- *         Result r = ecs.take().get();
- *         if (r != null)
- *             use(r);
- *     }
+ *   CompletionService<Result> ecs
+ *       = new ExecutorCompletionService<Result>(e);
+ *   for (Callable<Result> s : solvers)
+ *     ecs.submit(s);
+ *   int n = solvers.size();
+ *   for (int i = 0; i < n; ++i) {
+ *     Result r = ecs.take().get();
+ *     if (r != null)
+ *       use(r);
+ *   }
  * }}</pre>
  *
  * Suppose instead that you would like to use the first non-null result
@@ -76,32 +76,31 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException {
- *     CompletionService<Result> ecs
- *         = new ExecutorCompletionService<Result>(e);
- *     int n = solvers.size();
- *     List<Future<Result>> futures
- *         = new ArrayList<Future<Result>>(n);
- *     Result result = null;
- *     try {
- *         for (Callable<Result> s : solvers)
- *             futures.add(ecs.submit(s));
- *         for (int i = 0; i < n; ++i) {
- *             try {
- *                 Result r = ecs.take().get();
- *                 if (r != null) {
- *                     result = r;
- *                     break;
- *                 }
- *             } catch (ExecutionException ignore) {}
+ *   CompletionService<Result> ecs
+ *       = new ExecutorCompletionService<Result>(e);
+ *   int n = solvers.size();
+ *   List<Future<Result>> futures = new ArrayList<>(n);
+ *   Result result = null;
+ *   try {
+ *     for (Callable<Result> s : solvers)
+ *       futures.add(ecs.submit(s));
+ *     for (int i = 0; i < n; ++i) {
+ *       try {
+ *         Result r = ecs.take().get();
+ *         if (r != null) {
+ *           result = r;
+ *           break;
  *         }
+ *       } catch (ExecutionException ignore) {}
  *     }
- *     finally {
- *         for (Future<Result> f : futures)
- *             f.cancel(true);
- *     }
+ *   }
+ *   finally {
+ *     for (Future<Result> f : futures)
+ *       f.cancel(true);
+ *   }
  *
- *     if (result != null)
- *         use(result);
+ *   if (result != null)
+ *     use(result);
  * }}</pre>
  */
 public class ExecutorCompletionService<V> implements CompletionService<V> {
@@ -110,15 +109,18 @@
     private final BlockingQueue<Future<V>> completionQueue;
 
     /**
-     * FutureTask extension to enqueue upon completion
+     * FutureTask extension to enqueue upon completion.
      */
-    private class QueueingFuture extends FutureTask<Void> {
-        QueueingFuture(RunnableFuture<V> task) {
+    private static class QueueingFuture<V> extends FutureTask<Void> {
+        QueueingFuture(RunnableFuture<V> task,
+                       BlockingQueue<Future<V>> completionQueue) {
             super(task, null);
             this.task = task;
+            this.completionQueue = completionQueue;
         }
+        private final Future<V> task;
+        private final BlockingQueue<Future<V>> completionQueue;
         protected void done() { completionQueue.add(task); }
-        private final Future<V> task;
     }
 
     private RunnableFuture<V> newTaskFor(Callable<V> task) {
@@ -178,14 +180,14 @@
     public Future<V> submit(Callable<V> task) {
         if (task == null) throw new NullPointerException();
         RunnableFuture<V> f = newTaskFor(task);
-        executor.execute(new QueueingFuture(f));
+        executor.execute(new QueueingFuture<V>(f, completionQueue));
         return f;
     }
 
     public Future<V> submit(Runnable task, V result) {
         if (task == null) throw new NullPointerException();
         RunnableFuture<V> f = newTaskFor(task, result);
-        executor.execute(new QueueingFuture(f));
+        executor.execute(new QueueingFuture<V>(f, completionQueue));
         return f;
     }
 
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorService.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorService.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,8 +34,9 @@
  */
 
 package java.util.concurrent;
+
+import java.util.Collection;
 import java.util.List;
-import java.util.Collection;
 
 /**
  * An {@link Executor} that provides methods to manage termination and
@@ -71,7 +72,7 @@
  * pool service incoming requests. It uses the preconfigured {@link
  * Executors#newFixedThreadPool} factory method:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class NetworkService implements Runnable {
  *   private final ServerSocket serverSocket;
  *   private final ExecutorService pool;
@@ -105,7 +106,7 @@
  * first by calling {@code shutdown} to reject incoming tasks, and then
  * calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
  *
- *  <pre> {@code
+ * <pre> {@code
  * void shutdownAndAwaitTermination(ExecutorService pool) {
  *   pool.shutdown(); // Disable new tasks from being submitted
  *   try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,14 +34,16 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
+
 import java.security.AccessControlContext;
+import java.security.AccessControlException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 import sun.security.util.SecurityConstants;
 
 /**
@@ -51,18 +53,18 @@
  * package. This class supports the following kinds of methods:
  *
  * <ul>
- *   <li> Methods that create and return an {@link ExecutorService}
- *        set up with commonly useful configuration settings.
- *   <li> Methods that create and return a {@link ScheduledExecutorService}
- *        set up with commonly useful configuration settings.
- *   <li> Methods that create and return a "wrapped" ExecutorService, that
- *        disables reconfiguration by making implementation-specific methods
- *        inaccessible.
- *   <li> Methods that create and return a {@link ThreadFactory}
- *        that sets newly created threads to a known state.
- *   <li> Methods that create and return a {@link Callable}
- *        out of other closure-like forms, so they can be used
- *        in execution methods requiring {@code Callable}.
+ *   <li>Methods that create and return an {@link ExecutorService}
+ *       set up with commonly useful configuration settings.
+ *   <li>Methods that create and return a {@link ScheduledExecutorService}
+ *       set up with commonly useful configuration settings.
+ *   <li>Methods that create and return a "wrapped" ExecutorService, that
+ *       disables reconfiguration by making implementation-specific methods
+ *       inaccessible.
+ *   <li>Methods that create and return a {@link ThreadFactory}
+ *       that sets newly created threads to a known state.
+ *   <li>Methods that create and return a {@link Callable}
+ *       out of other closure-like forms, so they can be used
+ *       in execution methods requiring {@code Callable}.
  * </ul>
  *
  * @since 1.5
@@ -114,9 +116,10 @@
     }
 
     /**
-     * Creates a work-stealing thread pool using all
-     * {@link Runtime#availableProcessors available processors}
+     * Creates a work-stealing thread pool using the number of
+     * {@linkplain Runtime#availableProcessors available processors}
      * as its target parallelism level.
+     *
      * @return the newly created thread pool
      * @see #newWorkStealingPool(int)
      * @since 1.8
@@ -498,11 +501,11 @@
     // Non-public classes supporting the public methods
 
     /**
-     * A callable that runs given task and returns given result
+     * A callable that runs given task and returns given result.
      */
-    static final class RunnableAdapter<T> implements Callable<T> {
-        final Runnable task;
-        final T result;
+    private static final class RunnableAdapter<T> implements Callable<T> {
+        private final Runnable task;
+        private final T result;
         RunnableAdapter(Runnable task, T result) {
             this.task = task;
             this.result = result;
@@ -514,11 +517,11 @@
     }
 
     /**
-     * A callable that runs under established access control settings
+     * A callable that runs under established access control settings.
      */
-    static final class PrivilegedCallable<T> implements Callable<T> {
-        private final Callable<T> task;
-        private final AccessControlContext acc;
+    private static final class PrivilegedCallable<T> implements Callable<T> {
+        final Callable<T> task;
+        final AccessControlContext acc;
 
         PrivilegedCallable(Callable<T> task) {
             this.task = task;
@@ -541,12 +544,13 @@
 
     /**
      * A callable that runs under established access control settings and
-     * current ClassLoader
+     * current ClassLoader.
      */
-    static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
-        private final Callable<T> task;
-        private final AccessControlContext acc;
-        private final ClassLoader ccl;
+    private static final class PrivilegedCallableUsingCurrentClassLoader<T>
+            implements Callable<T> {
+        final Callable<T> task;
+        final AccessControlContext acc;
+        final ClassLoader ccl;
 
         PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
             SecurityManager sm = System.getSecurityManager();
@@ -591,9 +595,9 @@
     }
 
     /**
-     * The default thread factory
+     * The default thread factory.
      */
-    static class DefaultThreadFactory implements ThreadFactory {
+    private static class DefaultThreadFactory implements ThreadFactory {
         private static final AtomicInteger poolNumber = new AtomicInteger(1);
         private final ThreadGroup group;
         private final AtomicInteger threadNumber = new AtomicInteger(1);
@@ -621,11 +625,11 @@
     }
 
     /**
-     * Thread factory capturing access control context and class loader
+     * Thread factory capturing access control context and class loader.
      */
-    static class PrivilegedThreadFactory extends DefaultThreadFactory {
-        private final AccessControlContext acc;
-        private final ClassLoader ccl;
+    private static class PrivilegedThreadFactory extends DefaultThreadFactory {
+        final AccessControlContext acc;
+        final ClassLoader ccl;
 
         PrivilegedThreadFactory() {
             super();
@@ -662,7 +666,8 @@
      * A wrapper class that exposes only the ExecutorService methods
      * of an ExecutorService implementation.
      */
-    static class DelegatedExecutorService extends AbstractExecutorService {
+    private static class DelegatedExecutorService
+            extends AbstractExecutorService {
         private final ExecutorService e;
         DelegatedExecutorService(ExecutorService executor) { e = executor; }
         public void execute(Runnable command) { e.execute(command); }
@@ -703,8 +708,8 @@
         }
     }
 
-    static class FinalizableDelegatedExecutorService
-        extends DelegatedExecutorService {
+    private static class FinalizableDelegatedExecutorService
+            extends DelegatedExecutorService {
         FinalizableDelegatedExecutorService(ExecutorService executor) {
             super(executor);
         }
@@ -717,7 +722,7 @@
      * A wrapper class that exposes only the ScheduledExecutorService
      * methods of a ScheduledExecutorService implementation.
      */
-    static class DelegatedScheduledExecutorService
+    private static class DelegatedScheduledExecutorService
             extends DelegatedExecutorService
             implements ScheduledExecutorService {
         private final ScheduledExecutorService e;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Interrelated interfaces and static methods for establishing
+ * flow-controlled components in which {@link Publisher Publishers}
+ * produce items consumed by one or more {@link Subscriber
+ * Subscribers}, each managed by a {@link Subscription
+ * Subscription}.
+ *
+ * <p>These interfaces correspond to the <a
+ * href="http://www.reactive-streams.org/"> reactive-streams</a>
+ * specification.  They apply in both concurrent and distributed
+ * asynchronous settings: All (seven) methods are defined in {@code
+ * void} "one-way" message style. Communication relies on a simple form
+ * of flow control (method {@link Subscription#request}) that can be
+ * used to avoid resource management problems that may otherwise occur
+ * in "push" based systems.
+ *
+ * <p><b>Examples.</b> A {@link Publisher} usually defines its own
+ * {@link Subscription} implementation; constructing one in method
+ * {@code subscribe} and issuing it to the calling {@link
+ * Subscriber}. It publishes items to the subscriber asynchronously,
+ * normally using an {@link Executor}.  For example, here is a very
+ * simple publisher that only issues (when requested) a single {@code
+ * TRUE} item to a single subscriber.  Because the subscriber receives
+ * only a single item, this class does not use buffering and ordering
+ * control required in most implementations (for example {@link
+ * SubmissionPublisher}).
+ *
+ * <pre> {@code
+ * class OneShotPublisher implements Publisher<Boolean> {
+ *   private final ExecutorService executor = ForkJoinPool.commonPool(); // daemon-based
+ *   private boolean subscribed; // true after first subscribe
+ *   public synchronized void subscribe(Subscriber<? super Boolean> subscriber) {
+ *     if (subscribed)
+ *        subscriber.onError(new IllegalStateException()); // only one allowed
+ *     else {
+ *       subscribed = true;
+ *       subscriber.onSubscribe(new OneShotSubscription(subscriber, executor));
+ *     }
+ *   }
+ *   static class OneShotSubscription implements Subscription {
+ *     private final Subscriber<? super Boolean> subscriber;
+ *     private final ExecutorService executor;
+ *     private Future<?> future; // to allow cancellation
+ *     private boolean completed;
+ *     OneShotSubscription(Subscriber<? super Boolean> subscriber,
+ *                         ExecutorService executor) {
+ *       this.subscriber = subscriber;
+ *       this.executor = executor;
+ *     }
+ *     public synchronized void request(long n) {
+ *       if (n != 0 && !completed) {
+ *         completed = true;
+ *         if (n < 0) {
+ *           IllegalArgumentException ex = new IllegalArgumentException();
+ *           executor.execute(() -> subscriber.onError(ex));
+ *         } else {
+ *           future = executor.submit(() -> {
+ *             subscriber.onNext(Boolean.TRUE);
+ *             subscriber.onComplete();
+ *           });
+ *         }
+ *       }
+ *     }
+ *     public synchronized void cancel() {
+ *       completed = true;
+ *       if (future != null) future.cancel(false);
+ *     }
+ *   }
+ * }}</pre>
+ *
+ * <p>A {@link Subscriber} arranges that items be requested and
+ * processed.  Items (invocations of {@link Subscriber#onNext}) are
+ * not issued unless requested, but multiple items may be requested.
+ * Many Subscriber implementations can arrange this in the style of
+ * the following example, where a buffer size of 1 single-steps, and
+ * larger sizes usually allow for more efficient overlapped processing
+ * with less communication; for example with a value of 64, this keeps
+ * total outstanding requests between 32 and 64.
+ * Because Subscriber method invocations for a given {@link
+ * Subscription} are strictly ordered, there is no need for these
+ * methods to use locks or volatiles unless a Subscriber maintains
+ * multiple Subscriptions (in which case it is better to instead
+ * define multiple Subscribers, each with its own Subscription).
+ *
+ * <pre> {@code
+ * class SampleSubscriber<T> implements Subscriber<T> {
+ *   final Consumer<? super T> consumer;
+ *   Subscription subscription;
+ *   final long bufferSize;
+ *   long count;
+ *   SampleSubscriber(long bufferSize, Consumer<? super T> consumer) {
+ *     this.bufferSize = bufferSize;
+ *     this.consumer = consumer;
+ *   }
+ *   public void onSubscribe(Subscription subscription) {
+ *     long initialRequestSize = bufferSize;
+ *     count = bufferSize - bufferSize / 2; // re-request when half consumed
+ *     (this.subscription = subscription).request(initialRequestSize);
+ *   }
+ *   public void onNext(T item) {
+ *     if (--count <= 0)
+ *       subscription.request(count = bufferSize - bufferSize / 2);
+ *     consumer.accept(item);
+ *   }
+ *   public void onError(Throwable ex) { ex.printStackTrace(); }
+ *   public void onComplete() {}
+ * }}</pre>
+ *
+ * <p>The default value of {@link #defaultBufferSize} may provide a
+ * useful starting point for choosing request sizes and capacities in
+ * Flow components based on expected rates, resources, and usages.
+ * Or, when flow control is never needed, a subscriber may initially
+ * request an effectively unbounded number of items, as in:
+ *
+ * <pre> {@code
+ * class UnboundedSubscriber<T> implements Subscriber<T> {
+ *   public void onSubscribe(Subscription subscription) {
+ *     subscription.request(Long.MAX_VALUE); // effectively unbounded
+ *   }
+ *   public void onNext(T item) { use(item); }
+ *   public void onError(Throwable ex) { ex.printStackTrace(); }
+ *   public void onComplete() {}
+ *   void use(T item) { ... }
+ * }}</pre>
+ *
+ * @author Doug Lea
+ * @since 1.9
+ */
+public final class Flow {
+
+    private Flow() {} // uninstantiable
+
+    /**
+     * A producer of items (and related control messages) received by
+     * Subscribers.  Each current {@link Subscriber} receives the same
+     * items (via method {@code onNext}) in the same order, unless
+     * drops or errors are encountered. If a Publisher encounters an
+     * error that does not allow items to be issued to a Subscriber,
+     * that Subscriber receives {@code onError}, and then receives no
+     * further messages.  Otherwise, when it is known that no further
+     * messages will be issued to it, a subscriber receives {@code
+     * onComplete}.  Publishers ensure that Subscriber method
+     * invocations for each subscription are strictly ordered in <a
+     * href="package-summary.html#MemoryVisibility"><i>happens-before</i></a>
+     * order.
+     *
+     * <p>Publishers may vary in policy about whether drops (failures
+     * to issue an item because of resource limitations) are treated
+     * as unrecoverable errors.  Publishers may also vary about
+     * whether Subscribers receive items that were produced or
+     * available before they subscribed.
+     *
+     * @param <T> the published item type
+     */
+    @FunctionalInterface
+    public static interface Publisher<T> {
+        /**
+         * Adds the given Subscriber if possible.  If already
+         * subscribed, or the attempt to subscribe fails due to policy
+         * violations or errors, the Subscriber's {@code onError}
+         * method is invoked with an {@link IllegalStateException}.
+         * Otherwise, the Subscriber's {@code onSubscribe} method is
+         * invoked with a new {@link Subscription}.  Subscribers may
+         * enable receiving items by invoking the {@code request}
+         * method of this Subscription, and may unsubscribe by
+         * invoking its {@code cancel} method.
+         *
+         * @param subscriber the subscriber
+         * @throws NullPointerException if subscriber is null
+         */
+        public void subscribe(Subscriber<? super T> subscriber);
+    }
+
+    /**
+     * A receiver of messages.  The methods in this interface are
+     * invoked in strict sequential order for each {@link
+     * Subscription}.
+     *
+     * @param <T> the subscribed item type
+     */
+    public static interface Subscriber<T> {
+        /**
+         * Method invoked prior to invoking any other Subscriber
+         * methods for the given Subscription. If this method throws
+         * an exception, resulting behavior is not guaranteed, but may
+         * cause the Subscription not to be established or to be cancelled.
+         *
+         * <p>Typically, implementations of this method invoke {@code
+         * subscription.request} to enable receiving items.
+         *
+         * @param subscription a new subscription
+         */
+        public void onSubscribe(Subscription subscription);
+
+        /**
+         * Method invoked with a Subscription's next item.  If this
+         * method throws an exception, resulting behavior is not
+         * guaranteed, but may cause the Subscription to be cancelled.
+         *
+         * @param item the item
+         */
+        public void onNext(T item);
+
+        /**
+         * Method invoked upon an unrecoverable error encountered by a
+         * Publisher or Subscription, after which no other Subscriber
+         * methods are invoked by the Subscription.  If this method
+         * itself throws an exception, resulting behavior is
+         * undefined.
+         *
+         * @param throwable the exception
+         */
+        public void onError(Throwable throwable);
+
+        /**
+         * Method invoked when it is known that no additional
+         * Subscriber method invocations will occur for a Subscription
+         * that is not already terminated by error, after which no
+         * other Subscriber methods are invoked by the Subscription.
+         * If this method throws an exception, resulting behavior is
+         * undefined.
+         */
+        public void onComplete();
+    }
+
+    /**
+     * Message control linking a {@link Publisher} and {@link
+     * Subscriber}.  Subscribers receive items only when requested,
+     * and may cancel at any time. The methods in this interface are
+     * intended to be invoked only by their Subscribers; usages in
+     * other contexts have undefined effects.
+     */
+    public static interface Subscription {
+        /**
+         * Adds the given number {@code n} of items to the current
+         * unfulfilled demand for this subscription.  If {@code n} is
+         * negative, the Subscriber will receive an {@code onError}
+         * signal with an {@link IllegalArgumentException} argument.
+         * Otherwise, the Subscriber will receive up to {@code n}
+         * additional {@code onNext} invocations (or fewer if
+         * terminated).
+         *
+         * @param n the increment of demand; a value of {@code
+         * Long.MAX_VALUE} may be considered as effectively unbounded
+         */
+        public void request(long n);
+
+        /**
+         * Causes the Subscriber to (eventually) stop receiving
+         * messages.  Implementation is best-effort -- additional
+         * messages may be received after invoking this method.
+         * A cancelled subscription need not ever receive an
+         * {@code onComplete} or {@code onError} signal.
+         */
+        public void cancel();
+    }
+
+    /**
+     * A component that acts as both a Subscriber and Publisher.
+     *
+     * @param <T> the subscribed item type
+     * @param <R> the published item type
+     */
+    public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
+    }
+
+    static final int DEFAULT_BUFFER_SIZE = 256;
+
+    /**
+     * Returns a default value for Publisher or Subscriber buffering,
+     * that may be used in the absence of other constraints.
+     *
+     * @implNote
+     * The current value returned is 256.
+     *
+     * @return the buffer size value
+     */
+    public static int defaultBufferSize() {
+        return DEFAULT_BUFFER_SIZE;
+    }
+
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,23 +36,16 @@
 package java.util.concurrent;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.security.AccessControlContext;
+import java.security.Permissions;
+import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.security.AccessControlContext;
-import java.security.ProtectionDomain;
-import java.security.Permissions;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.LockSupport;
 
 /**
  * An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -216,42 +209,60 @@
      * arbitrating pop vs poll (steal) from being on the indices
      * ("base" and "top") to the slots themselves.
      *
-     * Adding tasks then takes the form of a classic array push(task):
-     *    q.array[q.top] = task; ++q.top;
+     * Adding tasks then takes the form of a classic array push(task)
+     * in a circular buffer:
+     *    q.array[q.top++ % length] = task;
      *
      * (The actual code needs to null-check and size-check the array,
-     * properly fence the accesses, and possibly signal waiting
-     * workers to start scanning -- see below.)  Both a successful pop
-     * and poll mainly entail a CAS of a slot from non-null to null.
+     * uses masking, not mod, for indexing a power-of-two-sized array,
+     * properly fences accesses, and possibly signals waiting workers
+     * to start scanning -- see below.)  Both a successful pop and
+     * poll mainly entail a CAS of a slot from non-null to null.
      *
      * The pop operation (always performed by owner) is:
-     *   if ((base != top) and
-     *        (the task at top slot is not null) and
+     *   if ((the task at top slot is not null) and
      *        (CAS slot to null))
      *           decrement top and return task;
      *
      * And the poll operation (usually by a stealer) is
-     *    if ((base != top) and
-     *        (the task at base slot is not null) and
-     *        (base has not changed) and
+     *    if ((the task at base slot is not null) and
      *        (CAS slot to null))
      *           increment base and return task;
      *
-     * Because we rely on CASes of references, we do not need tag bits
-     * on base or top.  They are simple ints as used in any circular
-     * array-based queue (see for example ArrayDeque).  Updates to the
-     * indices guarantee that top == base means the queue is empty,
-     * but otherwise may err on the side of possibly making the queue
-     * appear nonempty when a push, pop, or poll have not fully
-     * committed. (Method isEmpty() checks the case of a partially
+     * There are several variants of each of these; for example most
+     * versions of poll pre-screen the CAS by rechecking that the base
+     * has not changed since reading the slot, and most methods only
+     * attempt the CAS if base appears not to be equal to top.
+     *
+     * Memory ordering.  See "Correct and Efficient Work-Stealing for
+     * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
+     * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
+     * analysis of memory ordering requirements in work-stealing
+     * algorithms similar to (but different than) the one used here.
+     * Extracting tasks in array slots via (fully fenced) CAS provides
+     * primary synchronization. The base and top indices imprecisely
+     * guide where to extract from. We do not always require strict
+     * orderings of array and index updates, so sometimes let them be
+     * subject to compiler and processor reorderings. However, the
+     * volatile "base" index also serves as a basis for memory
+     * ordering: Slot accesses are preceded by a read of base,
+     * ensuring happens-before ordering with respect to stealers (so
+     * the slots themselves can be read via plain array reads.)  The
+     * only other memory orderings relied on are maintained in the
+     * course of signalling and activation (see below).  A check that
+     * base == top indicates (momentary) emptiness, but otherwise may
+     * err on the side of possibly making the queue appear nonempty
+     * when a push, pop, or poll have not fully committed, or making
+     * it appear empty when an update of top has not yet been visibly
+     * written.  (Method isEmpty() checks the case of a partially
      * completed removal of the last element.)  Because of this, the
      * poll operation, considered individually, is not wait-free. One
      * thief cannot successfully continue until another in-progress
-     * one (or, if previously empty, a push) completes.  However, in
-     * the aggregate, we ensure at least probabilistic
-     * non-blockingness.  If an attempted steal fails, a thief always
-     * chooses a different random victim target to try next. So, in
-     * order for one thief to progress, it suffices for any
+     * one (or, if previously empty, a push) visibly completes.
+     * However, in the aggregate, we ensure at least probabilistic
+     * non-blockingness.  If an attempted steal fails, a scanning
+     * thief chooses a different random victim target to try next. So,
+     * in order for one thief to progress, it suffices for any
      * in-progress poll or new push on any empty queue to
      * complete. (This is why we normally use method pollAt and its
      * variants that try once at the apparent base index, else
@@ -262,19 +273,6 @@
      * local task processing is in FIFO, not LIFO order, simply by
      * using poll rather than pop.  This can be useful in
      * message-passing frameworks in which tasks are never joined.
-     * However neither mode considers affinities, loads, cache
-     * localities, etc, so rarely provide the best possible
-     * performance on a given machine, but portably provide good
-     * throughput by averaging over these factors.  Further, even if
-     * we did try to use such information, we do not usually have a
-     * basis for exploiting it.  For example, some sets of tasks
-     * profit from cache affinities, but others are harmed by cache
-     * pollution effects. Additionally, even though it requires
-     * scanning, long-term throughput is often best using random
-     * selection rather than directed selection policies, so cheap
-     * randomization of sufficient quality is used whenever
-     * applicable.  Various Marsaglia XorShifts (some with different
-     * shift constants) are inlined at use points.
      *
      * WorkQueues are also used in a similar way for tasks submitted
      * to the pool. We cannot mix these tasks in the same queues used
@@ -286,14 +284,14 @@
      * like workers except that they are restricted to executing local
      * tasks that they submitted (or in the case of CountedCompleters,
      * others with the same root task).  Insertion of tasks in shared
-     * mode requires a lock (mainly to protect in the case of
-     * resizing) but we use only a simple spinlock (using field
-     * qlock), because submitters encountering a busy queue move on to
-     * try or create other queues -- they block only when creating and
-     * registering new queues. Additionally, "qlock" saturates to an
-     * unlockable value (-1) at shutdown. Unlocking still can be and
-     * is performed by cheaper ordered writes of "qlock" in successful
-     * cases, but uses CAS in unsuccessful cases.
+     * mode requires a lock but we use only a simple spinlock (using
+     * field qlock), because submitters encountering a busy queue move
+     * on to try or create other queues -- they block only when
+     * creating and registering new queues. Because it is used only as
+     * a spinlock, unlocking requires only a "releasing" store (using
+     * putOrderedInt).  The qlock is also used during termination
+     * detection, in which case it is forced to a negative
+     * non-lockable value.
      *
      * Management
      * ==========
@@ -320,46 +318,36 @@
      * and their negations (used for thresholding) to fit into 16bit
      * subfields.
      *
-     * Field "runState" holds lockable state bits (STARTED, STOP, etc)
-     * also protecting updates to the workQueues array.  When used as
-     * a lock, it is normally held only for a few instructions (the
-     * only exceptions are one-time array initialization and uncommon
-     * resizing), so is nearly always available after at most a brief
-     * spin. But to be extra-cautious, after spinning, method
-     * awaitRunStateLock (called only if an initial CAS fails), uses a
-     * wait/notify mechanics on a builtin monitor to block when
-     * (rarely) needed. This would be a terrible idea for a highly
-     * contended lock, but most pools run without the lock ever
-     * contending after the spin limit, so this works fine as a more
-     * conservative alternative. Because we don't otherwise have an
-     * internal Object to use as a monitor, the "stealCounter" (an
-     * AtomicLong) is used when available (it too must be lazily
-     * initialized; see externalSubmit).
+     * Field "runState" holds lifetime status, atomically and
+     * monotonically setting STARTED, SHUTDOWN, STOP, and finally
+     * TERMINATED bits.
+     *
+     * Field "auxState" is a ReentrantLock subclass that also
+     * opportunistically holds some other bookkeeping fields accessed
+     * only when locked.  It is mainly used to lock (infrequent)
+     * updates to workQueues.  The auxState instance is itself lazily
+     * constructed (see tryInitialize), requiring a double-check-style
+     * bootstrapping use of field runState, and locking a private
+     * static.
      *
-     * Usages of "runState" vs "ctl" interact in only one case:
-     * deciding to add a worker thread (see tryAddWorker), in which
-     * case the ctl CAS is performed while the lock is held.
-     *
-     * Recording WorkQueues.  WorkQueues are recorded in the
-     * "workQueues" array. The array is created upon first use (see
-     * externalSubmit) and expanded if necessary.  Updates to the
-     * array while recording new workers and unrecording terminated
-     * ones are protected from each other by the runState lock, but
-     * the array is otherwise concurrently readable, and accessed
+     * Field "workQueues" holds references to WorkQueues.  It is
+     * updated (only during worker creation and termination) under the
+     * lock, but is otherwise concurrently readable, and accessed
      * directly. We also ensure that reads of the array reference
-     * itself never become too stale. To simplify index-based
-     * operations, the array size is always a power of two, and all
-     * readers must tolerate null slots. Worker queues are at odd
-     * indices. Shared (submission) queues are at even indices, up to
-     * a maximum of 64 slots, to limit growth even if array needs to
-     * expand to add more workers. Grouping them together in this way
-     * simplifies and speeds up task scanning.
+     * itself never become too stale (for example, re-reading before
+     * each scan). To simplify index-based operations, the array size
+     * is always a power of two, and all readers must tolerate null
+     * slots. Worker queues are at odd indices. Shared (submission)
+     * queues are at even indices, up to a maximum of 64 slots, to
+     * limit growth even if array needs to expand to add more
+     * workers. Grouping them together in this way simplifies and
+     * speeds up task scanning.
      *
      * All worker thread creation is on-demand, triggered by task
      * submissions, replacement of terminated workers, and/or
      * compensation for blocked workers. However, all other support
      * code is set up to work with other policies.  To ensure that we
-     * do not hold on to worker references that would prevent GC, All
+     * do not hold on to worker references that would prevent GC, all
      * accesses to workQueues are via indices into the workQueues
      * array (which is one source of some of the messy code
      * constructions here). In essence, the workQueues array serves as
@@ -386,7 +374,7 @@
      * activating threads in most-recently used order. This improves
      * performance and locality, outweighing the disadvantages of
      * being prone to contention and inability to release a worker
-     * unless it is topmost on stack.  We park/unpark workers after
+     * unless it is topmost on stack.  We block/unblock workers after
      * pushing on the idle worker stack (represented by the lower
      * 32bit subfield of ctl) when they cannot find work.  The top
      * stack state holds the value of the "scanState" field of the
@@ -394,48 +382,14 @@
      * addition to the count subfields (also serving as version
      * stamps) provide protection against Treiber stack ABA effects.
      *
-     * Field scanState is used by both workers and the pool to manage
-     * and track whether a worker is INACTIVE (possibly blocked
-     * waiting for a signal), or SCANNING for tasks (when neither hold
-     * it is busy running tasks).  When a worker is inactivated, its
-     * scanState field is set, and is prevented from executing tasks,
-     * even though it must scan once for them to avoid queuing
-     * races. Note that scanState updates lag queue CAS releases so
-     * usage requires care. When queued, the lower 16 bits of
-     * scanState must hold its pool index. So we place the index there
-     * upon initialization (see registerWorker) and otherwise keep it
-     * there or restore it when necessary.
-     *
-     * Memory ordering.  See "Correct and Efficient Work-Stealing for
-     * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
-     * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
-     * analysis of memory ordering requirements in work-stealing
-     * algorithms similar to the one used here.  We usually need
-     * stronger than minimal ordering because we must sometimes signal
-     * workers, requiring Dekker-like full-fences to avoid lost
-     * signals.  Arranging for enough ordering without expensive
-     * over-fencing requires tradeoffs among the supported means of
-     * expressing access constraints. The most central operations,
-     * taking from queues and updating ctl state, require full-fence
-     * CAS.  Array slots are read using the emulation of volatiles
-     * provided by Unsafe.  Access from other threads to WorkQueue
-     * base, top, and array requires a volatile load of the first of
-     * any of these read.  We use the convention of declaring the
-     * "base" index volatile, and always read it before other fields.
-     * The owner thread must ensure ordered updates, so writes use
-     * ordered intrinsics unless they can piggyback on those for other
-     * writes.  Similar conventions and rationales hold for other
-     * WorkQueue fields (such as "currentSteal") that are only written
-     * by owners but observed by others.
-     *
      * Creating workers. To create a worker, we pre-increment total
      * count (serving as a reservation), and attempt to construct a
      * ForkJoinWorkerThread via its factory. Upon construction, the
      * new thread invokes registerWorker, where it constructs a
      * WorkQueue and is assigned an index in the workQueues array
-     * (expanding the array if necessary). The thread is then
-     * started. Upon any exception across these steps, or null return
-     * from factory, deregisterWorker adjusts counts and records
+     * (expanding the array if necessary). The thread is then started.
+     * Upon any exception across these steps, or null return from
+     * factory, deregisterWorker adjusts counts and records
      * accordingly.  If a null return, the pool continues running with
      * fewer than the target number workers. If exceptional, the
      * exception is propagated, generally to some external caller.
@@ -448,80 +402,106 @@
      * probability of collision low. We cannot use
      * ThreadLocalRandom.getProbe() for similar purposes here because
      * the thread has not started yet, but do so for creating
-     * submission queues for existing external threads.
+     * submission queues for existing external threads (see
+     * externalPush).
+     *
+     * WorkQueue field scanState is used by both workers and the pool
+     * to manage and track whether a worker is UNSIGNALLED (possibly
+     * blocked waiting for a signal).  When a worker is inactivated,
+     * its scanState field is set, and is prevented from executing
+     * tasks, even though it must scan once for them to avoid queuing
+     * races. Note that scanState updates lag queue CAS releases so
+     * usage requires care. When queued, the lower 16 bits of
+     * scanState must hold its pool index. So we place the index there
+     * upon initialization (see registerWorker) and otherwise keep it
+     * there or restore it when necessary.
+     *
+     * The ctl field also serves as the basis for memory
+     * synchronization surrounding activation. This uses a more
+     * efficient version of a Dekker-like rule that task producers and
+     * consumers sync with each other by both writing/CASing ctl (even
+     * if to its current value).  This would be extremely costly. So
+     * we relax it in several ways: (1) Producers only signal when
+     * their queue is empty. Other workers propagate this signal (in
+     * method scan) when they find tasks. (2) Workers only enqueue
+     * after scanning (see below) and not finding any tasks.  (3)
+     * Rather than CASing ctl to its current value in the common case
+     * where no action is required, we reduce write contention by
+     * equivalently prefacing signalWork when called by an external
+     * task producer using a memory access with full-volatile
+     * semantics or a "fullFence". (4) For internal task producers we
+     * rely on the fact that even if no other workers awaken, the
+     * producer itself will eventually see the task and execute it.
+     *
+     * Almost always, too many signals are issued. A task producer
+     * cannot in general tell if some existing worker is in the midst
+     * of finishing one task (or already scanning) and ready to take
+     * another without being signalled. So the producer might instead
+     * activate a different worker that does not find any work, and
+     * then inactivates. This scarcely matters in steady-state
+     * computations involving all workers, but can create contention
+     * and bookkeeping bottlenecks during ramp-up, ramp-down, and small
+     * computations involving only a few workers.
+     *
+     * Scanning. Method scan() performs top-level scanning for tasks.
+     * Each scan traverses (and tries to poll from) each queue in
+     * pseudorandom permutation order by randomly selecting an origin
+     * index and a step value.  (The pseudorandom generator need not
+     * have high-quality statistical properties in the long term, but
+     * just within computations; We use 64bit and 32bit Marsaglia
+     * XorShifts, which are cheap and suffice here.)  Scanning also
+     * employs contention reduction: When scanning workers fail a CAS
+     * polling for work, they soon restart with a different
+     * pseudorandom scan order (thus likely retrying at different
+     * intervals). This improves throughput when many threads are
+     * trying to take tasks from few queues.  Scans do not otherwise
+     * explicitly take into account core affinities, loads, cache
+     * localities, etc, However, they do exploit temporal locality
+     * (which usually approximates these) by preferring to re-poll (up
+     * to POLL_LIMIT times) from the same queue after a successful
+     * poll before trying others.  Restricted forms of scanning occur
+     * in methods helpComplete and findNonEmptyStealQueue, and take
+     * similar but simpler forms.
      *
      * Deactivation and waiting. Queuing encounters several intrinsic
-     * races; most notably that a task-producing thread can miss
-     * seeing (and signalling) another thread that gave up looking for
-     * work but has not yet entered the wait queue.  When a worker
-     * cannot find a task to steal, it deactivates and enqueues. Very
-     * often, the lack of tasks is transient due to GC or OS
-     * scheduling. To reduce false-alarm deactivation, scanners
-     * compute checksums of queue states during sweeps.  (The
-     * stability checks used here and elsewhere are probabilistic
-     * variants of snapshot techniques -- see Herlihy & Shavit.)
-     * Workers give up and try to deactivate only after the sum is
-     * stable across scans. Further, to avoid missed signals, they
-     * repeat this scanning process after successful enqueuing until
-     * again stable.  In this state, the worker cannot take/run a task
-     * it sees until it is released from the queue, so the worker
-     * itself eventually tries to release itself or any successor (see
-     * tryRelease).  Otherwise, upon an empty scan, a deactivated
-     * worker uses an adaptive local spin construction (see awaitWork)
-     * before blocking (via park). Note the unusual conventions about
-     * Thread.interrupts surrounding parking and other blocking:
-     * Because interrupts are used solely to alert threads to check
-     * termination, which is checked anyway upon blocking, we clear
-     * status (using Thread.interrupted) before any call to park, so
-     * that park does not immediately return due to status being set
-     * via some other unrelated call to interrupt in user code.
+     * races; most notably that an inactivating scanning worker can
+     * miss seeing a task produced during a scan.  So when a worker
+     * cannot find a task to steal, it inactivates and enqueues, and
+     * then rescans to ensure that it didn't miss one, reactivating
+     * upon seeing one with probability approximately proportional to
+     * probability of a miss.  (In most cases, the worker will be
+     * signalled before self-signalling, avoiding cascades of multiple
+     * signals for the same task).
      *
-     * Signalling and activation.  Workers are created or activated
-     * only when there appears to be at least one task they might be
-     * able to find and execute.  Upon push (either by a worker or an
-     * external submission) to a previously (possibly) empty queue,
-     * workers are signalled if idle, or created if fewer exist than
-     * the given parallelism level.  These primary signals are
-     * buttressed by others whenever other threads remove a task from
-     * a queue and notice that there are other tasks there as well.
-     * On most platforms, signalling (unpark) overhead time is
-     * noticeably long, and the time between signalling a thread and
-     * it actually making progress can be very noticeably long, so it
-     * is worth offloading these delays from critical paths as much as
-     * possible. Also, because inactive workers are often rescanning
-     * or spinning rather than blocking, we set and clear the "parker"
-     * field of WorkQueues to reduce unnecessary calls to unpark.
-     * (This requires a secondary recheck to avoid missed signals.)
+     * Workers block (in method awaitWork) using park/unpark;
+     * advertising the need for signallers to unpark by setting their
+     * "parker" fields.
      *
      * Trimming workers. To release resources after periods of lack of
      * use, a worker starting to wait when the pool is quiescent will
      * time out and terminate (see awaitWork) if the pool has remained
-     * quiescent for period IDLE_TIMEOUT, increasing the period as the
-     * number of threads decreases, eventually removing all workers.
-     * Also, when more than two spare threads exist, excess threads
-     * are immediately terminated at the next quiescent point.
-     * (Padding by two avoids hysteresis.)
+     * quiescent for period given by IDLE_TIMEOUT_MS, increasing the
+     * period as the number of threads decreases, eventually removing
+     * all workers.
      *
      * Shutdown and Termination. A call to shutdownNow invokes
      * tryTerminate to atomically set a runState bit. The calling
      * thread, as well as every other worker thereafter terminating,
      * helps terminate others by setting their (qlock) status,
      * cancelling their unprocessed tasks, and waking them up, doing
-     * so repeatedly until stable (but with a loop bounded by the
-     * number of workers).  Calls to non-abrupt shutdown() preface
-     * this by checking whether termination should commence. This
-     * relies primarily on the active count bits of "ctl" maintaining
-     * consensus -- tryTerminate is called from awaitWork whenever
-     * quiescent. However, external submitters do not take part in
-     * this consensus.  So, tryTerminate sweeps through queues (until
-     * stable) to ensure lack of in-flight submissions and workers
-     * about to process them before triggering the "STOP" phase of
-     * termination. (Note: there is an intrinsic conflict if
+     * so repeatedly until stable. Calls to non-abrupt shutdown()
+     * preface this by checking whether termination should commence.
+     * This relies primarily on the active count bits of "ctl"
+     * maintaining consensus -- tryTerminate is called from awaitWork
+     * whenever quiescent. However, external submitters do not take
+     * part in this consensus.  So, tryTerminate sweeps through queues
+     * (until stable) to ensure lack of in-flight submissions and
+     * workers about to process them before triggering the "STOP"
+     * phase of termination. (Note: there is an intrinsic conflict if
      * helpQuiescePool is called when shutdown is enabled. Both wait
      * for quiescence, but tryTerminate is biased to not trigger until
      * helpQuiescePool completes.)
      *
-     *
      * Joining Tasks
      * =============
      *
@@ -605,8 +585,13 @@
      * continuation tasks) blocks on a join and there still remain
      * enough threads to ensure liveness.
      *
+     * Spare threads are removed as soon as they notice that the
+     * target parallelism level has been exceeded, in method
+     * tryDropSpare. (Method scan arranges returns for rechecks upon
+     * each probe via the "bound" parameter.)
+     *
      * The compensation mechanism may be bounded.  Bounds for the
-     * commonPool (see commonMaxSpares) better enable JVMs to cope
+     * commonPool (see COMMON_MAX_SPARES) better enable JVMs to cope
      * with programming errors and abuse before running out of
      * resources to do so. In other cases, users may supply factories
      * that limit thread construction. The effects of bounding in this
@@ -728,7 +713,7 @@
      * Default ForkJoinWorkerThreadFactory implementation; creates a
      * new ForkJoinWorkerThread.
      */
-    static final class DefaultForkJoinWorkerThreadFactory
+    private static final class DefaultForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
             return new ForkJoinWorkerThread(pool);
@@ -741,7 +726,7 @@
      * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
      * actually do anything beyond having a unique identity.
      */
-    static final class EmptyTask extends ForkJoinTask<Void> {
+    private static final class EmptyTask extends ForkJoinTask<Void> {
         private static final long serialVersionUID = -7721805057305804111L;
         EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
         public final Void getRawResult() { return null; }
@@ -749,6 +734,16 @@
         public final boolean exec() { return true; }
     }
 
+    /**
+     * Additional fields and lock created upon initialization.
+     */
+    private static final class AuxState extends ReentrantLock {
+        private static final long serialVersionUID = -6001602636862214147L;
+        volatile long stealCount;     // cumulative steal count
+        long indexSeed;               // index bits for registerWorker
+        AuxState() {}
+    }
+
     // Constants shared across ForkJoinPool and WorkQueue
 
     // Bounds
@@ -758,15 +753,23 @@
     static final int SQMASK       = 0x007e;        // max 64 (even) slots
 
     // Masks and units for WorkQueue.scanState and ctl sp subfield
-    static final int SCANNING     = 1;             // false when running tasks
-    static final int INACTIVE     = 1 << 31;       // must be negative
+    static final int UNSIGNALLED  = 1 << 31;       // must be negative
     static final int SS_SEQ       = 1 << 16;       // version count
 
     // Mode bits for ForkJoinPool.config and WorkQueue.config
     static final int MODE_MASK    = 0xffff << 16;  // top half of int
-    static final int LIFO_QUEUE   = 0;
-    static final int FIFO_QUEUE   = 1 << 16;
-    static final int SHARED_QUEUE = 1 << 31;       // must be negative
+    static final int SPARE_WORKER = 1 << 17;       // set if tc > 0 on creation
+    static final int UNREGISTERED = 1 << 18;       // to skip some of deregister
+    static final int FIFO_QUEUE   = 1 << 31;       // must be negative
+    static final int LIFO_QUEUE   = 0;             // for clarity
+    static final int IS_OWNED     = 1;             // low bit 0 if shared
+
+    /**
+     * The maximum number of task executions from the same queue
+     * before checking other queues, bounding unfairness and impact of
+     * infinite user task recursion.  Must be a power of two minus 1.
+     */
+    static final int POLL_LIMIT = (1 << 10) - 1;
 
     /**
      * Queues supporting work-stealing as well as external task
@@ -801,7 +804,8 @@
         static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 
         // Instance fields
-        volatile int scanState;    // versioned, <0: inactive; odd:scanning
+
+        volatile int scanState;    // versioned, negative if inactive
         int stackPred;             // pool stack (ctl) predecessor
         int nsteals;               // number of steals
         int hint;                  // randomization and stealer index hint
@@ -814,7 +818,8 @@
         final ForkJoinWorkerThread owner; // owning thread or null if shared
         volatile Thread parker;    // == owner during call to park; else null
         volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
-        volatile ForkJoinTask<?> currentSteal; // mainly used by helpStealer
+        @sun.misc.Contended("group2") // separate from other fields
+        volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
 
         WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
             this.pool = pool;
@@ -834,7 +839,7 @@
          * Returns the approximate number of tasks in the queue.
          */
         final int queueSize() {
-            int n = base - top;       // non-owner callers must read base first
+            int n = base - top;       // read base first
             return (n >= 0) ? 0 : -n; // ignore transient negative
         }
 
@@ -844,33 +849,31 @@
          * near-empty queue has at least one unclaimed task.
          */
         final boolean isEmpty() {
-            ForkJoinTask<?>[] a; int n, m, s;
-            return ((n = base - (s = top)) >= 0 ||
-                    (n == -1 &&           // possibly one task
-                     ((a = array) == null || (m = a.length - 1) < 0 ||
-                      U.getObject
-                      (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
+            ForkJoinTask<?>[] a; int n, al, s;
+            return ((n = base - (s = top)) >= 0 || // possibly one task
+                    (n == -1 && ((a = array) == null ||
+                                 (al = a.length) == 0 ||
+                                 a[(al - 1) & (s - 1)] == null)));
         }
 
         /**
-         * Pushes a task. Call only by owner in unshared queues.  (The
-         * shared-queue version is embedded in method externalPush.)
+         * Pushes a task. Call only by owner in unshared queues.
          *
          * @param task the task. Caller must ensure non-null.
          * @throws RejectedExecutionException if array cannot be resized
          */
         final void push(ForkJoinTask<?> task) {
-            ForkJoinTask<?>[] a; ForkJoinPool p;
-            int b = base, s = top, n;
-            if ((a = array) != null) {    // ignore if queue removed
-                int m = a.length - 1;     // fenced write for task visibility
-                U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
-                U.putOrderedInt(this, QTOP, s + 1);
-                if ((n = s - b) <= 1) {
-                    if ((p = pool) != null)
-                        p.signalWork(p.workQueues, this);
+            U.storeFence();              // ensure safe publication
+            int s = top, al, d; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (al = a.length) > 0) {
+                a[(al - 1) & s] = task;  // relaxed writes OK
+                top = s + 1;
+                ForkJoinPool p = pool;
+                if ((d = base - s) == 0 && p != null) {
+                    U.fullFence();
+                    p.signalWork();
                 }
-                else if (n >= m)
+                else if (al + d == 1)
                     growArray();
             }
         }
@@ -883,22 +886,23 @@
         final ForkJoinTask<?>[] growArray() {
             ForkJoinTask<?>[] oldA = array;
             int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
-            if (size > MAXIMUM_QUEUE_CAPACITY)
+            if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY)
                 throw new RejectedExecutionException("Queue capacity exceeded");
             int oldMask, t, b;
             ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
-            if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
+            if (oldA != null && (oldMask = oldA.length - 1) > 0 &&
                 (t = top) - (b = base) > 0) {
                 int mask = size - 1;
                 do { // emulate poll from old array, push to new array
-                    ForkJoinTask<?> x;
-                    int oldj = ((b & oldMask) << ASHIFT) + ABASE;
-                    int j    = ((b &    mask) << ASHIFT) + ABASE;
-                    x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
+                    int index = b & oldMask;
+                    long offset = ((long)index << ASHIFT) + ABASE;
+                    ForkJoinTask<?> x = (ForkJoinTask<?>)
+                        U.getObjectVolatile(oldA, offset);
                     if (x != null &&
-                        U.compareAndSwapObject(oldA, oldj, x, null))
-                        U.putObjectVolatile(a, j, x);
+                        U.compareAndSwapObject(oldA, offset, x, null))
+                        a[b & mask] = x;
                 } while (++b != t);
+                U.storeFence();
             }
             return a;
         }
@@ -908,16 +912,16 @@
          * by owner in unshared queues.
          */
         final ForkJoinTask<?> pop() {
-            ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
-            if ((a = array) != null && (m = a.length - 1) >= 0) {
-                for (int s; (s = top - 1) - base >= 0;) {
-                    long j = ((m & s) << ASHIFT) + ABASE;
-                    if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
-                        break;
-                    if (U.compareAndSwapObject(a, j, t, null)) {
-                        U.putOrderedInt(this, QTOP, s);
-                        return t;
-                    }
+            int b = base, s = top, al, i; ForkJoinTask<?>[] a;
+            if ((a = array) != null && b != s && (al = a.length) > 0) {
+                int index = (al - 1) & --s;
+                long offset = ((long)index << ASHIFT) + ABASE;
+                ForkJoinTask<?> t = (ForkJoinTask<?>)
+                    U.getObject(a, offset);
+                if (t != null &&
+                    U.compareAndSwapObject(a, offset, t, null)) {
+                    top = s;
+                    return t;
                 }
             }
             return null;
@@ -929,12 +933,15 @@
          * appear in ForkJoinPool methods scan and helpStealer.
          */
         final ForkJoinTask<?> pollAt(int b) {
-            ForkJoinTask<?> t; ForkJoinTask<?>[] a;
-            if ((a = array) != null) {
-                int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
-                    base == b && U.compareAndSwapObject(a, j, t, null)) {
-                    base = b + 1;
+            ForkJoinTask<?>[] a; int al;
+            if ((a = array) != null && (al = a.length) > 0) {
+                int index = (al - 1) & b;
+                long offset = ((long)index << ASHIFT) + ABASE;
+                ForkJoinTask<?> t = (ForkJoinTask<?>)
+                    U.getObjectVolatile(a, offset);
+                if (t != null && b++ == base &&
+                    U.compareAndSwapObject(a, offset, t, null)) {
+                    base = b;
                     return t;
                 }
             }
@@ -945,20 +952,27 @@
          * Takes next task, if one exists, in FIFO order.
          */
         final ForkJoinTask<?> poll() {
-            ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
-            while ((b = base) - top < 0 && (a = array) != null) {
-                int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
-                if (base == b) {
-                    if (t != null) {
-                        if (U.compareAndSwapObject(a, j, t, null)) {
-                            base = b + 1;
-                            return t;
+            for (;;) {
+                int b = base, s = top, d, al; ForkJoinTask<?>[] a;
+                if ((a = array) != null && (d = b - s) < 0 &&
+                    (al = a.length) > 0) {
+                    int index = (al - 1) & b;
+                    long offset = ((long)index << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        U.getObjectVolatile(a, offset);
+                    if (b++ == base) {
+                        if (t != null) {
+                            if (U.compareAndSwapObject(a, offset, t, null)) {
+                                base = b;
+                                return t;
+                            }
                         }
+                        else if (d == -1)
+                            break; // now empty
                     }
-                    else if (b + 1 == top) // now empty
-                        break;
                 }
+                else
+                    break;
             }
             return null;
         }
@@ -967,37 +981,100 @@
          * Takes next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> nextLocalTask() {
-            return (config & FIFO_QUEUE) == 0 ? pop() : poll();
+            return (config < 0) ? poll() : pop();
         }
 
         /**
          * Returns next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> peek() {
-            ForkJoinTask<?>[] a = array; int m;
-            if (a == null || (m = a.length - 1) < 0)
-                return null;
-            int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base;
-            int j = ((i & m) << ASHIFT) + ABASE;
-            return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+            int al; ForkJoinTask<?>[] a;
+            return ((a = array) != null && (al = a.length) > 0) ?
+                a[(al - 1) & (config < 0 ? base : top - 1)] : null;
         }
 
         /**
          * Pops the given task only if it is at the current top.
-         * (A shared version is available only via FJP.tryExternalUnpush)
-        */
-        final boolean tryUnpush(ForkJoinTask<?> t) {
-            ForkJoinTask<?>[] a; int s;
-            if ((a = array) != null && (s = top) != base &&
-                U.compareAndSwapObject
-                (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
-                U.putOrderedInt(this, QTOP, s);
-                return true;
+         */
+        final boolean tryUnpush(ForkJoinTask<?> task) {
+            int b = base, s = top, al; ForkJoinTask<?>[] a;
+            if ((a = array) != null && b != s && (al = a.length) > 0) {
+                int index = (al - 1) & --s;
+                long offset = ((long)index << ASHIFT) + ABASE;
+                if (U.compareAndSwapObject(a, offset, task, null)) {
+                    top = s;
+                    return true;
+                }
             }
             return false;
         }
 
         /**
+         * Shared version of push. Fails if already locked.
+         *
+         * @return status: > 0 locked, 0 possibly was empty, < 0 was nonempty
+         */
+        final int sharedPush(ForkJoinTask<?> task) {
+            int stat;
+            if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+                int b = base, s = top, al, d; ForkJoinTask<?>[] a;
+                if ((a = array) != null && (al = a.length) > 0 &&
+                    al - 1 + (d = b - s) > 0) {
+                    a[(al - 1) & s] = task;
+                    top = s + 1;                 // relaxed writes OK here
+                    qlock = 0;
+                    stat = (d < 0 && b == base) ? d : 0;
+                }
+                else {
+                    growAndSharedPush(task);
+                    stat = 0;
+                }
+            }
+            else
+                stat = 1;
+            return stat;
+        }
+
+        /**
+         * Helper for sharedPush; called only when locked and resize
+         * needed.
+         */
+        private void growAndSharedPush(ForkJoinTask<?> task) {
+            try {
+                growArray();
+                int s = top, al; ForkJoinTask<?>[] a;
+                if ((a = array) != null && (al = a.length) > 0) {
+                    a[(al - 1) & s] = task;
+                    top = s + 1;
+                }
+            } finally {
+                qlock = 0;
+            }
+        }
+
+        /**
+         * Shared version of pop.
+         */
+        final boolean trySharedUnpush(ForkJoinTask<?> task) {
+            boolean popped = false;
+            int s = top - 1, al; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (al = a.length) > 0) {
+                int index = (al - 1) & s;
+                long offset = ((long)index << ASHIFT) + ABASE;
+                ForkJoinTask<?> t = (ForkJoinTask<?>) U.getObject(a, offset);
+                if (t == task &&
+                    U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+                    if (U.compareAndSwapObject(a, offset, task, null)) {
+                        popped = true;
+                        top = s;
+                    }
+                    U.putOrderedInt(this, QLOCK, 0);
+                }
+            }
+            return popped;
+        }
+
+        /**
          * Removes and cancels all known tasks, ignoring any exceptions.
          */
         final void cancelAll() {
@@ -1017,66 +1094,88 @@
         // Specialized execution methods
 
         /**
-         * Polls and runs tasks until empty.
+         * Pops and executes up to POLL_LIMIT tasks or until empty.
          */
-        final void pollAndExecAll() {
-            for (ForkJoinTask<?> t; (t = poll()) != null;)
-                t.doExec();
+        final void localPopAndExec() {
+            for (int nexec = 0;;) {
+                int b = base, s = top, al; ForkJoinTask<?>[] a;
+                if ((a = array) != null && b != s && (al = a.length) > 0) {
+                    int index = (al - 1) & --s;
+                    long offset = ((long)index << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        U.getAndSetObject(a, offset, null);
+                    if (t != null) {
+                        top = s;
+                        (currentSteal = t).doExec();
+                        if (++nexec > POLL_LIMIT)
+                            break;
+                    }
+                    else
+                        break;
+                }
+                else
+                    break;
+            }
         }
 
         /**
-         * Removes and executes all local tasks. If LIFO, invokes
-         * pollAndExecAll. Otherwise implements a specialized pop loop
-         * to exec until empty.
+         * Polls and executes up to POLL_LIMIT tasks or until empty.
          */
-        final void execLocalTasks() {
-            int b = base, m, s;
-            ForkJoinTask<?>[] a = array;
-            if (b - (s = top - 1) <= 0 && a != null &&
-                (m = a.length - 1) >= 0) {
-                if ((config & FIFO_QUEUE) == 0) {
-                    for (ForkJoinTask<?> t;;) {
-                        if ((t = (ForkJoinTask<?>)U.getAndSetObject
-                             (a, ((m & s) << ASHIFT) + ABASE, null)) == null)
-                            break;
-                        U.putOrderedInt(this, QTOP, s);
+        final void localPollAndExec() {
+            for (int nexec = 0;;) {
+                int b = base, s = top, al; ForkJoinTask<?>[] a;
+                if ((a = array) != null && b != s && (al = a.length) > 0) {
+                    int index = (al - 1) & b++;
+                    long offset = ((long)index << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        U.getAndSetObject(a, offset, null);
+                    if (t != null) {
+                        base = b;
                         t.doExec();
-                        if (base - (s = top - 1) > 0)
+                        if (++nexec > POLL_LIMIT)
                             break;
                     }
                 }
                 else
-                    pollAndExecAll();
+                    break;
             }
         }
 
         /**
-         * Executes the given task and any remaining local tasks.
+         * Executes the given task and (some) remaining local tasks.
          */
         final void runTask(ForkJoinTask<?> task) {
             if (task != null) {
-                scanState &= ~SCANNING; // mark as busy
-                (currentSteal = task).doExec();
-                U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC
-                execLocalTasks();
+                task.doExec();
+                if (config < 0)
+                    localPollAndExec();
+                else
+                    localPopAndExec();
+                int ns = ++nsteals;
                 ForkJoinWorkerThread thread = owner;
-                if (++nsteals < 0)      // collect on overflow
+                currentSteal = null;
+                if (ns < 0)           // collect on overflow
                     transferStealCount(pool);
-                scanState |= SCANNING;
                 if (thread != null)
                     thread.afterTopLevelExec();
             }
         }
 
         /**
-         * Adds steal count to pool stealCounter if it exists, and resets.
+         * Adds steal count to pool steal count if it exists, and resets.
          */
         final void transferStealCount(ForkJoinPool p) {
-            AtomicLong sc;
-            if (p != null && (sc = p.stealCounter) != null) {
-                int s = nsteals;
+            AuxState aux;
+            if (p != null && (aux = p.auxState) != null) {
+                long s = nsteals;
                 nsteals = 0;            // if negative, correct for overflow
-                sc.getAndAdd((long)(s < 0 ? Integer.MAX_VALUE : s));
+                if (s < 0) s = Integer.MAX_VALUE;
+                aux.lock();
+                try {
+                    aux.stealCount += s;
+                } finally {
+                    aux.unlock();
+                }
             }
         }
 
@@ -1087,36 +1186,46 @@
          * @return true if queue empty and task not known to be done
          */
         final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
-            ForkJoinTask<?>[] a; int m, s, b, n;
-            if ((a = array) != null && (m = a.length - 1) >= 0 &&
-                task != null) {
-                while ((n = (s = top) - (b = base)) > 0) {
-                    for (ForkJoinTask<?> t;;) {      // traverse from s to b
-                        long j = ((--s & m) << ASHIFT) + ABASE;
-                        if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
-                            return s + 1 == top;     // shorter than expected
+            if (task != null && task.status >= 0) {
+                int b, s, d, al; ForkJoinTask<?>[] a;
+                while ((d = (b = base) - (s = top)) < 0 &&
+                       (a = array) != null && (al = a.length) > 0) {
+                    for (;;) {      // traverse from s to b
+                        int index = --s & (al - 1);
+                        long offset = (index << ASHIFT) + ABASE;
+                        ForkJoinTask<?> t = (ForkJoinTask<?>)
+                            U.getObjectVolatile(a, offset);
+                        if (t == null)
+                            break;                   // restart
                         else if (t == task) {
                             boolean removed = false;
                             if (s + 1 == top) {      // pop
-                                if (U.compareAndSwapObject(a, j, task, null)) {
-                                    U.putOrderedInt(this, QTOP, s);
+                                if (U.compareAndSwapObject(a, offset, t, null)) {
+                                    top = s;
                                     removed = true;
                                 }
                             }
                             else if (base == b)      // replace with proxy
-                                removed = U.compareAndSwapObject(
-                                    a, j, task, new EmptyTask());
-                            if (removed)
-                                task.doExec();
+                                removed = U.compareAndSwapObject(a, offset, t,
+                                                                 new EmptyTask());
+                            if (removed) {
+                                ForkJoinTask<?> ps = currentSteal;
+                                (currentSteal = task).doExec();
+                                currentSteal = ps;
+                            }
                             break;
                         }
                         else if (t.status < 0 && s + 1 == top) {
-                            if (U.compareAndSwapObject(a, j, t, null))
-                                U.putOrderedInt(this, QTOP, s);
+                            if (U.compareAndSwapObject(a, offset, t, null)) {
+                                top = s;
+                            }
                             break;                  // was cancelled
                         }
-                        if (--n == 0)
+                        else if (++d == 0) {
+                            if (base != b)          // rescan
+                                break;
                             return false;
+                        }
                     }
                     if (task.status < 0)
                         return false;
@@ -1130,27 +1239,31 @@
          * in either shared or owned mode. Used only by helpComplete.
          */
         final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
-            int s; ForkJoinTask<?>[] a; Object o;
-            if (base - (s = top) < 0 && (a = array) != null) {
-                long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
-                if ((o = U.getObjectVolatile(a, j)) != null &&
-                    (o instanceof CountedCompleter)) {
+            int b = base, s = top, al; ForkJoinTask<?>[] a;
+            if ((a = array) != null && b != s && (al = a.length) > 0) {
+                int index = (al - 1) & (s - 1);
+                long offset = ((long)index << ASHIFT) + ABASE;
+                ForkJoinTask<?> o = (ForkJoinTask<?>)
+                    U.getObjectVolatile(a, offset);
+                if (o instanceof CountedCompleter) {
                     CountedCompleter<?> t = (CountedCompleter<?>)o;
                     for (CountedCompleter<?> r = t;;) {
                         if (r == task) {
-                            if (mode < 0) { // must lock
+                            if ((mode & IS_OWNED) == 0) {
+                                boolean popped;
                                 if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                                    if (top == s && array == a &&
-                                        U.compareAndSwapObject(a, j, t, null)) {
-                                        U.putOrderedInt(this, QTOP, s - 1);
-                                        U.putOrderedInt(this, QLOCK, 0);
+                                    if (popped =
+                                        U.compareAndSwapObject(a, offset,
+                                                               t, null))
+                                        top = s - 1;
+                                    U.putOrderedInt(this, QLOCK, 0);
+                                    if (popped)
                                         return t;
-                                    }
-                                    U.compareAndSwapInt(this, QLOCK, 1, 0);
                                 }
                             }
-                            else if (U.compareAndSwapObject(a, j, t, null)) {
-                                U.putOrderedInt(this, QTOP, s - 1);
+                            else if (U.compareAndSwapObject(a, offset,
+                                                            t, null)) {
+                                top = s - 1;
                                 return t;
                             }
                             break;
@@ -1174,36 +1287,40 @@
          * the base index, forced negative.
          */
         final int pollAndExecCC(CountedCompleter<?> task) {
-            int b, h; ForkJoinTask<?>[] a; Object o;
-            if ((b = base) - top >= 0 || (a = array) == null)
-                h = b | Integer.MIN_VALUE;  // to sense movement on re-poll
-            else {
-                long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                if ((o = U.getObjectVolatile(a, j)) == null)
-                    h = 2;                  // retryable
+            ForkJoinTask<?>[] a;
+            int b = base, s = top, al, h;
+            if ((a = array) != null && b != s && (al = a.length) > 0) {
+                int index = (al - 1) & b;
+                long offset = ((long)index << ASHIFT) + ABASE;
+                ForkJoinTask<?> o = (ForkJoinTask<?>)
+                    U.getObjectVolatile(a, offset);
+                if (o == null)
+                    h = 2;                      // retryable
                 else if (!(o instanceof CountedCompleter))
-                    h = -1;                 // unmatchable
+                    h = -1;                     // unmatchable
                 else {
                     CountedCompleter<?> t = (CountedCompleter<?>)o;
                     for (CountedCompleter<?> r = t;;) {
                         if (r == task) {
-                            if (base == b &&
-                                U.compareAndSwapObject(a, j, t, null)) {
-                                base = b + 1;
+                            if (b++ == base &&
+                                U.compareAndSwapObject(a, offset, t, null)) {
+                                base = b;
                                 t.doExec();
-                                h = 1;      // success
+                                h = 1;          // success
                             }
                             else
-                                h = 2;      // lost CAS
+                                h = 2;          // lost CAS
                             break;
                         }
                         else if ((r = r.completer) == null) {
-                            h = -1;         // unmatched
+                            h = -1;             // unmatched
                             break;
                         }
                     }
                 }
             }
+            else
+                h = b | Integer.MIN_VALUE;      // to sense movement on re-poll
             return h;
         }
 
@@ -1220,29 +1337,20 @@
         }
 
         // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final sun.misc.Unsafe U;
-        private static final int  ABASE;
-        private static final int  ASHIFT;
-        private static final long QTOP;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
         private static final long QLOCK;
-        private static final long QCURRENTSTEAL;
+        private static final int ABASE;
+        private static final int ASHIFT;
         static {
             try {
-                U = sun.misc.Unsafe.getUnsafe();
-                Class<?> wk = WorkQueue.class;
-                Class<?> ak = ForkJoinTask[].class;
-                QTOP = U.objectFieldOffset
-                    (wk.getDeclaredField("top"));
                 QLOCK = U.objectFieldOffset
-                    (wk.getDeclaredField("qlock"));
-                QCURRENTSTEAL = U.objectFieldOffset
-                    (wk.getDeclaredField("currentSteal"));
-                ABASE = U.arrayBaseOffset(ak);
-                int scale = U.arrayIndexScale(ak);
+                    (WorkQueue.class.getDeclaredField("qlock"));
+                ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
+                int scale = U.arrayIndexScale(ForkJoinTask[].class);
                 if ((scale & (scale - 1)) != 0)
-                    throw new Error("data type scale not a power of two");
+                    throw new Error("array index scale not a power of two");
                 ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-            } catch (Exception e) {
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -1259,9 +1367,9 @@
 
     /**
      * Permission required for callers of methods that may start or
-     * kill threads.
+     * kill threads.  Also used as a static lock in tryInitialize.
      */
-    private static final RuntimePermission modifyThreadPermission;
+    static final RuntimePermission modifyThreadPermission;
 
     /**
      * Common (static) pool. Non-null for public use unless a static
@@ -1277,12 +1385,12 @@
      * common.parallelism field to be zero, but in that case still report
      * parallelism as 1 to reflect resulting caller-runs mechanics.
      */
-    static final int commonParallelism;
+    static final int COMMON_PARALLELISM;
 
     /**
      * Limit on spare thread construction in tryCompensate.
      */
-    private static int commonMaxSpares;
+    private static final int COMMON_MAX_SPARES;
 
     /**
      * Sequence number for creating workerNamePrefix.
@@ -1300,44 +1408,28 @@
     // static configuration constants
 
     /**
-     * Initial timeout value (in nanoseconds) for the thread
+     * Initial timeout value (in milliseconds) for the thread
      * triggering quiescence to park waiting for new work. On timeout,
-     * the thread will instead try to shrink the number of
-     * workers. The value should be large enough to avoid overly
-     * aggressive shrinkage during most transient stalls (long GCs
-     * etc).
+     * the thread will instead try to shrink the number of workers.
+     * The value should be large enough to avoid overly aggressive
+     * shrinkage during most transient stalls (long GCs etc).
      */
-    private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec
-
-    /**
-     * Tolerance for idle timeouts, to cope with timer undershoots
-     */
-    private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L;  // 20ms
+    private static final long IDLE_TIMEOUT_MS = 2000L; // 2sec
 
     /**
-     * The initial value for commonMaxSpares during static
-     * initialization unless overridden using System property
-     * "java.util.concurrent.ForkJoinPool.common.maximumSpares".  The
-     * default value is far in excess of normal requirements, but also
-     * far short of MAX_CAP and typical OS thread limits, so allows
-     * JVMs to catch misuse/abuse before running out of resources
-     * needed to do so.
+     * Tolerance for idle timeouts, to cope with timer undershoots.
      */
-    private static final int DEFAULT_COMMON_MAX_SPARES = 256;
+    private static final long TIMEOUT_SLOP_MS =   20L; // 20ms
 
     /**
-     * Number of times to spin-wait before blocking. The spins (in
-     * awaitRunStateLock and awaitWork) currently use randomized
-     * spins. Currently set to zero to reduce CPU usage.
-     *
-     * If greater than zero the value of SPINS must be a power
-     * of two, at least 4.  A value of 2048 causes spinning for a
-     * small fraction of typical context-switch times.
-     *
-     * If/when MWAIT-like intrinsics becomes available, they
-     * may allow quieter spinning.
+     * The default value for COMMON_MAX_SPARES.  Overridable using the
+     * "java.util.concurrent.ForkJoinPool.common.maximumSpares" system
+     * property.  The default value is far in excess of normal
+     * requirements, but also far short of MAX_CAP and typical OS
+     * thread limits, so allows JVMs to catch misuse/abuse before
+     * running out of resources needed to do so.
      */
-    private static final int SPINS  = 0;
+    private static final int DEFAULT_COMMON_MAX_SPARES = 256;
 
     /**
      * Increment for seed generators. See class ThreadLocal for
@@ -1384,92 +1476,49 @@
     private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
 
     // runState bits: SHUTDOWN must be negative, others arbitrary powers of two
-    private static final int  RSLOCK     = 1;
-    private static final int  RSIGNAL    = 1 << 1;
-    private static final int  STARTED    = 1 << 2;
-    private static final int  STOP       = 1 << 29;
-    private static final int  TERMINATED = 1 << 30;
+    private static final int  STARTED    = 1;
+    private static final int  STOP       = 1 << 1;
+    private static final int  TERMINATED = 1 << 2;
     private static final int  SHUTDOWN   = 1 << 31;
 
     // Instance fields
     volatile long ctl;                   // main pool control
-    volatile int runState;               // lockable status
+    volatile int runState;
     final int config;                    // parallelism, mode
-    int indexSeed;                       // to generate worker index
+    AuxState auxState;                   // lock, steal counts
     volatile WorkQueue[] workQueues;     // main registry
+    final String workerNamePrefix;       // to create worker name string
     final ForkJoinWorkerThreadFactory factory;
     final UncaughtExceptionHandler ueh;  // per-worker UEH
-    final String workerNamePrefix;       // to create worker name string
-    volatile AtomicLong stealCounter;    // also used as sync monitor
-
-    /**
-     * Acquires the runState lock; returns current (locked) runState.
-     */
-    private int lockRunState() {
-        int rs;
-        return ((((rs = runState) & RSLOCK) != 0 ||
-                 !U.compareAndSwapInt(this, RUNSTATE, rs, rs |= RSLOCK)) ?
-                awaitRunStateLock() : rs);
-    }
 
     /**
-     * Spins and/or blocks until runstate lock is available.  See
-     * above for explanation.
+     * Instantiates fields upon first submission, or upon shutdown if
+     * no submissions. If checkTermination true, also responds to
+     * termination by external calls submitting tasks.
      */
-    private int awaitRunStateLock() {
-        Object lock;
-        boolean wasInterrupted = false;
-        for (int spins = SPINS, r = 0, rs, ns;;) {
-            if (((rs = runState) & RSLOCK) == 0) {
-                if (U.compareAndSwapInt(this, RUNSTATE, rs, ns = rs | RSLOCK)) {
-                    if (wasInterrupted) {
-                        try {
-                            Thread.currentThread().interrupt();
-                        } catch (SecurityException ignore) {
-                        }
-                    }
-                    return ns;
-                }
-            }
-            else if (r == 0)
-                r = ThreadLocalRandom.nextSecondarySeed();
-            else if (spins > 0) {
-                r ^= r << 6; r ^= r >>> 21; r ^= r << 7; // xorshift
-                if (r >= 0)
-                    --spins;
-            }
-            else if ((rs & STARTED) == 0 || (lock = stealCounter) == null)
-                Thread.yield();   // initialization race
-            else if (U.compareAndSwapInt(this, RUNSTATE, rs, rs | RSIGNAL)) {
-                synchronized (lock) {
-                    if ((runState & RSIGNAL) != 0) {
-                        try {
-                            lock.wait();
-                        } catch (InterruptedException ie) {
-                            if (!(Thread.currentThread() instanceof
-                                  ForkJoinWorkerThread))
-                                wasInterrupted = true;
-                        }
-                    }
-                    else
-                        lock.notifyAll();
+    private void tryInitialize(boolean checkTermination) {
+        if (runState == 0) { // bootstrap by locking static field
+            int p = config & SMASK;
+            int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
+            n |= n >>> 1;    // create workQueues array with size a power of two
+            n |= n >>> 2;
+            n |= n >>> 4;
+            n |= n >>> 8;
+            n |= n >>> 16;
+            n = ((n + 1) << 1) & SMASK;
+            AuxState aux = new AuxState();
+            WorkQueue[] ws = new WorkQueue[n];
+            synchronized (modifyThreadPermission) { // double-check
+                if (runState == 0) {
+                    workQueues = ws;
+                    auxState = aux;
+                    runState = STARTED;
                 }
             }
         }
-    }
-
-    /**
-     * Unlocks and sets runState to newRunState.
-     *
-     * @param oldRunState a value returned from lockRunState
-     * @param newRunState the next value (must have lock bit clear).
-     */
-    private void unlockRunState(int oldRunState, int newRunState) {
-        if (!U.compareAndSwapInt(this, RUNSTATE, oldRunState, newRunState)) {
-            Object lock = stealCounter;
-            runState = newRunState;              // clears RSIGNAL bit
-            if (lock != null)
-                synchronized (lock) { lock.notifyAll(); }
+        if (checkTermination && runState < 0) {
+            tryTerminate(false, false); // help terminate
+            throw new RejectedExecutionException();
         }
     }
 
@@ -1480,14 +1529,18 @@
      * count has already been incremented as a reservation.  Invokes
      * deregisterWorker on any failure.
      *
+     * @param isSpare true if this is a spare thread
      * @return true if successful
      */
-    private boolean createWorker() {
+    private boolean createWorker(boolean isSpare) {
         ForkJoinWorkerThreadFactory fac = factory;
         Throwable ex = null;
         ForkJoinWorkerThread wt = null;
+        WorkQueue q;
         try {
             if (fac != null && (wt = fac.newThread(this)) != null) {
+                if (isSpare && (q = wt.workQueue) != null)
+                    q.config |= SPARE_WORKER;
                 wt.start();
                 return true;
             }
@@ -1507,21 +1560,12 @@
      * this holds (otherwise, a new worker is not needed).
      */
     private void tryAddWorker(long c) {
-        boolean add = false;
         do {
             long nc = ((AC_MASK & (c + AC_UNIT)) |
                        (TC_MASK & (c + TC_UNIT)));
-            if (ctl == c) {
-                int rs, stop;                 // check if terminating
-                if ((stop = (rs = lockRunState()) & STOP) == 0)
-                    add = U.compareAndSwapLong(this, CTL, c, nc);
-                unlockRunState(rs, rs & ~RSLOCK);
-                if (stop != 0)
-                    break;
-                if (add) {
-                    createWorker();
-                    break;
-                }
+            if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) {
+                createWorker(false);
+                break;
             }
         } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
     }
@@ -1535,37 +1579,39 @@
      */
     final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
         UncaughtExceptionHandler handler;
+        AuxState aux;
         wt.setDaemon(true);                           // configure thread
         if ((handler = ueh) != null)
             wt.setUncaughtExceptionHandler(handler);
         WorkQueue w = new WorkQueue(this, wt);
         int i = 0;                                    // assign a pool index
         int mode = config & MODE_MASK;
-        int rs = lockRunState();
-        try {
-            WorkQueue[] ws; int n;                    // skip if no array
-            if ((ws = workQueues) != null && (n = ws.length) > 0) {
-                int s = indexSeed += SEED_INCREMENT;  // unlikely to collide
-                int m = n - 1;
-                i = ((s << 1) | 1) & m;               // odd-numbered indices
-                if (ws[i] != null) {                  // collision
-                    int probes = 0;                   // step by approx half n
-                    int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
-                    while (ws[i = (i + step) & m] != null) {
-                        if (++probes >= n) {
-                            workQueues = ws = Arrays.copyOf(ws, n <<= 1);
-                            m = n - 1;
-                            probes = 0;
+        if ((aux = auxState) != null) {
+            aux.lock();
+            try {
+                int s = (int)(aux.indexSeed += SEED_INCREMENT), n, m;
+                WorkQueue[] ws = workQueues;
+                if (ws != null && (n = ws.length) > 0) {
+                    i = (m = n - 1) & ((s << 1) | 1); // odd-numbered indices
+                    if (ws[i] != null) {              // collision
+                        int probes = 0;               // step by approx half n
+                        int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
+                        while (ws[i = (i + step) & m] != null) {
+                            if (++probes >= n) {
+                                workQueues = ws = Arrays.copyOf(ws, n <<= 1);
+                                m = n - 1;
+                                probes = 0;
+                            }
                         }
                     }
+                    w.hint = s;                       // use as random seed
+                    w.config = i | mode;
+                    w.scanState = i | (s & 0x7fff0000); // random seq bits
+                    ws[i] = w;
                 }
-                w.hint = s;                           // use as random seed
-                w.config = i | mode;
-                w.scanState = i;                      // publication fence
-                ws[i] = w;
+            } finally {
+                aux.unlock();
             }
-        } finally {
-            unlockRunState(rs, rs & ~RSLOCK);
         }
         wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
         return w;
@@ -1583,31 +1629,40 @@
     final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
         WorkQueue w = null;
         if (wt != null && (w = wt.workQueue) != null) {
-            WorkQueue[] ws;                           // remove index from array
+            AuxState aux; WorkQueue[] ws;          // remove index from array
             int idx = w.config & SMASK;
-            int rs = lockRunState();
-            if ((ws = workQueues) != null && ws.length > idx && ws[idx] == w)
-                ws[idx] = null;
-            unlockRunState(rs, rs & ~RSLOCK);
+            int ns = w.nsteals;
+            if ((aux = auxState) != null) {
+                aux.lock();
+                try {
+                    if ((ws = workQueues) != null && ws.length > idx &&
+                        ws[idx] == w)
+                        ws[idx] = null;
+                    aux.stealCount += ns;
+                } finally {
+                    aux.unlock();
+                }
+            }
         }
-        long c;                                       // decrement counts
-        do {} while (!U.compareAndSwapLong
-                     (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
-                                           (TC_MASK & (c - TC_UNIT)) |
-                                           (SP_MASK & c))));
+        if (w == null || (w.config & UNREGISTERED) == 0) { // else pre-adjusted
+            long c;                                   // decrement counts
+            do {} while (!U.compareAndSwapLong
+                         (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
+                                               (TC_MASK & (c - TC_UNIT)) |
+                                               (SP_MASK & c))));
+        }
         if (w != null) {
+            w.currentSteal = null;
             w.qlock = -1;                             // ensure set
-            w.transferStealCount(this);
             w.cancelAll();                            // cancel remaining tasks
         }
-        for (;;) {                                    // possibly replace
-            WorkQueue[] ws; int m, sp;
-            if (tryTerminate(false, false) || w == null || w.array == null ||
-                (runState & STOP) != 0 || (ws = workQueues) == null ||
-                (m = ws.length - 1) < 0)              // already terminating
+        while (tryTerminate(false, false) >= 0) {     // possibly replace
+            WorkQueue[] ws; int wl, sp; long c;
+            if (w == null || w.array == null ||
+                (ws = workQueues) == null || (wl = ws.length) <= 0)
                 break;
-            if ((sp = (int)(c = ctl)) != 0) {         // wake up replacement
-                if (tryRelease(c, ws[sp & m], AC_UNIT))
+            else if ((sp = (int)(c = ctl)) != 0) {    // wake up replacement
+                if (tryRelease(c, ws[(wl - 1) & sp], AC_UNIT))
                     break;
             }
             else if (ex != null && (c & ADD_WORKER) != 0L) {
@@ -1627,35 +1682,33 @@
 
     /**
      * Tries to create or activate a worker if too few are active.
-     *
-     * @param ws the worker array to use to find signallees
-     * @param q a WorkQueue --if non-null, don't retry if now empty
      */
-    final void signalWork(WorkQueue[] ws, WorkQueue q) {
-        long c; int sp, i; WorkQueue v; Thread p;
-        while ((c = ctl) < 0L) {                       // too few active
-            if ((sp = (int)c) == 0) {                  // no idle workers
-                if ((c & ADD_WORKER) != 0L)            // too few workers
+    final void signalWork() {
+        for (;;) {
+            long c; int sp, i; WorkQueue v; WorkQueue[] ws;
+            if ((c = ctl) >= 0L)                      // enough workers
+                break;
+            else if ((sp = (int)c) == 0) {            // no idle workers
+                if ((c & ADD_WORKER) != 0L)           // too few workers
                     tryAddWorker(c);
                 break;
             }
-            if (ws == null)                            // unstarted/terminated
-                break;
-            if (ws.length <= (i = sp & SMASK))         // terminated
-                break;
-            if ((v = ws[i]) == null)                   // terminating
-                break;
-            int vs = (sp + SS_SEQ) & ~INACTIVE;        // next scanState
-            int d = sp - v.scanState;                  // screen CAS
-            long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred);
-            if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = vs;                      // activate v
-                if ((p = v.parker) != null)
-                    U.unpark(p);
-                break;
+            else if ((ws = workQueues) == null)
+                break;                                // unstarted/terminated
+            else if (ws.length <= (i = sp & SMASK))
+                break;                                // terminated
+            else if ((v = ws[i]) == null)
+                break;                                // terminating
+            else {
+                int ns = sp & ~UNSIGNALLED;
+                int vs = v.scanState;
+                long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
+                if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
+                    v.scanState = ns;
+                    LockSupport.unpark(v.parker);
+                    break;
+                }
             }
-            if (q != null && q.base == q.top)          // no more work
-                break;
         }
     }
 
@@ -1670,174 +1723,287 @@
      * @return true if successful
      */
     private boolean tryRelease(long c, WorkQueue v, long inc) {
-        int sp = (int)c, vs = (sp + SS_SEQ) & ~INACTIVE; Thread p;
-        if (v != null && v.scanState == sp) {          // v is at top of stack
-            long nc = (UC_MASK & (c + inc)) | (SP_MASK & v.stackPred);
-            if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = vs;
-                if ((p = v.parker) != null)
-                    U.unpark(p);
+        int sp = (int)c, ns = sp & ~UNSIGNALLED;
+        if (v != null) {
+            int vs = v.scanState;
+            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + inc));
+            if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
+                v.scanState = ns;
+                LockSupport.unpark(v.parker);
                 return true;
             }
         }
         return false;
     }
 
-    // Scanning for tasks
+    /**
+     * With approx probability of a missed signal, tries (once) to
+     * reactivate worker w (or some other worker), failing if stale or
+     * known to be already active.
+     *
+     * @param w the worker
+     * @param ws the workQueue array to use
+     * @param r random seed
+     */
+    private void tryReactivate(WorkQueue w, WorkQueue[] ws, int r) {
+        long c; int sp, wl; WorkQueue v;
+        if ((sp = (int)(c = ctl)) != 0 && w != null &&
+            ws != null && (wl = ws.length) > 0 &&
+            ((sp ^ r) & SS_SEQ) == 0 &&
+            (v = ws[(wl - 1) & sp]) != null) {
+            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
+            int ns = sp & ~UNSIGNALLED;
+            if (w.scanState < 0 &&
+                v.scanState == sp &&
+                U.compareAndSwapLong(this, CTL, c, nc)) {
+                v.scanState = ns;
+                LockSupport.unpark(v.parker);
+            }
+        }
+    }
+
+    /**
+     * If worker w exists and is active, enqueues and sets status to inactive.
+     *
+     * @param w the worker
+     * @param ss current (non-negative) scanState
+     */
+    private void inactivate(WorkQueue w, int ss) {
+        int ns = (ss + SS_SEQ) | UNSIGNALLED;
+        long lc = ns & SP_MASK, nc, c;
+        if (w != null) {
+            w.scanState = ns;
+            do {
+                nc = lc | (UC_MASK & ((c = ctl) - AC_UNIT));
+                w.stackPred = (int)c;
+            } while (!U.compareAndSwapLong(this, CTL, c, nc));
+        }
+    }
+
+    /**
+     * Possibly blocks worker w waiting for signal, or returns
+     * negative status if the worker should terminate. May return
+     * without status change if multiple stale unparks and/or
+     * interrupts occur.
+     *
+     * @param w the calling worker
+     * @return negative if w should terminate
+     */
+    private int awaitWork(WorkQueue w) {
+        int stat = 0;
+        if (w != null && w.scanState < 0) {
+            long c = ctl;
+            if ((int)(c >> AC_SHIFT) + (config & SMASK) <= 0)
+                stat = timedAwaitWork(w, c);     // possibly quiescent
+            else if ((runState & STOP) != 0)
+                stat = w.qlock = -1;             // pool terminating
+            else if (w.scanState < 0) {
+                w.parker = Thread.currentThread();
+                if (w.scanState < 0)             // recheck after write
+                    LockSupport.park(this);
+                w.parker = null;
+                if ((runState & STOP) != 0)
+                    stat = w.qlock = -1;         // recheck
+                else if (w.scanState < 0)
+                    Thread.interrupted();        // clear status
+            }
+        }
+        return stat;
+    }
+
+    /**
+     * Possibly triggers shutdown and tries (once) to block worker
+     * when pool is (or may be) quiescent. Waits up to a duration
+     * determined by number of workers.  On timeout, if ctl has not
+     * changed, terminates the worker, which will in turn wake up
+     * another worker to possibly repeat this process.
+     *
+     * @param w the calling worker
+     * @return negative if w should terminate
+     */
+    private int timedAwaitWork(WorkQueue w, long c) {
+        int stat = 0;
+        int scale = 1 - (short)(c >>> TC_SHIFT);
+        long deadline = (((scale <= 0) ? 1 : scale) * IDLE_TIMEOUT_MS +
+                         System.currentTimeMillis());
+        if ((runState >= 0 || (stat = tryTerminate(false, false)) > 0) &&
+            w != null && w.scanState < 0) {
+            int ss; AuxState aux;
+            w.parker = Thread.currentThread();
+            if (w.scanState < 0)
+                LockSupport.parkUntil(this, deadline);
+            w.parker = null;
+            if ((runState & STOP) != 0)
+                stat = w.qlock = -1;         // pool terminating
+            else if ((ss = w.scanState) < 0 && !Thread.interrupted() &&
+                     (int)c == ss && (aux = auxState) != null && ctl == c &&
+                     deadline - System.currentTimeMillis() <= TIMEOUT_SLOP_MS) {
+                aux.lock();
+                try {                        // pre-deregister
+                    WorkQueue[] ws;
+                    int cfg = w.config, idx = cfg & SMASK;
+                    long nc = ((UC_MASK & (c - TC_UNIT)) |
+                               (SP_MASK & w.stackPred));
+                    if ((runState & STOP) == 0 &&
+                        (ws = workQueues) != null &&
+                        idx < ws.length && idx >= 0 && ws[idx] == w &&
+                        U.compareAndSwapLong(this, CTL, c, nc)) {
+                        ws[idx] = null;
+                        w.config = cfg | UNREGISTERED;
+                        stat = w.qlock = -1;
+                    }
+                } finally {
+                    aux.unlock();
+                }
+            }
+        }
+        return stat;
+    }
+
+    /**
+     * If the given worker is a spare with no queued tasks, and there
+     * are enough existing workers, drops it from ctl counts and sets
+     * its state to terminated.
+     *
+     * @param w the calling worker -- must be a spare
+     * @return true if dropped (in which case it must not process more tasks)
+     */
+    private boolean tryDropSpare(WorkQueue w) {
+        if (w != null && w.isEmpty()) {           // no local tasks
+            long c; int sp, wl; WorkQueue[] ws; WorkQueue v;
+            while ((short)((c = ctl) >> TC_SHIFT) > 0 &&
+                   ((sp = (int)c) != 0 || (int)(c >> AC_SHIFT) > 0) &&
+                   (ws = workQueues) != null && (wl = ws.length) > 0) {
+                boolean dropped, canDrop;
+                if (sp == 0) {                    // no queued workers
+                    long nc = ((AC_MASK & (c - AC_UNIT)) |
+                               (TC_MASK & (c - TC_UNIT)) | (SP_MASK & c));
+                    dropped = U.compareAndSwapLong(this, CTL, c, nc);
+                }
+                else if (
+                    (v = ws[(wl - 1) & sp]) == null || v.scanState != sp)
+                    dropped = false;              // stale; retry
+                else {
+                    long nc = v.stackPred & SP_MASK;
+                    if (w == v || w.scanState >= 0) {
+                        canDrop = true;           // w unqueued or topmost
+                        nc |= ((AC_MASK & c) |    // ensure replacement
+                               (TC_MASK & (c - TC_UNIT)));
+                    }
+                    else {                        // w may be queued
+                        canDrop = false;          // help uncover
+                        nc |= ((AC_MASK & (c + AC_UNIT)) |
+                               (TC_MASK & c));
+                    }
+                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                        v.scanState = sp & ~UNSIGNALLED;
+                        LockSupport.unpark(v.parker);
+                        dropped = canDrop;
+                    }
+                    else
+                        dropped = false;
+                }
+                if (dropped) {                    // pre-deregister
+                    int cfg = w.config, idx = cfg & SMASK;
+                    if (idx >= 0 && idx < ws.length && ws[idx] == w)
+                        ws[idx] = null;
+                    w.config = cfg | UNREGISTERED;
+                    w.qlock = -1;
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 
     /**
      * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
      */
     final void runWorker(WorkQueue w) {
-        w.growArray();                   // allocate queue
-        int seed = w.hint;               // initially holds randomization hint
-        int r = (seed == 0) ? 1 : seed;  // avoid 0 for xorShift
-        for (ForkJoinTask<?> t;;) {
-            if ((t = scan(w, r)) != null)
-                w.runTask(t);
-            else if (!awaitWork(w, r))
-                break;
-            r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
+        w.growArray();                                  // allocate queue
+        int bound = (w.config & SPARE_WORKER) != 0 ? 0 : POLL_LIMIT;
+        long seed = w.hint * 0xdaba0b6eb09322e3L;       // initial random seed
+        if ((runState & STOP) == 0) {
+            for (long r = (seed == 0L) ? 1L : seed;;) { // ensure nonzero
+                if (bound == 0 && tryDropSpare(w))
+                    break;
+                // high bits of prev seed for step; current low bits for idx
+                int step = (int)(r >>> 48) | 1;
+                r ^= r >>> 12; r ^= r << 25; r ^= r >>> 27; // xorshift
+                if (scan(w, bound, step, (int)r) < 0 && awaitWork(w) < 0)
+                    break;
+            }
         }
     }
 
+    // Scanning for tasks
+
     /**
-     * Scans for and tries to steal a top-level task. Scans start at a
-     * random location, randomly moving on apparent contention,
-     * otherwise continuing linearly until reaching two consecutive
-     * empty passes over all queues with the same checksum (summing
-     * each base index of each queue, that moves on each steal), at
-     * which point the worker tries to inactivate and then re-scans,
-     * attempting to re-activate (itself or some other worker) if
-     * finding a task; otherwise returning null to await work.  Scans
-     * otherwise touch as little memory as possible, to reduce
-     * disruption on other scanning threads.
+     * Repeatedly scans for and tries to steal and execute (via
+     * workQueue.runTask) a queued task. Each scan traverses queues in
+     * pseudorandom permutation. Upon finding a non-empty queue, makes
+     * at most the given bound attempts to re-poll (fewer if
+     * contended) on the same queue before returning (impossible
+     * scanState value) 0 to restart scan. Else returns after at least
+     * 1 and at most 32 full scans.
      *
      * @param w the worker (via its WorkQueue)
-     * @param r a random seed
-     * @return a task, or null if none found
+     * @param bound repoll bound as bitmask (0 if spare)
+     * @param step (circular) index increment per iteration (must be odd)
+     * @param r a random seed for origin index
+     * @return negative if should await signal
      */
-    private ForkJoinTask<?> scan(WorkQueue w, int r) {
-        WorkQueue[] ws; int m;
-        if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) {
-            int ss = w.scanState;                     // initially non-negative
-            for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
-                WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
-                int b, n; long c;
-                if ((q = ws[k]) != null) {
-                    if ((n = (b = q.base) - q.top) < 0 &&
-                        (a = q.array) != null) {      // non-empty
-                        long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                        if ((t = ((ForkJoinTask<?>)
-                                  U.getObjectVolatile(a, i))) != null &&
-                            q.base == b) {
-                            if (ss >= 0) {
-                                if (U.compareAndSwapObject(a, i, t, null)) {
-                                    q.base = b + 1;
-                                    if (n < -1)       // signal others
-                                        signalWork(ws, q);
-                                    return t;
-                                }
-                            }
-                            else if (oldSum == 0 &&   // try to activate
-                                     w.scanState < 0)
-                                tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
-                        }
-                        if (ss < 0)                   // refresh
-                            ss = w.scanState;
-                        r ^= r << 1; r ^= r >>> 3; r ^= r << 10;
-                        origin = k = r & m;           // move and rescan
-                        oldSum = checkSum = 0;
-                        continue;
+    private int scan(WorkQueue w, int bound, int step, int r) {
+        int stat = 0, wl; WorkQueue[] ws;
+        if ((ws = workQueues) != null && w != null && (wl = ws.length) > 0) {
+            for (int m = wl - 1,
+                     origin = m & r, idx = origin,
+                     npolls = 0,
+                     ss = w.scanState;;) {         // negative if inactive
+                WorkQueue q; ForkJoinTask<?>[] a; int b, al;
+                if ((q = ws[idx]) != null && (b = q.base) - q.top < 0 &&
+                    (a = q.array) != null && (al = a.length) > 0) {
+                    int index = (al - 1) & b;
+                    long offset = ((long)index << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        U.getObjectVolatile(a, offset);
+                    if (t == null)
+                        break;                     // empty or busy
+                    else if (b++ != q.base)
+                        break;                     // busy
+                    else if (ss < 0) {
+                        tryReactivate(w, ws, r);
+                        break;                     // retry upon rescan
                     }
-                    checkSum += b;
-                }
-                if ((k = (k + 1) & m) == origin) {    // continue until stable
-                    if ((ss >= 0 || (ss == (ss = w.scanState))) &&
-                        oldSum == (oldSum = checkSum)) {
-                        if (ss < 0 || w.qlock < 0)    // already inactive
+                    else if (!U.compareAndSwapObject(a, offset, t, null))
+                        break;                     // contended
+                    else {
+                        q.base = b;
+                        w.currentSteal = t;
+                        if (b != q.top)            // propagate signal
+                            signalWork();
+                        w.runTask(t);
+                        if (++npolls > bound)
                             break;
-                        int ns = ss | INACTIVE;       // try to inactivate
-                        long nc = ((SP_MASK & ns) |
-                                   (UC_MASK & ((c = ctl) - AC_UNIT)));
-                        w.stackPred = (int)c;         // hold prev stack top
-                        U.putInt(w, QSCANSTATE, ns);
-                        if (U.compareAndSwapLong(this, CTL, c, nc))
-                            ss = ns;
-                        else
-                            w.scanState = ss;         // back out
                     }
-                    checkSum = 0;
+                }
+                else if (npolls != 0)              // rescan
+                    break;
+                else if ((idx = (idx + step) & m) == origin) {
+                    if (ss < 0) {                  // await signal
+                        stat = ss;
+                        break;
+                    }
+                    else if (r >= 0) {
+                        inactivate(w, ss);
+                        break;
+                    }
+                    else
+                        r <<= 1;                   // at most 31 rescans
                 }
             }
         }
-        return null;
-    }
-
-    /**
-     * Possibly blocks worker w waiting for a task to steal, or
-     * returns false if the worker should terminate.  If inactivating
-     * w has caused the pool to become quiescent, checks for pool
-     * termination, and, so long as this is not the only worker, waits
-     * for up to a given duration.  On timeout, if ctl has not
-     * changed, terminates the worker, which will in turn wake up
-     * another worker to possibly repeat this process.
-     *
-     * @param w the calling worker
-     * @param r a random seed (for spins)
-     * @return false if the worker should terminate
-     */
-    private boolean awaitWork(WorkQueue w, int r) {
-        if (w == null || w.qlock < 0)                 // w is terminating
-            return false;
-        for (int pred = w.stackPred, spins = SPINS, ss;;) {
-            if ((ss = w.scanState) >= 0)
-                break;
-            else if (spins > 0) {
-                r ^= r << 6; r ^= r >>> 21; r ^= r << 7;
-                if (r >= 0 && --spins == 0) {         // randomize spins
-                    WorkQueue v; WorkQueue[] ws; int s, j; AtomicLong sc;
-                    if (pred != 0 && (ws = workQueues) != null &&
-                        (j = pred & SMASK) < ws.length &&
-                        (v = ws[j]) != null &&        // see if pred parking
-                        (v.parker == null || v.scanState >= 0))
-                        spins = SPINS;                // continue spinning
-                }
-            }
-            else if (w.qlock < 0)                     // recheck after spins
-                return false;
-            else if (!Thread.interrupted()) {
-                long c, prevctl, parkTime, deadline;
-                int ac = (int)((c = ctl) >> AC_SHIFT) + (config & SMASK);
-                if ((ac <= 0 && tryTerminate(false, false)) ||
-                    (runState & STOP) != 0)           // pool terminating
-                    return false;
-                if (ac <= 0 && ss == (int)c) {        // is last waiter
-                    prevctl = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & pred);
-                    int t = (short)(c >>> TC_SHIFT);  // shrink excess spares
-                    if (t > 2 && U.compareAndSwapLong(this, CTL, c, prevctl))
-                        return false;                 // else use timed wait
-                    parkTime = IDLE_TIMEOUT * ((t >= 0) ? 1 : 1 - t);
-                    deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
-                }
-                else
-                    prevctl = parkTime = deadline = 0L;
-                Thread wt = Thread.currentThread();
-                U.putObject(wt, PARKBLOCKER, this);   // emulate LockSupport
-                w.parker = wt;
-                if (w.scanState < 0 && ctl == c)      // recheck before park
-                    U.park(false, parkTime);
-                U.putOrderedObject(w, QPARKER, null);
-                U.putObject(wt, PARKBLOCKER, null);
-                if (w.scanState >= 0)
-                    break;
-                if (parkTime != 0L && ctl == c &&
-                    deadline - System.nanoTime() <= 0L &&
-                    U.compareAndSwapLong(this, CTL, c, prevctl))
-                    return false;                     // shrink pool
-            }
-        }
-        return true;
+        return stat;
     }
 
     // Joining tasks
@@ -1849,7 +2015,7 @@
      * eligible tasks popped from the worker's own queue (via
      * popCC). Otherwise it scans others, randomly moving on
      * contention or execution, deciding to give up based on a
-     * checksum (via return codes frob pollAndExecCC). The maxTasks
+     * checksum (via return codes from pollAndExecCC). The maxTasks
      * argument supports external usages; internal calls use zero,
      * allowing unbounded steps (external calls trap non-positive
      * values).
@@ -1860,15 +2026,17 @@
      */
     final int helpComplete(WorkQueue w, CountedCompleter<?> task,
                            int maxTasks) {
-        WorkQueue[] ws; int s = 0, m;
-        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+        WorkQueue[] ws; int s = 0, wl;
+        if ((ws = workQueues) != null && (wl = ws.length) > 1 &&
             task != null && w != null) {
-            int mode = w.config;                 // for popCC
-            int r = w.hint ^ w.top;              // arbitrary seed for origin
-            int origin = r & m;                  // first queue to scan
-            int h = 1;                           // 1:ran, >1:contended, <0:hash
-            for (int k = origin, oldSum = 0, checkSum = 0;;) {
-                CountedCompleter<?> p; WorkQueue q;
+            for (int m = wl - 1,
+                     mode = w.config,
+                     r = ~mode,                  // scanning seed
+                     origin = r & m, k = origin, // first queue to scan
+                     step = 3,                   // first scan step
+                     h = 1,                      // 1:ran, >1:contended, <0:hash
+                     oldSum = 0, checkSum = 0;;) {
+                CountedCompleter<?> p; WorkQueue q; int i;
                 if ((s = task.status) < 0)
                     break;
                 if (h == 1 && (p = w.popCC(task, mode)) != null) {
@@ -1878,19 +2046,20 @@
                     origin = k;                  // reset
                     oldSum = checkSum = 0;
                 }
-                else {                           // poll other queues
-                    if ((q = ws[k]) == null)
+                else {                           // poll other worker queues
+                    if ((i = k | 1) < 0 || i > m || (q = ws[i]) == null)
                         h = 0;
                     else if ((h = q.pollAndExecCC(task)) < 0)
                         checkSum += h;
                     if (h > 0) {
                         if (h == 1 && maxTasks != 0 && --maxTasks == 0)
                             break;
+                        step = (r >>> 16) | 3;
                         r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
-                        origin = k = r & m;      // move and restart
+                        k = origin = r & m;      // move and restart
                         oldSum = checkSum = 0;
                     }
-                    else if ((k = (k + 1) & m) == origin) {
+                    else if ((k = (k + step) & m) == origin) {
                         if (oldSum == (oldSum = checkSum))
                             break;
                         checkSum = 0;
@@ -1903,7 +2072,7 @@
 
     /**
      * Tries to locate and execute tasks for a stealer of the given
-     * task, or in turn one of its stealers, Traces currentSteal ->
+     * task, or in turn one of its stealers. Traces currentSteal ->
      * currentJoin links looking for a thread working on a descendant
      * of the given task and with a non-empty queue to steal back and
      * execute tasks from. The first call to this method upon a
@@ -1915,63 +2084,74 @@
      * @param task the task to join
      */
     private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
-        WorkQueue[] ws = workQueues;
-        int oldSum = 0, checkSum, m;
-        if (ws != null && (m = ws.length - 1) >= 0 && w != null &&
-            task != null) {
-            do {                                       // restart point
-                checkSum = 0;                          // for stability check
+        if (task != null && w != null) {
+            ForkJoinTask<?> ps = w.currentSteal;
+            WorkQueue[] ws; int wl, oldSum = 0;
+            outer: while (w.tryRemoveAndExec(task) && task.status >= 0 &&
+                          (ws = workQueues) != null && (wl = ws.length) > 0) {
                 ForkJoinTask<?> subtask;
+                int m = wl - 1, checkSum = 0;          // for stability check
                 WorkQueue j = w, v;                    // v is subtask stealer
                 descent: for (subtask = task; subtask.status >= 0; ) {
-                    for (int h = j.hint | 1, k = 0, i; ; k += 2) {
-                        if (k > m)                     // can't find stealer
-                            break descent;
-                        if ((v = ws[i = (h + k) & m]) != null) {
+                    for (int h = j.hint | 1, k = 0, i;;) {
+                        if ((v = ws[i = (h + (k << 1)) & m]) != null) {
                             if (v.currentSteal == subtask) {
                                 j.hint = i;
                                 break;
                             }
                             checkSum += v.base;
                         }
+                        if (++k > m)                   // can't find stealer
+                            break outer;
                     }
+
                     for (;;) {                         // help v or descend
-                        ForkJoinTask<?>[] a; int b;
+                        ForkJoinTask<?>[] a; int b, al;
+                        if (subtask.status < 0)        // too late to help
+                            break descent;
                         checkSum += (b = v.base);
                         ForkJoinTask<?> next = v.currentJoin;
-                        if (subtask.status < 0 || j.currentJoin != subtask ||
-                            v.currentSteal != subtask) // stale
-                            break descent;
-                        if (b - v.top >= 0 || (a = v.array) == null) {
-                            if ((subtask = next) == null)
+                        ForkJoinTask<?> t = null;
+                        if ((a = v.array) != null && (al = a.length) > 0) {
+                            int index = (al - 1) & b;
+                            long offset = ((long)index << ASHIFT) + ABASE;
+                            t = (ForkJoinTask<?>)
+                                U.getObjectVolatile(a, offset);
+                            if (t != null && b++ == v.base) {
+                                if (j.currentJoin != subtask ||
+                                    v.currentSteal != subtask ||
+                                    subtask.status < 0)
+                                    break descent;     // stale
+                                if (U.compareAndSwapObject(a, offset, t, null)) {
+                                    v.base = b;
+                                    w.currentSteal = t;
+                                    for (int top = w.top;;) {
+                                        t.doExec();    // help
+                                        w.currentSteal = ps;
+                                        if (task.status < 0)
+                                            break outer;
+                                        if (w.top == top)
+                                            break;     // run local tasks
+                                        if ((t = w.pop()) == null)
+                                            break descent;
+                                        w.currentSteal = t;
+                                    }
+                                }
+                            }
+                        }
+                        if (t == null && b == v.base && b - v.top >= 0) {
+                            if ((subtask = next) == null) {  // try to descend
+                                if (next == v.currentJoin &&
+                                    oldSum == (oldSum = checkSum))
+                                    break outer;
                                 break descent;
+                            }
                             j = v;
                             break;
                         }
-                        int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                        ForkJoinTask<?> t = ((ForkJoinTask<?>)
-                                             U.getObjectVolatile(a, i));
-                        if (v.base == b) {
-                            if (t == null)             // stale
-                                break descent;
-                            if (U.compareAndSwapObject(a, i, t, null)) {
-                                v.base = b + 1;
-                                ForkJoinTask<?> ps = w.currentSteal;
-                                int top = w.top;
-                                do {
-                                    U.putOrderedObject(w, QCURRENTSTEAL, t);
-                                    t.doExec();        // clear local tasks too
-                                } while (task.status >= 0 &&
-                                         w.top != top &&
-                                         (t = w.pop()) != null);
-                                U.putOrderedObject(w, QCURRENTSTEAL, ps);
-                                if (w.base != w.top)
-                                    return;            // can't further help
-                            }
-                        }
                     }
                 }
-            } while (task.status >= 0 && oldSum != (oldSum = checkSum));
+            }
         }
     }
 
@@ -1984,45 +2164,44 @@
      * @param w caller
      */
     private boolean tryCompensate(WorkQueue w) {
-        boolean canBlock;
-        WorkQueue[] ws; long c; int m, pc, sp;
-        if (w == null || w.qlock < 0 ||           // caller terminating
-            (ws = workQueues) == null || (m = ws.length - 1) <= 0 ||
-            (pc = config & SMASK) == 0)           // parallelism disabled
+        boolean canBlock; int wl;
+        long c = ctl;
+        WorkQueue[] ws = workQueues;
+        int pc = config & SMASK;
+        int ac = pc + (int)(c >> AC_SHIFT);
+        int tc = pc + (short)(c >> TC_SHIFT);
+        if (w == null || w.qlock < 0 || pc == 0 ||  // terminating or disabled
+            ws == null || (wl = ws.length) <= 0)
             canBlock = false;
-        else if ((sp = (int)(c = ctl)) != 0)      // release idle worker
-            canBlock = tryRelease(c, ws[sp & m], 0L);
         else {
-            int ac = (int)(c >> AC_SHIFT) + pc;
-            int tc = (short)(c >> TC_SHIFT) + pc;
-            int nbusy = 0;                        // validate saturation
-            for (int i = 0; i <= m; ++i) {        // two passes of odd indices
-                WorkQueue v;
-                if ((v = ws[((i << 1) | 1) & m]) != null) {
-                    if ((v.scanState & SCANNING) != 0)
-                        break;
-                    ++nbusy;
+            int m = wl - 1, sp;
+            boolean busy = true;                    // validate ac
+            for (int i = 0; i <= m; ++i) {
+                int k; WorkQueue v;
+                if ((k = (i << 1) | 1) <= m && k >= 0 && (v = ws[k]) != null &&
+                    v.scanState >= 0 && v.currentSteal == null) {
+                    busy = false;
+                    break;
                 }
             }
-            if (nbusy != (tc << 1) || ctl != c)
-                canBlock = false;                 // unstable or stale
+            if (!busy || ctl != c)
+                canBlock = false;                   // unstable or stale
+            else if ((sp = (int)c) != 0)            // release idle worker
+                canBlock = tryRelease(c, ws[m & sp], 0L);
             else if (tc >= pc && ac > 1 && w.isEmpty()) {
                 long nc = ((AC_MASK & (c - AC_UNIT)) |
-                           (~AC_MASK & c));       // uncompensated
+                           (~AC_MASK & c));         // uncompensated
                 canBlock = U.compareAndSwapLong(this, CTL, c, nc);
             }
             else if (tc >= MAX_CAP ||
-                     (this == common && tc >= pc + commonMaxSpares))
+                     (this == common && tc >= pc + COMMON_MAX_SPARES))
                 throw new RejectedExecutionException(
                     "Thread limit exceeded replacing blocked worker");
-            else {                                // similar to tryAddWorker
-                boolean add = false; int rs;      // CAS within lock
-                long nc = ((AC_MASK & c) |
-                           (TC_MASK & (c + TC_UNIT)));
-                if (((rs = lockRunState()) & STOP) == 0)
-                    add = U.compareAndSwapLong(this, CTL, c, nc);
-                unlockRunState(rs, rs & ~RSLOCK);
-                canBlock = add && createWorker(); // throws on exception
+            else {                                  // similar to tryAddWorker
+                boolean isSpare = (tc >= pc);
+                long nc = (AC_MASK & c) | (TC_MASK & (c + TC_UNIT));
+                canBlock = (U.compareAndSwapLong(this, CTL, c, nc) &&
+                            createWorker(isSpare)); // throws on exception
             }
         }
         return canBlock;
@@ -2038,33 +2217,35 @@
      */
     final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
         int s = 0;
-        if (task != null && w != null) {
+        if (w != null) {
             ForkJoinTask<?> prevJoin = w.currentJoin;
-            U.putOrderedObject(w, QCURRENTJOIN, task);
-            CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
-                (CountedCompleter<?>)task : null;
-            for (;;) {
-                if ((s = task.status) < 0)
-                    break;
-                if (cc != null)
-                    helpComplete(w, cc, 0);
-                else if (w.base == w.top || w.tryRemoveAndExec(task))
-                    helpStealer(w, task);
-                if ((s = task.status) < 0)
-                    break;
-                long ms, ns;
-                if (deadline == 0L)
-                    ms = 0L;
-                else if ((ns = deadline - System.nanoTime()) <= 0L)
-                    break;
-                else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
-                    ms = 1L;
-                if (tryCompensate(w)) {
-                    task.internalWait(ms);
-                    U.getAndAddLong(this, CTL, AC_UNIT);
+            if (task != null && (s = task.status) >= 0) {
+                w.currentJoin = task;
+                CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
+                    (CountedCompleter<?>)task : null;
+                for (;;) {
+                    if (cc != null)
+                        helpComplete(w, cc, 0);
+                    else
+                        helpStealer(w, task);
+                    if ((s = task.status) < 0)
+                        break;
+                    long ms, ns;
+                    if (deadline == 0L)
+                        ms = 0L;
+                    else if ((ns = deadline - System.nanoTime()) <= 0L)
+                        break;
+                    else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
+                        ms = 1L;
+                    if (tryCompensate(w)) {
+                        task.internalWait(ms);
+                        U.getAndAddLong(this, CTL, AC_UNIT);
+                    }
+                    if ((s = task.status) < 0)
+                        break;
                 }
+                w.currentJoin = prevJoin;
             }
-            U.putOrderedObject(w, QCURRENTJOIN, prevJoin);
         }
         return s;
     }
@@ -2077,10 +2258,11 @@
      * caller if, by the time it tries to use the queue, it is empty.
      */
     private WorkQueue findNonEmptyStealQueue() {
-        WorkQueue[] ws; int m;  // one-shot version of scan loop
+        WorkQueue[] ws; int wl;  // one-shot version of scan loop
         int r = ThreadLocalRandom.nextSecondarySeed();
-        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
-            for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
+        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
+            int m = wl - 1, origin = r & m;
+            for (int k = origin, oldSum = 0, checkSum = 0;;) {
                 WorkQueue q; int b;
                 if ((q = ws[k]) != null) {
                     if ((b = q.base) - q.top < 0)
@@ -2105,25 +2287,27 @@
      */
     final void helpQuiescePool(WorkQueue w) {
         ForkJoinTask<?> ps = w.currentSteal; // save context
+        int wc = w.config;
         for (boolean active = true;;) {
-            long c; WorkQueue q; ForkJoinTask<?> t; int b;
-            w.execLocalTasks();     // run locals before each scan
-            if ((q = findNonEmptyStealQueue()) != null) {
+            long c; WorkQueue q; ForkJoinTask<?> t;
+            if (wc >= 0 && (t = w.pop()) != null) { // run locals if LIFO
+                (w.currentSteal = t).doExec();
+                w.currentSteal = ps;
+            }
+            else if ((q = findNonEmptyStealQueue()) != null) {
                 if (!active) {      // re-establish active count
                     active = true;
                     U.getAndAddLong(this, CTL, AC_UNIT);
                 }
-                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
-                    U.putOrderedObject(w, QCURRENTSTEAL, t);
-                    t.doExec();
+                if ((t = q.pollAt(q.base)) != null) {
+                    (w.currentSteal = t).doExec();
+                    w.currentSteal = ps;
                     if (++w.nsteals < 0)
                         w.transferStealCount(this);
                 }
             }
             else if (active) {      // decrement active count without queuing
                 long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c);
-                if ((int)(nc >> AC_SHIFT) + (config & SMASK) <= 0)
-                    break;          // bypass decrement-then-increment
                 if (U.compareAndSwapLong(this, CTL, c, nc))
                     active = false;
             }
@@ -2131,7 +2315,6 @@
                      U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
                 break;
         }
-        U.putOrderedObject(w, QCURRENTSTEAL, ps);
     }
 
     /**
@@ -2141,12 +2324,12 @@
      */
     final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
         for (ForkJoinTask<?> t;;) {
-            WorkQueue q; int b;
+            WorkQueue q;
             if ((t = w.nextLocalTask()) != null)
                 return t;
             if ((q = findNonEmptyStealQueue()) == null)
                 return null;
-            if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+            if ((t = q.pollAt(q.base)) != null)
                 return t;
         }
     }
@@ -2195,9 +2378,8 @@
      */
     static int getSurplusQueuedTaskCount() {
         Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
-        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
-            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).
-                config & SMASK;
+        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
+            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
             int n = (q = wt.workQueue).top - q.base;
             int a = (int)(pool.ctl >> AC_SHIFT) + p;
             return n - (a > (p >>>= 1) ? 0 :
@@ -2216,212 +2398,165 @@
      *
      * @param now if true, unconditionally terminate, else only
      * if no work and no active workers
-     * @param enable if true, enable shutdown when next possible
-     * @return true if now terminating or terminated
+     * @param enable if true, terminate when next possible
+     * @return -1: terminating/terminated, 0: retry if internal caller, else 1
      */
-    private boolean tryTerminate(boolean now, boolean enable) {
-        int rs;
-        if (this == common)                       // cannot shut down
-            return false;
-        if ((rs = runState) >= 0) {
-            if (!enable)
-                return false;
-            rs = lockRunState();                  // enter SHUTDOWN phase
-            unlockRunState(rs, (rs & ~RSLOCK) | SHUTDOWN);
+    private int tryTerminate(boolean now, boolean enable) {
+        int rs; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
+
+        while ((rs = runState) >= 0) {
+            if (!enable || this == common)        // cannot shutdown
+                return 1;
+            else if (rs == 0)
+                tryInitialize(false);             // ensure initialized
+            else
+                U.compareAndSwapInt(this, RUNSTATE, rs, rs | SHUTDOWN);
         }
 
-        if ((rs & STOP) == 0) {
+        if ((rs & STOP) == 0) {                   // try to initiate termination
             if (!now) {                           // check quiescence
                 for (long oldSum = 0L;;) {        // repeat until stable
-                    WorkQueue[] ws; WorkQueue w; int m, b; long c;
+                    WorkQueue[] ws; WorkQueue w; int b;
                     long checkSum = ctl;
                     if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
-                        return false;             // still active workers
-                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
-                        break;                    // check queues
-                    for (int i = 0; i <= m; ++i) {
-                        if ((w = ws[i]) != null) {
-                            if ((b = w.base) != w.top || w.scanState >= 0 ||
-                                w.currentSteal != null) {
-                                tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
-                                return false;     // arrange for recheck
+                        return 0;                 // still active workers
+                    if ((ws = workQueues) != null) {
+                        for (int i = 0; i < ws.length; ++i) {
+                            if ((w = ws[i]) != null) {
+                                checkSum += (b = w.base);
+                                if (w.currentSteal != null || b != w.top)
+                                    return 0;     // retry if internal caller
                             }
-                            checkSum += b;
-                            if ((i & 1) == 0)
-                                w.qlock = -1;     // try to disable external
                         }
                     }
                     if (oldSum == (oldSum = checkSum))
                         break;
                 }
             }
-            if ((runState & STOP) == 0) {
-                rs = lockRunState();              // enter STOP phase
-                unlockRunState(rs, (rs & ~RSLOCK) | STOP);
-            }
+            do {} while (!U.compareAndSwapInt(this, RUNSTATE,
+                                              rs = runState, rs | STOP));
         }
 
-        int pass = 0;                             // 3 passes to help terminate
-        for (long oldSum = 0L;;) {                // or until done or stable
-            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt; int m;
+        for (long oldSum = 0L;;) {                // repeat until stable
+            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt;
             long checkSum = ctl;
-            if ((short)(checkSum >>> TC_SHIFT) + (config & SMASK) <= 0 ||
-                (ws = workQueues) == null || (m = ws.length - 1) <= 0) {
-                if ((runState & TERMINATED) == 0) {
-                    rs = lockRunState();          // done
-                    unlockRunState(rs, (rs & ~RSLOCK) | TERMINATED);
-                    synchronized (this) { notifyAll(); } // for awaitTermination
-                }
-                break;
-            }
-            for (int i = 0; i <= m; ++i) {
-                if ((w = ws[i]) != null) {
-                    checkSum += w.base;
-                    w.qlock = -1;                 // try to disable
-                    if (pass > 0) {
-                        w.cancelAll();            // clear queue
-                        if (pass > 1 && (wt = w.owner) != null) {
-                            if (!wt.isInterrupted()) {
-                                try {             // unblock join
+            if ((ws = workQueues) != null) {      // help terminate others
+                for (int i = 0; i < ws.length; ++i) {
+                    if ((w = ws[i]) != null) {
+                        w.cancelAll();            // clear queues
+                        checkSum += w.base;
+                        if (w.qlock >= 0) {
+                            w.qlock = -1;         // racy set OK
+                            if ((wt = w.owner) != null) {
+                                try {             // unblock join or park
                                     wt.interrupt();
                                 } catch (Throwable ignore) {
                                 }
                             }
-                            if (w.scanState < 0)
-                                U.unpark(wt);     // wake up
                         }
                     }
                 }
             }
-            if (checkSum != oldSum) {             // unstable
-                oldSum = checkSum;
-                pass = 0;
-            }
-            else if (pass > 3 && pass > m)        // can't further help
+            if (oldSum == (oldSum = checkSum))
                 break;
-            else if (++pass > 1) {                // try to dequeue
-                long c; int j = 0, sp;            // bound attempts
-                while (j++ <= m && (sp = (int)(c = ctl)) != 0)
-                    tryRelease(c, ws[sp & m], AC_UNIT);
+        }
+
+        if ((short)(ctl >>> TC_SHIFT) + (config & SMASK) <= 0) {
+            runState = (STARTED | SHUTDOWN | STOP | TERMINATED); // final write
+            synchronized (this) {
+                notifyAll();                      // for awaitTermination
             }
         }
-        return true;
+
+        return -1;
     }
 
     // External operations
 
     /**
-     * Full version of externalPush, handling uncommon cases, as well
-     * as performing secondary initialization upon the first
-     * submission of the first task to the pool.  It also detects
+     * Constructs and tries to install a new external queue,
+     * failing if the workQueues array already has a queue at
+     * the given index.
+     *
+     * @param index the index of the new queue
+     */
+    private void tryCreateExternalQueue(int index) {
+        AuxState aux;
+        if ((aux = auxState) != null && index >= 0) {
+            WorkQueue q = new WorkQueue(this, null);
+            q.config = index;
+            q.scanState = ~UNSIGNALLED;
+            q.qlock = 1;                   // lock queue
+            boolean installed = false;
+            aux.lock();
+            try {                          // lock pool to install
+                WorkQueue[] ws;
+                if ((ws = workQueues) != null && index < ws.length &&
+                    ws[index] == null) {
+                    ws[index] = q;         // else throw away
+                    installed = true;
+                }
+            } finally {
+                aux.unlock();
+            }
+            if (installed) {
+                try {
+                    q.growArray();
+                } finally {
+                    q.qlock = 0;
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds the given task to a submission queue at submitter's
+     * current queue. Also performs secondary initialization upon the
+     * first submission of the first task to the pool, and detects
      * first submission by an external thread and creates a new shared
      * queue if the one at index if empty or contended.
      *
      * @param task the task. Caller must ensure non-null.
      */
-    private void externalSubmit(ForkJoinTask<?> task) {
-        int r;                                    // initialize caller's probe
+    final void externalPush(ForkJoinTask<?> task) {
+        int r;                            // initialize caller's probe
         if ((r = ThreadLocalRandom.getProbe()) == 0) {
             ThreadLocalRandom.localInit();
             r = ThreadLocalRandom.getProbe();
         }
         for (;;) {
-            WorkQueue[] ws; WorkQueue q; int rs, m, k;
-            boolean move = false;
-            if ((rs = runState) < 0) {
-                tryTerminate(false, false);     // help terminate
-                throw new RejectedExecutionException();
-            }
-            else if ((rs & STARTED) == 0 ||     // initialize
-                     ((ws = workQueues) == null || (m = ws.length - 1) < 0)) {
-                int ns = 0;
-                rs = lockRunState();
-                try {
-                    if ((rs & STARTED) == 0) {
-                        U.compareAndSwapObject(this, STEALCOUNTER, null,
-                                               new AtomicLong());
-                        // create workQueues array with size a power of two
-                        int p = config & SMASK; // ensure at least 2 slots
-                        int n = (p > 1) ? p - 1 : 1;
-                        n |= n >>> 1; n |= n >>> 2;  n |= n >>> 4;
-                        n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
-                        workQueues = new WorkQueue[n];
-                        ns = STARTED;
-                    }
-                } finally {
-                    unlockRunState(rs, (rs & ~RSLOCK) | ns);
-                }
+            WorkQueue q; int wl, k, stat;
+            int rs = runState;
+            WorkQueue[] ws = workQueues;
+            if (rs <= 0 || ws == null || (wl = ws.length) <= 0)
+                tryInitialize(true);
+            else if ((q = ws[k = (wl - 1) & r & SQMASK]) == null)
+                tryCreateExternalQueue(k);
+            else if ((stat = q.sharedPush(task)) < 0)
+                break;
+            else if (stat == 0) {
+                signalWork();
+                break;
             }
-            else if ((q = ws[k = r & m & SQMASK]) != null) {
-                if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
-                    ForkJoinTask<?>[] a = q.array;
-                    int s = q.top;
-                    boolean submitted = false; // initial submission or resizing
-                    try {                      // locked version of push
-                        if ((a != null && a.length > s + 1 - q.base) ||
-                            (a = q.growArray()) != null) {
-                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
-                            U.putOrderedObject(a, j, task);
-                            U.putOrderedInt(q, QTOP, s + 1);
-                            submitted = true;
-                        }
-                    } finally {
-                        U.compareAndSwapInt(q, QLOCK, 1, 0);
-                    }
-                    if (submitted) {
-                        signalWork(ws, q);
-                        return;
-                    }
-                }
-                move = true;                   // move on failure
-            }
-            else if (((rs = runState) & RSLOCK) == 0) { // create new queue
-                q = new WorkQueue(this, null);
-                q.hint = r;
-                q.config = k | SHARED_QUEUE;
-                q.scanState = INACTIVE;
-                rs = lockRunState();           // publish index
-                if (rs > 0 &&  (ws = workQueues) != null &&
-                    k < ws.length && ws[k] == null)
-                    ws[k] = q;                 // else terminated
-                unlockRunState(rs, rs & ~RSLOCK);
-            }
-            else
-                move = true;                   // move if busy
-            if (move)
+            else                          // move if busy
                 r = ThreadLocalRandom.advanceProbe(r);
         }
     }
 
     /**
-     * Tries to add the given task to a submission queue at
-     * submitter's current queue. Only the (vastly) most common path
-     * is directly handled in this method, while screening for need
-     * for externalSubmit.
-     *
-     * @param task the task. Caller must ensure non-null.
+     * Pushes a possibly-external submission.
      */
-    final void externalPush(ForkJoinTask<?> task) {
-        WorkQueue[] ws; WorkQueue q; int m;
-        int r = ThreadLocalRandom.getProbe();
-        int rs = runState;
-        if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
-            (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
-            U.compareAndSwapInt(q, QLOCK, 0, 1)) {
-            ForkJoinTask<?>[] a; int am, n, s;
-            if ((a = q.array) != null &&
-                (am = a.length - 1) > (n = (s = q.top) - q.base)) {
-                int j = ((am & s) << ASHIFT) + ABASE;
-                U.putOrderedObject(a, j, task);
-                U.putOrderedInt(q, QTOP, s + 1);
-                U.putIntVolatile(q, QLOCK, 0);
-                if (n <= 1)
-                    signalWork(ws, q);
-                return;
-            }
-            U.compareAndSwapInt(q, QLOCK, 1, 0);
-        }
-        externalSubmit(task);
+    private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
+        Thread t; ForkJoinWorkerThread w; WorkQueue q;
+        if (task == null)
+            throw new NullPointerException();
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+            (w = (ForkJoinWorkerThread)t).pool == this &&
+            (q = w.workQueue) != null)
+            q.push(task);
+        else
+            externalPush(task);
+        return task;
     }
 
     /**
@@ -2430,46 +2565,32 @@
     static WorkQueue commonSubmitterQueue() {
         ForkJoinPool p = common;
         int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; int m;
+        WorkQueue[] ws; int wl;
         return (p != null && (ws = p.workQueues) != null &&
-                (m = ws.length - 1) >= 0) ?
-            ws[m & r & SQMASK] : null;
+                (wl = ws.length) > 0) ?
+            ws[(wl - 1) & r & SQMASK] : null;
     }
 
     /**
-     * Performs tryUnpush for an external submitter: Finds queue,
-     * locks if apparently non-empty, validates upon locking, and
-     * adjusts top. Each check can fail but rarely does.
+     * Performs tryUnpush for an external submitter.
      */
     final boolean tryExternalUnpush(ForkJoinTask<?> task) {
-        WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m, s;
         int r = ThreadLocalRandom.getProbe();
-        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
-            (w = ws[m & r & SQMASK]) != null &&
-            (a = w.array) != null && (s = w.top) != w.base) {
-            long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
-            if (U.compareAndSwapInt(w, QLOCK, 0, 1)) {
-                if (w.top == s && w.array == a &&
-                    U.getObject(a, j) == task &&
-                    U.compareAndSwapObject(a, j, task, null)) {
-                    U.putOrderedInt(w, QTOP, s - 1);
-                    U.putOrderedInt(w, QLOCK, 0);
-                    return true;
-                }
-                U.compareAndSwapInt(w, QLOCK, 1, 0);
-            }
-        }
-        return false;
+        WorkQueue[] ws; WorkQueue w; int wl;
+        return ((ws = workQueues) != null &&
+                (wl = ws.length) > 0 &&
+                (w = ws[(wl - 1) & r & SQMASK]) != null &&
+                w.trySharedUnpush(task));
     }
 
     /**
      * Performs helpComplete for an external submitter.
      */
     final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
-        WorkQueue[] ws; int n;
+        WorkQueue[] ws; int wl;
         int r = ThreadLocalRandom.getProbe();
-        return ((ws = workQueues) == null || (n = ws.length) == 0) ? 0 :
-            helpComplete(ws[(n - 1) & r & SQMASK], task, maxTasks);
+        return ((ws = workQueues) != null && (wl = ws.length) > 0) ?
+            helpComplete(ws[(wl - 1) & r & SQMASK], task, maxTasks) : 0;
     }
 
     // Exported methods
@@ -2617,7 +2738,7 @@
     public <T> T invoke(ForkJoinTask<T> task) {
         if (task == null)
             throw new NullPointerException();
-        externalPush(task);
+        externalSubmit(task);
         return task.join();
     }
 
@@ -2630,9 +2751,7 @@
      *         scheduled for execution
      */
     public void execute(ForkJoinTask<?> task) {
-        if (task == null)
-            throw new NullPointerException();
-        externalPush(task);
+        externalSubmit(task);
     }
 
     // AbstractExecutorService methods
@@ -2650,7 +2769,7 @@
             job = (ForkJoinTask<?>) task;
         else
             job = new ForkJoinTask.RunnableExecuteAction(task);
-        externalPush(job);
+        externalSubmit(job);
     }
 
     /**
@@ -2664,10 +2783,7 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
-        if (task == null)
-            throw new NullPointerException();
-        externalPush(task);
-        return task;
+        return externalSubmit(task);
     }
 
     /**
@@ -2676,9 +2792,7 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Callable<T> task) {
-        ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
-        externalPush(job);
-        return job;
+        return externalSubmit(new ForkJoinTask.AdaptedCallable<T>(task));
     }
 
     /**
@@ -2687,9 +2801,7 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Runnable task, T result) {
-        ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
-        externalPush(job);
-        return job;
+        return externalSubmit(new ForkJoinTask.AdaptedRunnable<T>(task, result));
     }
 
     /**
@@ -2705,8 +2817,7 @@
             job = (ForkJoinTask<?>) task;
         else
             job = new ForkJoinTask.AdaptedRunnableAction(task);
-        externalPush(job);
-        return job;
+        return externalSubmit(job);
     }
 
     /**
@@ -2719,21 +2830,19 @@
         // invocation of multiple tasks is at least as efficient.
         ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
 
-        boolean done = false;
         try {
             for (Callable<T> t : tasks) {
                 ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
                 futures.add(f);
-                externalPush(f);
+                externalSubmit(f);
             }
             for (int i = 0, size = futures.size(); i < size; i++)
                 ((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
-            done = true;
             return futures;
-        } finally {
-            if (!done)
-                for (int i = 0, size = futures.size(); i < size; i++)
-                    futures.get(i).cancel(false);
+        } catch (Throwable t) {
+            for (int i = 0, size = futures.size(); i < size; i++)
+                futures.get(i).cancel(false);
+            throw t;
         }
     }
 
@@ -2773,7 +2882,7 @@
      * @since 1.8
      */
     public static int getCommonPoolParallelism() {
-        return commonParallelism;
+        return COMMON_PARALLELISM;
     }
 
     /**
@@ -2857,8 +2966,8 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        AtomicLong sc = stealCounter;
-        long count = (sc == null) ? 0L : sc.get();
+        AuxState sc = auxState;
+        long count = (sc == null) ? 0L : sc.stealCount;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
@@ -2935,10 +3044,11 @@
      * @return the next submission, or {@code null} if none
      */
     protected ForkJoinTask<?> pollSubmission() {
-        WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
-        if ((ws = workQueues) != null) {
-            for (int i = 0; i < ws.length; i += 2) {
-                if ((w = ws[i]) != null && (t = w.poll()) != null)
+        WorkQueue[] ws; int wl; WorkQueue w; ForkJoinTask<?> t;
+        int r = ThreadLocalRandom.nextSecondarySeed();
+        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
+            for (int m = wl - 1, i = 0; i < wl; ++i) {
+                if ((w = ws[(i << 1) & m]) != null && (t = w.poll()) != null)
                     return t;
             }
         }
@@ -2988,8 +3098,8 @@
     public String toString() {
         // Use a single pass through workQueues to collect counts
         long qt = 0L, qs = 0L; int rc = 0;
-        AtomicLong sc = stealCounter;
-        long st = (sc == null) ? 0L : sc.get();
+        AuxState sc = auxState;
+        long st = (sc == null) ? 0L : sc.stealCount;
         long c = ctl;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
@@ -3171,17 +3281,17 @@
         }
         long startTime = System.nanoTime();
         WorkQueue[] ws;
-        int r = 0, m;
+        int r = 0, wl;
         boolean found = true;
         while (!isQuiescent() && (ws = workQueues) != null &&
-               (m = ws.length - 1) >= 0) {
+               (wl = ws.length) > 0) {
             if (!found) {
                 if ((System.nanoTime() - startTime) > nanos)
                     return false;
                 Thread.yield(); // cannot block
             }
             found = false;
-            for (int j = (m + 1) << 2; j >= 0; --j) {
+            for (int m = wl - 1, j = (m + 1) << 2; j >= 0; --j) {
                 ForkJoinTask<?> t; WorkQueue q; int b, k;
                 if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null &&
                     (b = q.base) - q.top < 0) {
@@ -3223,7 +3333,7 @@
      *
      * <p>For example, here is a ManagedBlocker based on a
      * ReentrantLock:
-     *  <pre> {@code
+     * <pre> {@code
      * class ManagedLocker implements ManagedBlocker {
      *   final ReentrantLock lock;
      *   boolean hasLock = false;
@@ -3240,7 +3350,7 @@
      *
      * <p>Here is a class that possibly blocks waiting for an
      * item on a given queue:
-     *  <pre> {@code
+     * <pre> {@code
      * class QueueTaker<E> implements ManagedBlocker {
      *   final BlockingQueue<E> queue;
      *   volatile E item = null;
@@ -3291,7 +3401,7 @@
      *
      * <p>If not running in a ForkJoinPool, this method is
      * behaviorally equivalent to
-     *  <pre> {@code
+     * <pre> {@code
      * while (!blocker.isReleasable())
      *   if (blocker.block())
      *     break;}</pre>
@@ -3342,58 +3452,40 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
-    private static final int  ABASE;
-    private static final int  ASHIFT;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long CTL;
     private static final long RUNSTATE;
-    private static final long STEALCOUNTER;
-    private static final long PARKBLOCKER;
-    private static final long QTOP;
-    private static final long QLOCK;
-    private static final long QSCANSTATE;
-    private static final long QPARKER;
-    private static final long QCURRENTSTEAL;
-    private static final long QCURRENTJOIN;
+    private static final int ABASE;
+    private static final int ASHIFT;
 
     static {
-        // initialize field offsets for CAS etc
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ForkJoinPool.class;
             CTL = U.objectFieldOffset
-                (k.getDeclaredField("ctl"));
+                (ForkJoinPool.class.getDeclaredField("ctl"));
             RUNSTATE = U.objectFieldOffset
-                (k.getDeclaredField("runState"));
-            STEALCOUNTER = U.objectFieldOffset
-                (k.getDeclaredField("stealCounter"));
-            Class<?> tk = Thread.class;
-            PARKBLOCKER = U.objectFieldOffset
-                (tk.getDeclaredField("parkBlocker"));
-            Class<?> wk = WorkQueue.class;
-            QTOP = U.objectFieldOffset
-                (wk.getDeclaredField("top"));
-            QLOCK = U.objectFieldOffset
-                (wk.getDeclaredField("qlock"));
-            QSCANSTATE = U.objectFieldOffset
-                (wk.getDeclaredField("scanState"));
-            QPARKER = U.objectFieldOffset
-                (wk.getDeclaredField("parker"));
-            QCURRENTSTEAL = U.objectFieldOffset
-                (wk.getDeclaredField("currentSteal"));
-            QCURRENTJOIN = U.objectFieldOffset
-                (wk.getDeclaredField("currentJoin"));
-            Class<?> ak = ForkJoinTask[].class;
-            ABASE = U.arrayBaseOffset(ak);
-            int scale = U.arrayIndexScale(ak);
+                (ForkJoinPool.class.getDeclaredField("runState"));
+            ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
+            int scale = U.arrayIndexScale(ForkJoinTask[].class);
             if ((scale & (scale - 1)) != 0)
-                throw new Error("data type scale not a power of two");
+                throw new Error("array index scale not a power of two");
             ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (Exception e) {
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
 
-        commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
+
+        int commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
+        try {
+            String p = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.maximumSpares");
+            if (p != null)
+                commonMaxSpares = Integer.parseInt(p);
+        } catch (Exception ignore) {}
+        COMMON_MAX_SPARES = commonMaxSpares;
+
         defaultForkJoinWorkerThreadFactory =
             new DefaultForkJoinWorkerThreadFactory();
         modifyThreadPermission = new RuntimePermission("modifyThread");
@@ -3401,15 +3493,16 @@
         common = java.security.AccessController.doPrivileged
             (new java.security.PrivilegedAction<ForkJoinPool>() {
                 public ForkJoinPool run() { return makeCommonPool(); }});
-        int par = common.config & SMASK; // report 1 even if threads disabled
-        commonParallelism = par > 0 ? par : 1;
+
+        // report 1 even if threads disabled
+        COMMON_PARALLELISM = Math.max(common.config & SMASK, 1);
     }
 
     /**
      * Creates and returns the common pool, respecting user settings
      * specified via system properties.
      */
-    private static ForkJoinPool makeCommonPool() {
+    static ForkJoinPool makeCommonPool() {
         int parallelism = -1;
         ForkJoinWorkerThreadFactory factory = null;
         UncaughtExceptionHandler handler = null;
@@ -3420,8 +3513,6 @@
                 ("java.util.concurrent.ForkJoinPool.common.threadFactory");
             String hp = System.getProperty
                 ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
-            String mp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.maximumSpares");
             if (pp != null)
                 parallelism = Integer.parseInt(pp);
             if (fp != null)
@@ -3430,8 +3521,6 @@
             if (hp != null)
                 handler = ((UncaughtExceptionHandler)ClassLoader.
                            getSystemClassLoader().loadClass(hp).newInstance());
-            if (mp != null)
-                commonMaxSpares = Integer.parseInt(mp);
         } catch (Exception ignore) {
         }
         if (factory == null) {
@@ -3450,9 +3539,9 @@
     }
 
     /**
-     * Factory for innocuous worker threads
+     * Factory for innocuous worker threads.
      */
-    static final class InnocuousForkJoinWorkerThreadFactory
+    private static final class InnocuousForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
 
         /**
@@ -3473,9 +3562,8 @@
         }
 
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            return (ForkJoinWorkerThread.InnocuousForkJoinWorkerThread)
-                java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
+            return java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
                     public ForkJoinWorkerThread run() {
                         return new ForkJoinWorkerThread.
                             InnocuousForkJoinWorkerThread(pool);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,21 +36,13 @@
 package java.util.concurrent;
 
 import java.io.Serializable;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
 import java.util.Collection;
 import java.util.List;
 import java.util.RandomAccess;
-import java.lang.ref.WeakReference;
-import java.lang.ref.ReferenceQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.locks.ReentrantLock;
-import java.lang.reflect.Constructor;
 
 /**
  * Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -442,7 +434,8 @@
         ExceptionNode next;
         final long thrower;  // use id not ref to avoid weak cycles
         final int hashCode;  // store task hashCode before weak ref disappears
-        ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) {
+        ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next,
+                      ReferenceQueue<Object> exceptionTableRefQueue) {
             super(task, exceptionTableRefQueue);
             this.ex = ex;
             this.next = next;
@@ -468,7 +461,8 @@
                 int i = h & (t.length - 1);
                 for (ExceptionNode e = t[i]; ; e = e.next) {
                     if (e == null) {
-                        t[i] = new ExceptionNode(this, ex, t[i]);
+                        t[i] = new ExceptionNode(this, ex, t[i],
+                                                 exceptionTableRefQueue);
                         break;
                     }
                     if (e.get() == this) // already present
@@ -561,8 +555,6 @@
      * @return the exception, or null if none
      */
     private Throwable getThrowableException() {
-        if ((status & DONE_MASK) != EXCEPTIONAL)
-            return null;
         int h = System.identityHashCode(this);
         ExceptionNode e;
         final ReentrantLock lock = exceptionTableLock;
@@ -608,7 +600,7 @@
     }
 
     /**
-     * Poll stale refs and remove them. Call only while holding lock.
+     * Polls stale refs and removes them. Call only while holding lock.
      */
     private static void expungeStaleExceptions() {
         for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
@@ -635,7 +627,7 @@
     }
 
     /**
-     * If lock is available, poll stale refs and remove them.
+     * If lock is available, polls stale refs and removes them.
      * Called from ForkJoinPool when pools become quiescent.
      */
     static final void helpExpungeStaleExceptions() {
@@ -650,21 +642,23 @@
     }
 
     /**
-     * A version of "sneaky throw" to relay exceptions
+     * A version of "sneaky throw" to relay exceptions.
      */
     static void rethrow(Throwable ex) {
-        if (ex != null)
-            ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
+        ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
     }
 
     /**
      * The sneaky part of sneaky throw, relying on generics
      * limitations to evade compiler complaints about rethrowing
-     * unchecked exceptions
+     * unchecked exceptions.
      */
     @SuppressWarnings("unchecked") static <T extends Throwable>
-        void uncheckedThrow(Throwable t) throws T {
-        throw (T)t; // rely on vacuous cast
+    void uncheckedThrow(Throwable t) throws T {
+        if (t != null)
+            throw (T)t; // rely on vacuous cast
+        else
+            throw new Error("Unknown Exception");
     }
 
     /**
@@ -999,11 +993,10 @@
     public final V get() throws InterruptedException, ExecutionException {
         int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
             doJoin() : externalInterruptibleAwaitDone();
-        Throwable ex;
         if ((s &= DONE_MASK) == CANCELLED)
             throw new CancellationException();
-        if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
-            throw new ExecutionException(ex);
+        if (s == EXCEPTIONAL)
+            throw new ExecutionException(getThrowableException());
         return getRawResult();
     }
 
@@ -1058,13 +1051,11 @@
         if (s >= 0)
             s = status;
         if ((s &= DONE_MASK) != NORMAL) {
-            Throwable ex;
             if (s == CANCELLED)
                 throw new CancellationException();
             if (s != EXCEPTIONAL)
                 throw new TimeoutException();
-            if ((ex = getThrowableException()) != null)
-                throw new ExecutionException(ex);
+            throw new ExecutionException(getThrowableException());
         }
         return getRawResult();
     }
@@ -1090,10 +1081,10 @@
 
     /**
      * Possibly executes tasks until the pool hosting the current task
-     * {@link ForkJoinPool#isQuiescent is quiescent}. This method may
-     * be of use in designs in which many tasks are forked, but none
-     * are explicitly joined, instead executing them until all are
-     * processed.
+     * {@linkplain ForkJoinPool#isQuiescent is quiescent}.  This
+     * method may be of use in designs in which many tasks are forked,
+     * but none are explicitly joined, instead executing them until
+     * all are processed.
      */
     public static void helpQuiesce() {
         Thread t;
@@ -1129,10 +1120,12 @@
     }
 
     /**
-     * Returns the pool hosting the current task execution, or null
-     * if this task is executing outside of any ForkJoinPool.
+     * Returns the pool hosting the current thread, or {@code null}
+     * if the current thread is executing outside of any ForkJoinPool.
      *
-     * @see #inForkJoinPool
+     * <p>This method returns {@code null} if and only if {@link
+     * #inForkJoinPool} returns {@code false}.
+     *
      * @return the pool, or {@code null} if none
      */
     public static ForkJoinPool getPool() {
@@ -1299,6 +1292,23 @@
             null;
     }
 
+    /**
+     * If the current thread is operating in a ForkJoinPool,
+     * unschedules and returns, without executing, a task externally
+     * submitted to the pool, if one is available. Availability may be
+     * transient, so a {@code null} result does not necessarily imply
+     * quiescence of the pool.  This method is designed primarily to
+     * support extensions, and is unlikely to be useful otherwise.
+     *
+     * @return a task, or {@code null} if none are available
+     * @since 1.9
+     */
+    protected static ForkJoinTask<?> pollSubmission() {
+        Thread t;
+        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+            ((ForkJoinWorkerThread)t).pool.pollSubmission() : null;
+    }
+
     // tag operations
 
     /**
@@ -1312,16 +1322,16 @@
     }
 
     /**
-     * Atomically sets the tag value for this task.
+     * Atomically sets the tag value for this task and returns the old value.
      *
-     * @param tag the tag value
+     * @param newValue the new tag value
      * @return the previous value of the tag
      * @since 1.8
      */
-    public final short setForkJoinTaskTag(short tag) {
+    public final short setForkJoinTaskTag(short newValue) {
         for (int s;;) {
             if (U.compareAndSwapInt(this, STATUS, s = status,
-                                    (s & ~SMASK) | (tag & SMASK)))
+                                    (s & ~SMASK) | (newValue & SMASK)))
                 return (short)s;
         }
     }
@@ -1334,24 +1344,24 @@
      * before processing, otherwise exiting because the node has
      * already been visited.
      *
-     * @param e the expected tag value
-     * @param tag the new tag value
+     * @param expect the expected tag value
+     * @param update the new tag value
      * @return {@code true} if successful; i.e., the current value was
-     * equal to e and is now tag.
+     * equal to {@code expect} and was changed to {@code update}.
      * @since 1.8
      */
-    public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
+    public final boolean compareAndSetForkJoinTaskTag(short expect, short update) {
         for (int s;;) {
-            if ((short)(s = status) != e)
+            if ((short)(s = status) != expect)
                 return false;
             if (U.compareAndSwapInt(this, STATUS, s,
-                                    (s & ~SMASK) | (tag & SMASK)))
+                                    (s & ~SMASK) | (update & SMASK)))
                 return true;
         }
     }
 
     /**
-     * Adaptor for Runnables. This implements RunnableFuture
+     * Adapter for Runnables. This implements RunnableFuture
      * to be compliant with AbstractExecutorService constraints
      * when used in ForkJoinPool.
      */
@@ -1372,7 +1382,7 @@
     }
 
     /**
-     * Adaptor for Runnables without results
+     * Adapter for Runnables without results.
      */
     static final class AdaptedRunnableAction extends ForkJoinTask<Void>
         implements RunnableFuture<Void> {
@@ -1389,7 +1399,7 @@
     }
 
     /**
-     * Adaptor for Runnables in which failure forces worker exception
+     * Adapter for Runnables in which failure forces worker exception.
      */
     static final class RunnableExecuteAction extends ForkJoinTask<Void> {
         final Runnable runnable;
@@ -1407,7 +1417,7 @@
     }
 
     /**
-     * Adaptor for Callables
+     * Adapter for Callables.
      */
     static final class AdaptedCallable<T> extends ForkJoinTask<T>
         implements RunnableFuture<T> {
@@ -1423,8 +1433,6 @@
             try {
                 result = callable.call();
                 return true;
-            } catch (Error err) {
-                throw err;
             } catch (RuntimeException rex) {
                 throw rex;
             } catch (Exception ex) {
@@ -1509,7 +1517,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long STATUS;
 
     static {
@@ -1517,11 +1525,9 @@
         exceptionTableRefQueue = new ReferenceQueue<Object>();
         exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = ForkJoinTask.class;
             STATUS = U.objectFieldOffset
-                (k.getDeclaredField("status"));
-        } catch (Exception e) {
+                (ForkJoinTask.class.getDeclaredField("status"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 20:54:58 2017 +0200
@@ -87,7 +87,7 @@
     }
 
     /**
-     * Version for InnocuousForkJoinWorkerThread
+     * Version for InnocuousForkJoinWorkerThread.
      */
     ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
                          AccessControlContext acc) {
@@ -179,28 +179,25 @@
     }
 
     /**
-     * Non-public hook method for InnocuousForkJoinWorkerThread
+     * Non-public hook method for InnocuousForkJoinWorkerThread.
      */
     void afterTopLevelExec() {
     }
 
     // Set up to allow setting thread fields in constructor
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long THREADLOCALS;
     private static final long INHERITABLETHREADLOCALS;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
     static {
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> tk = Thread.class;
             THREADLOCALS = U.objectFieldOffset
-                (tk.getDeclaredField("threadLocals"));
+                (Thread.class.getDeclaredField("threadLocals"));
             INHERITABLETHREADLOCALS = U.objectFieldOffset
-                (tk.getDeclaredField("inheritableThreadLocals"));
+                (Thread.class.getDeclaredField("inheritableThreadLocals"));
             INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
-                (tk.getDeclaredField("inheritedAccessControlContext"));
-
-        } catch (Exception e) {
+                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
@@ -252,10 +249,10 @@
         private static ThreadGroup createThreadGroup() {
             try {
                 sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
-                Class<?> tk = Thread.class;
-                Class<?> gk = ThreadGroup.class;
-                long tg = u.objectFieldOffset(tk.getDeclaredField("group"));
-                long gp = u.objectFieldOffset(gk.getDeclaredField("parent"));
+                long tg = u.objectFieldOffset
+                    (Thread.class.getDeclaredField("group"));
+                long gp = u.objectFieldOffset
+                    (ThreadGroup.class.getDeclaredField("parent"));
                 ThreadGroup group = (ThreadGroup)
                     u.getObject(Thread.currentThread(), tg);
                 while (group != null) {
@@ -265,7 +262,7 @@
                                                "InnocuousForkJoinWorkerThreadGroup");
                     group = parent;
                 }
-            } catch (Exception e) {
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
             // fall through if null as cannot-happen safeguard
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Future.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Future.java	Wed Jul 05 20:54:58 2017 +0200
@@ -53,6 +53,7 @@
  * <p>
  * <b>Sample Usage</b> (Note that the following classes are all
  * made-up.)
+ *
  * <pre> {@code
  * interface ArchiveSearcher { String search(String target); }
  * class App {
@@ -75,9 +76,9 @@
  * The {@link FutureTask} class is an implementation of {@code Future} that
  * implements {@code Runnable}, and so may be executed by an {@code Executor}.
  * For example, the above construction with {@code submit} could be replaced by:
- *  <pre> {@code
+ * <pre> {@code
  * FutureTask<String> future =
- *   new FutureTask<String>(new Callable<String>() {
+ *   new FutureTask<>(new Callable<String>() {
  *     public String call() {
  *       return searcher.search(target);
  *   }});
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -395,7 +396,7 @@
         throws InterruptedException {
         // The code below is very delicate, to achieve these goals:
         // - call nanoTime exactly once for each call to park
-        // - if nanos <= 0, return promptly without allocation or nanoTime
+        // - if nanos <= 0L, return promptly without allocation or nanoTime
         // - if nanos == Long.MIN_VALUE, don't underflow
         // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
         //   and we suffer a spurious wakeup, we will do no worse than
@@ -404,19 +405,20 @@
         WaitNode q = null;
         boolean queued = false;
         for (;;) {
-            if (Thread.interrupted()) {
-                removeWaiter(q);
-                throw new InterruptedException();
-            }
-
             int s = state;
             if (s > COMPLETING) {
                 if (q != null)
                     q.thread = null;
                 return s;
             }
-            else if (s == COMPLETING) // cannot time out yet
+            else if (s == COMPLETING)
+                // We may have already promised (via isDone) that we are done
+                // so never return empty-handed or throw InterruptedException
                 Thread.yield();
+            else if (Thread.interrupted()) {
+                removeWaiter(q);
+                throw new InterruptedException();
+            }
             else if (q == null) {
                 if (timed && nanos <= 0L)
                     return s;
@@ -440,7 +442,9 @@
                     }
                     parkNanos = nanos - elapsed;
                 }
-                LockSupport.parkNanos(this, parkNanos);
+                // nanoTime may be slow; recheck before parking
+                if (state < COMPLETING)
+                    LockSupport.parkNanos(this, parkNanos);
             }
             else
                 LockSupport.park(this);
@@ -480,20 +484,25 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long RUNNER;
     private static final long WAITERS;
     static {
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = FutureTask.class;
-            STATE   = U.objectFieldOffset(k.getDeclaredField("state"));
-            RUNNER  = U.objectFieldOffset(k.getDeclaredField("runner"));
-            WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters"));
-        } catch (Exception e) {
+            STATE = U.objectFieldOffset
+                (FutureTask.class.getDeclaredField("state"));
+            RUNNER = U.objectFieldOffset
+                (FutureTask.class.getDeclaredField("runner"));
+            WAITERS = U.objectFieldOffset
+                (FutureTask.class.getDeclaredField("waiters"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
+
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Helpers.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+import java.util.Collection;
+
+/** Shared implementation code for java.util.concurrent. */
+class Helpers {
+    private Helpers() {}                // non-instantiable
+
+    /**
+     * An implementation of Collection.toString() suitable for classes
+     * with locks.  Instead of holding a lock for the entire duration of
+     * toString(), or acquiring a lock for each call to Iterator.next(),
+     * we hold the lock only during the call to toArray() (less
+     * disruptive to other threads accessing the collection) and follows
+     * the maxim "Never call foreign code while holding a lock".
+     */
+    static String collectionToString(Collection<?> c) {
+        final Object[] a = c.toArray();
+        final int size = a.length;
+        if (size == 0)
+            return "[]";
+        int charLength = 0;
+
+        // Replace every array element with its string representation
+        for (int i = 0; i < size; i++) {
+            Object e = a[i];
+            // Extreme compatibility with AbstractCollection.toString()
+            String s = (e == c) ? "(this Collection)" : objectToString(e);
+            a[i] = s;
+            charLength += s.length();
+        }
+
+        return toString(a, size, charLength);
+    }
+
+    /**
+     * Like Arrays.toString(), but caller guarantees that size > 0,
+     * each element with index 0 <= i < size is a non-null String,
+     * and charLength is the sum of the lengths of the input Strings.
+     */
+    static String toString(Object[] a, int size, int charLength) {
+        // assert a != null;
+        // assert size > 0;
+
+        // Copy each string into a perfectly sized char[]
+        // Length of [ , , , ] == 2 * size
+        final char[] chars = new char[charLength + 2 * size];
+        chars[0] = '[';
+        int j = 1;
+        for (int i = 0; i < size; i++) {
+            if (i > 0) {
+                chars[j++] = ',';
+                chars[j++] = ' ';
+            }
+            String s = (String) a[i];
+            int len = s.length();
+            s.getChars(0, len, chars, j);
+            j += len;
+        }
+        chars[j] = ']';
+        // assert j == chars.length - 1;
+        return new String(chars);
+    }
+
+    /** Optimized form of: key + "=" + val */
+    static String mapEntryToString(Object key, Object val) {
+        final String k, v;
+        final int klen, vlen;
+        final char[] chars =
+            new char[(klen = (k = objectToString(key)).length()) +
+                     (vlen = (v = objectToString(val)).length()) + 1];
+        k.getChars(0, klen, chars, 0);
+        chars[klen] = '=';
+        v.getChars(0, vlen, chars, klen + 1);
+        return new String(chars);
+    }
+
+    private static String objectToString(Object x) {
+        // Extreme compatibility with StringBuilder.append(null)
+        String s;
+        return (x == null || (s = x.toString()) == null) ? "null" : s;
+    }
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Wed Jul 05 20:54:58 2017 +0200
@@ -39,10 +39,10 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.Spliterator;
-import java.util.Spliterators;
 import java.util.function.Consumer;
 
 /**
@@ -72,7 +72,7 @@
  *
  * @since 1.6
  * @author  Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
  */
 public class LinkedBlockingDeque<E>
     extends AbstractQueue<E>
@@ -412,7 +412,7 @@
         lock.lockInterruptibly();
         try {
             while (!linkFirst(node)) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -435,7 +435,7 @@
         lock.lockInterruptibly();
         try {
             while (!linkLast(node)) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -517,7 +517,7 @@
         try {
             E x;
             while ( (x = unlinkFirst()) == null) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -535,7 +535,7 @@
         try {
             E x;
             while ( (x = unlinkLast()) == null) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -924,7 +924,7 @@
      * The following code can be used to dump the deque into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -959,26 +959,7 @@
     }
 
     public String toString() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            Node<E> p = first;
-            if (p == null)
-                return "[]";
-
-            StringBuilder sb = new StringBuilder();
-            sb.append('[');
-            for (;;) {
-                E e = p.item;
-                sb.append(e == this ? "(this Collection)" : e);
-                p = p.next;
-                if (p == null)
-                    return sb.append(']').toString();
-                sb.append(',').append(' ');
-            }
-        } finally {
-            lock.unlock();
-        }
+        return Helpers.collectionToString(this);
     }
 
     /**
@@ -1032,11 +1013,11 @@
     }
 
     /**
-     * Base class for Iterators for LinkedBlockingDeque
+     * Base class for LinkedBlockingDeque iterators.
      */
     private abstract class AbstractItr implements Iterator<E> {
         /**
-         * The next node to return in next()
+         * The next node to return in next().
          */
         Node<E> next;
 
@@ -1192,8 +1173,9 @@
                 if (i > 0) {
                     batch = i;
                     return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                         Spliterator.CONCURRENT);
+                        (a, 0, i, (Spliterator.ORDERED |
+                                   Spliterator.NONNULL |
+                                   Spliterator.CONCURRENT));
                 }
             }
             return null;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,15 +35,15 @@
 
 package java.util.concurrent;
 
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.AbstractQueue;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 
 /**
@@ -75,7 +75,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class LinkedBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
@@ -117,7 +117,7 @@
      */
 
     /**
-     * Linked list node class
+     * Linked list node class.
      */
     static class Node<E> {
         E item;
@@ -380,7 +380,7 @@
         putLock.lockInterruptibly();
         try {
             while (count.get() == capacity) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -462,7 +462,7 @@
         takeLock.lockInterruptibly();
         try {
             while (count.get() == 0) {
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -507,11 +507,7 @@
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lock();
         try {
-            Node<E> first = head.next;
-            if (first == null)
-                return null;
-            else
-                return first.item;
+            return (count.get() > 0) ? head.next.item : null;
         } finally {
             takeLock.unlock();
         }
@@ -630,7 +626,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -665,25 +661,7 @@
     }
 
     public String toString() {
-        fullyLock();
-        try {
-            Node<E> p = head.next;
-            if (p == null)
-                return "[]";
-
-            StringBuilder sb = new StringBuilder();
-            sb.append('[');
-            for (;;) {
-                E e = p.item;
-                sb.append(e == this ? "(this Collection)" : e);
-                p = p.next;
-                if (p == null)
-                    return sb.append(']').toString();
-                sb.append(',').append(' ');
-            }
-        } finally {
-            fullyUnlock();
-        }
+        return Helpers.collectionToString(this);
     }
 
     /**
@@ -801,34 +779,26 @@
             return current != null;
         }
 
-        /**
-         * Returns the next live successor of p, or null if no such.
-         *
-         * Unlike other traversal methods, iterators need to handle both:
-         * - dequeued nodes (p.next == p)
-         * - (possibly multiple) interior removed nodes (p.item == null)
-         */
-        private Node<E> nextNode(Node<E> p) {
-            for (;;) {
-                Node<E> s = p.next;
-                if (s == p)
-                    return head.next;
-                if (s == null || s.item != null)
-                    return s;
-                p = s;
-            }
-        }
-
         public E next() {
             fullyLock();
             try {
                 if (current == null)
                     throw new NoSuchElementException();
-                E x = currentElement;
                 lastRet = current;
-                current = nextNode(current);
-                currentElement = (current == null) ? null : current.item;
-                return x;
+                E item = null;
+                // Unlike other traversal methods, iterators must handle both:
+                // - dequeued nodes (p.next == p)
+                // - (possibly multiple) interior removed nodes (p.item == null)
+                for (Node<E> p = current, q;; p = q) {
+                    if ((q = p.next) == p)
+                        q = head.next;
+                    if (q == null || (item = q.item) != null) {
+                        current = q;
+                        E x = currentElement;
+                        currentElement = item;
+                        return x;
+                    }
+                }
             } finally {
                 fullyUnlock();
             }
@@ -901,8 +871,9 @@
                 if (i > 0) {
                     batch = i;
                     return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                         Spliterator.CONCURRENT);
+                        (a, 0, i, (Spliterator.ORDERED |
+                                   Spliterator.NONNULL |
+                                   Spliterator.CONCURRENT));
                 }
             }
             return null;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,14 +36,14 @@
 package java.util.concurrent;
 
 import java.util.AbstractQueue;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.LockSupport;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.concurrent.locks.LockSupport;
 import java.util.function.Consumer;
 
 /**
@@ -83,7 +83,7 @@
  *
  * @since 1.7
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class LinkedTransferQueue<E> extends AbstractQueue<E>
     implements TransferQueue<E>, java.io.Serializable {
@@ -108,7 +108,7 @@
      *
      * A FIFO dual queue may be implemented using a variation of the
      * Michael & Scott (M&S) lock-free queue algorithm
-     * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
+     * (http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf).
      * It maintains two pointer fields, "head", pointing to a
      * (matched) node that in turn points to the first actual
      * (unmatched) queue node (or null if empty); and "tail" that
@@ -215,7 +215,7 @@
      * of costly-to-reclaim garbage caused by the sequential "next"
      * links of nodes starting at old forgotten head nodes: As first
      * described in detail by Boehm
-     * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC
+     * (http://portal.acm.org/citation.cfm?doid=503272.503282), if a GC
      * delays noticing that any arbitrarily old node has become
      * garbage, all newer dead nodes will also be unreclaimed.
      * (Similar issues arise in non-GC environments.)  To cope with
@@ -456,12 +456,12 @@
 
         // CAS methods for fields
         final boolean casNext(Node cmp, Node val) {
-            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+            return U.compareAndSwapObject(this, NEXT, cmp, val);
         }
 
         final boolean casItem(Object cmp, Object val) {
             // assert cmp == null || cmp.getClass() != Node.class;
-            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+            return U.compareAndSwapObject(this, ITEM, cmp, val);
         }
 
         /**
@@ -469,7 +469,7 @@
          * only be seen after publication via casNext.
          */
         Node(Object item, boolean isData) {
-            UNSAFE.putObject(this, itemOffset, item); // relaxed write
+            U.putObject(this, ITEM, item); // relaxed write
             this.isData = isData;
         }
 
@@ -478,7 +478,7 @@
          * only after CASing head field, so uses relaxed write.
          */
         final void forgetNext() {
-            UNSAFE.putObject(this, nextOffset, this);
+            U.putObject(this, NEXT, this);
         }
 
         /**
@@ -491,8 +491,8 @@
          * else we don't care).
          */
         final void forgetContents() {
-            UNSAFE.putObject(this, itemOffset, this);
-            UNSAFE.putObject(this, waiterOffset, null);
+            U.putObject(this, ITEM, this);
+            U.putObject(this, WAITER, null);
         }
 
         /**
@@ -538,21 +538,19 @@
         private static final long serialVersionUID = -3375979862319811754L;
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long itemOffset;
-        private static final long nextOffset;
-        private static final long waiterOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long ITEM;
+        private static final long NEXT;
+        private static final long WAITER;
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = Node.class;
-                itemOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("item"));
-                nextOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("next"));
-                waiterOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("waiter"));
-            } catch (Exception e) {
+                ITEM = U.objectFieldOffset
+                    (Node.class.getDeclaredField("item"));
+                NEXT = U.objectFieldOffset
+                    (Node.class.getDeclaredField("next"));
+                WAITER = U.objectFieldOffset
+                    (Node.class.getDeclaredField("waiter"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -569,15 +567,15 @@
 
     // CAS methods for fields
     private boolean casTail(Node cmp, Node val) {
-        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+        return U.compareAndSwapObject(this, TAIL, cmp, val);
     }
 
     private boolean casHead(Node cmp, Node val) {
-        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+        return U.compareAndSwapObject(this, HEAD, cmp, val);
     }
 
     private boolean casSweepVotes(int cmp, int val) {
-        return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
+        return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
     }
 
     /*
@@ -588,12 +586,6 @@
     private static final int SYNC  = 2; // for transfer, take
     private static final int TIMED = 3; // for timed poll, tryTransfer
 
-    @SuppressWarnings("unchecked")
-    static <E> E cast(Object item) {
-        // assert item == null || item.getClass() != Node.class;
-        return (E) item;
-    }
-
     /**
      * Implements all queuing methods. See above for explanation.
      *
@@ -630,7 +622,8 @@
                                 break;        // unless slack < 2
                         }
                         LockSupport.unpark(p.waiter);
-                        return LinkedTransferQueue.<E>cast(item);
+                        @SuppressWarnings("unchecked") E itemE = (E) item;
+                        return itemE;
                     }
                 }
                 Node n = p.next;
@@ -708,15 +701,15 @@
             if (item != e) {                  // matched
                 // assert item != s;
                 s.forgetContents();           // avoid garbage
-                return LinkedTransferQueue.<E>cast(item);
+                @SuppressWarnings("unchecked") E itemE = (E) item;
+                return itemE;
             }
-            if ((w.isInterrupted() || (timed && nanos <= 0)) &&
-                    s.casItem(e, s)) {        // cancel
-                unsplice(pred, s);
-                return e;
+            else if (w.isInterrupted() || (timed && nanos <= 0L)) {
+                unsplice(pred, s);           // try to unlink and cancel
+                if (s.casItem(e, s))         // return normally if lost CAS
+                    return e;
             }
-
-            if (spins < 0) {                  // establish spins at/near front
+            else if (spins < 0) {            // establish spins at/near front
                 if ((spins = spinsFor(pred, s.isData)) > 0)
                     randomYields = ThreadLocalRandom.current();
             }
@@ -768,52 +761,25 @@
     }
 
     /**
-     * Returns the first unmatched node of the given mode, or null if
-     * none.  Used by methods isEmpty, hasWaitingConsumer.
-     */
-    private Node firstOfMode(boolean isData) {
-        for (Node p = head; p != null; p = succ(p)) {
-            if (!p.isMatched())
-                return (p.isData == isData) ? p : null;
-        }
-        return null;
-    }
-
-    /**
-     * Version of firstOfMode used by Spliterator. Callers must
-     * recheck if the returned node's item field is null or
-     * self-linked before using.
+     * Returns the first unmatched data node, or null if none.
+     * Callers must recheck if the returned node's item field is null
+     * or self-linked before using.
      */
     final Node firstDataNode() {
-        for (Node p = head; p != null;) {
-            Object item = p.item;
-            if (p.isData) {
-                if (item != null && item != p)
-                    return p;
+        restartFromHead: for (;;) {
+            for (Node p = head; p != null;) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p)
+                        return p;
+                }
+                else if (item == null)
+                    break;
+                if (p == (p = p.next))
+                    continue restartFromHead;
             }
-            else if (item == null)
-                break;
-            if (p == (p = p.next))
-                p = head;
+            return null;
         }
-        return null;
-    }
-
-    /**
-     * Returns the item in the first unmatched node with isData; or
-     * null if none.  Used by peek.
-     */
-    private E firstDataItem() {
-        for (Node p = head; p != null; p = succ(p)) {
-            Object item = p.item;
-            if (p.isData) {
-                if (item != null && item != p)
-                    return LinkedTransferQueue.<E>cast(item);
-            }
-            else if (item == null)
-                return null;
-        }
-        return null;
     }
 
     /**
@@ -821,23 +787,140 @@
      * Used by methods size and getWaitingConsumerCount.
      */
     private int countOfMode(boolean data) {
-        int count = 0;
-        for (Node p = head; p != null; ) {
-            if (!p.isMatched()) {
-                if (p.isData != data)
-                    return 0;
-                if (++count == Integer.MAX_VALUE) // saturated
+        restartFromHead: for (;;) {
+            int count = 0;
+            for (Node p = head; p != null;) {
+                if (!p.isMatched()) {
+                    if (p.isData != data)
+                        return 0;
+                    if (++count == Integer.MAX_VALUE)
+                        break;  // @see Collection.size()
+                }
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            return count;
+        }
+    }
+
+    public String toString() {
+        String[] a = null;
+        restartFromHead: for (;;) {
+            int charLength = 0;
+            int size = 0;
+            for (Node p = head; p != null;) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p) {
+                        if (a == null)
+                            a = new String[4];
+                        else if (size == a.length)
+                            a = Arrays.copyOf(a, 2 * size);
+                        String s = item.toString();
+                        a[size++] = s;
+                        charLength += s.length();
+                    }
+                } else if (item == null)
                     break;
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+
+            if (size == 0)
+                return "[]";
+
+            return Helpers.toString(a, size, charLength);
+        }
+    }
+
+    private Object[] toArrayInternal(Object[] a) {
+        Object[] x = a;
+        restartFromHead: for (;;) {
+            int size = 0;
+            for (Node p = head; p != null;) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p) {
+                        if (x == null)
+                            x = new Object[4];
+                        else if (size == x.length)
+                            x = Arrays.copyOf(x, 2 * (size + 4));
+                        x[size++] = item;
+                    }
+                } else if (item == null)
+                    break;
+                if (p == (p = p.next))
+                    continue restartFromHead;
             }
-            Node n = p.next;
-            if (n != p)
-                p = n;
-            else {
-                count = 0;
-                p = head;
+            if (x == null)
+                return new Object[0];
+            else if (a != null && size <= a.length) {
+                if (a != x)
+                    System.arraycopy(x, 0, a, 0, size);
+                if (size < a.length)
+                    a[size] = null;
+                return a;
             }
+            return (size == x.length) ? x : Arrays.copyOf(x, size);
         }
-        return count;
+    }
+
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
+    public Object[] toArray() {
+        return toArrayInternal(null);
+    }
+
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence; the runtime type of the returned array is that of
+     * the specified array.  If the queue fits in the specified array, it
+     * is returned therein.  Otherwise, a new array is allocated with the
+     * runtime type of the specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * {@code null}.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose {@code x} is a queue known to contain only strings.
+     * The following code can be used to dump the queue into a newly
+     * allocated array of {@code String}:
+     *
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     *
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T[] toArray(T[] a) {
+        if (a == null) throw new NullPointerException();
+        return (T[]) toArrayInternal(a);
     }
 
     final class Itr implements Iterator<E> {
@@ -886,7 +969,8 @@
                 Object item = s.item;
                 if (s.isData) {
                     if (item != null && item != s) {
-                        nextItem = LinkedTransferQueue.<E>cast(item);
+                        @SuppressWarnings("unchecked") E itemE = (E) item;
+                        nextItem = itemE;
                         nextNode = s;
                         return;
                     }
@@ -934,23 +1018,19 @@
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LTQSpliterator<E> implements Spliterator<E> {
+    final class LTQSpliterator<E> implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedTransferQueue<E> queue;
-        Node current;    // current node; null until initialized
+        Node current;       // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        LTQSpliterator(LinkedTransferQueue<E> queue) {
-            this.queue = queue;
-        }
+        LTQSpliterator() {}
 
         public Spliterator<E> trySplit() {
             Node p;
-            final LinkedTransferQueue<E> q = this.queue;
             int b = batch;
             int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
             if (!exhausted &&
-                ((p = current) != null || (p = q.firstDataNode()) != null) &&
+                ((p = current) != null || (p = firstDataNode()) != null) &&
                 p.next != null) {
                 Object[] a = new Object[n];
                 int i = 0;
@@ -959,15 +1039,16 @@
                     if (e != p && (a[i] = e) != null)
                         ++i;
                     if (p == (p = p.next))
-                        p = q.firstDataNode();
+                        p = firstDataNode();
                 } while (p != null && i < n && p.isData);
                 if ((current = p) == null)
                     exhausted = true;
                 if (i > 0) {
                     batch = i;
                     return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                         Spliterator.CONCURRENT);
+                        (a, 0, i, (Spliterator.ORDERED |
+                                   Spliterator.NONNULL |
+                                   Spliterator.CONCURRENT));
                 }
             }
             return null;
@@ -977,16 +1058,15 @@
         public void forEachRemaining(Consumer<? super E> action) {
             Node p;
             if (action == null) throw new NullPointerException();
-            final LinkedTransferQueue<E> q = this.queue;
             if (!exhausted &&
-                ((p = current) != null || (p = q.firstDataNode()) != null)) {
+                ((p = current) != null || (p = firstDataNode()) != null)) {
                 exhausted = true;
                 do {
                     Object e = p.item;
                     if (e != null && e != p)
                         action.accept((E)e);
                     if (p == (p = p.next))
-                        p = q.firstDataNode();
+                        p = firstDataNode();
                 } while (p != null && p.isData);
             }
         }
@@ -995,15 +1075,14 @@
         public boolean tryAdvance(Consumer<? super E> action) {
             Node p;
             if (action == null) throw new NullPointerException();
-            final LinkedTransferQueue<E> q = this.queue;
             if (!exhausted &&
-                ((p = current) != null || (p = q.firstDataNode()) != null)) {
+                ((p = current) != null || (p = firstDataNode()) != null)) {
                 Object e;
                 do {
                     if ((e = p.item) == p)
                         e = null;
                     if (p == (p = p.next))
-                        p = q.firstDataNode();
+                        p = firstDataNode();
                 } while (e == null && p != null && p.isData);
                 if ((current = p) == null)
                     exhausted = true;
@@ -1040,7 +1119,7 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new LTQSpliterator<E>(this);
+        return new LTQSpliterator<E>();
     }
 
     /* -------------- Removal methods -------------- */
@@ -1054,7 +1133,7 @@
      * @param s the node to be unspliced
      */
     final void unsplice(Node pred, Node s) {
-        s.forgetContents(); // forget unneeded fields
+        s.waiter = null; // disable signals
         /*
          * See above for rationale. Briefly: if pred still points to
          * s, try to unlink s.  If s cannot be unlinked, because it is
@@ -1332,7 +1411,22 @@
     }
 
     public E peek() {
-        return firstDataItem();
+        restartFromHead: for (;;) {
+            for (Node p = head; p != null;) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p) {
+                        @SuppressWarnings("unchecked") E e = (E) item;
+                        return e;
+                    }
+                }
+                else if (item == null)
+                    break;
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            return null;
+        }
     }
 
     /**
@@ -1341,15 +1435,24 @@
      * @return {@code true} if this queue contains no elements
      */
     public boolean isEmpty() {
-        for (Node p = head; p != null; p = succ(p)) {
-            if (!p.isMatched())
-                return !p.isData;
-        }
-        return true;
+        return firstDataNode() == null;
     }
 
     public boolean hasWaitingConsumer() {
-        return firstOfMode(false) != null;
+        restartFromHead: for (;;) {
+            for (Node p = head; p != null;) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p)
+                        break;
+                }
+                else if (item == null)
+                    return true;
+                if (p == (p = p.next))
+                    continue restartFromHead;
+            }
+            return false;
+        }
     }
 
     /**
@@ -1396,15 +1499,16 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        if (o == null) return false;
-        for (Node p = head; p != null; p = succ(p)) {
-            Object item = p.item;
-            if (p.isData) {
-                if (item != null && item != p && o.equals(item))
-                    return true;
+        if (o != null) {
+            for (Node p = head; p != null; p = succ(p)) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p && o.equals(item))
+                        return true;
+                }
+                else if (item == null)
+                    break;
             }
-            else if (item == null)
-                break;
         }
         return false;
     }
@@ -1460,22 +1564,24 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long headOffset;
-    private static final long tailOffset;
-    private static final long sweepVotesOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long HEAD;
+    private static final long TAIL;
+    private static final long SWEEPVOTES;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = LinkedTransferQueue.class;
-            headOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("head"));
-            tailOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("tail"));
-            sweepVotesOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("sweepVotes"));
-        } catch (Exception e) {
+            HEAD = U.objectFieldOffset
+                (LinkedTransferQueue.class.getDeclaredField("head"));
+            TAIL = U.objectFieldOffset
+                (LinkedTransferQueue.class.getDeclaredField("tail"));
+            SWEEPVOTES = U.objectFieldOffset
+                (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
+
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,8 +35,6 @@
 
 package java.util.concurrent;
 
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 
@@ -73,7 +71,7 @@
  *
  * <ul>
  *
- *   <li> <b>Arrival.</b> Methods {@link #arrive} and
+ *   <li><b>Arrival.</b> Methods {@link #arrive} and
  *       {@link #arriveAndDeregister} record arrival.  These methods
  *       do not block, but return an associated <em>arrival phase
  *       number</em>; that is, the phase number of the phaser to which
@@ -86,7 +84,7 @@
  *       flexible than, providing a barrier action to a {@code
  *       CyclicBarrier}.
  *
- *   <li> <b>Waiting.</b> Method {@link #awaitAdvance} requires an
+ *   <li><b>Waiting.</b> Method {@link #awaitAdvance} requires an
  *       argument indicating an arrival phase number, and returns when
  *       the phaser advances to (or is already at) a different phase.
  *       Unlike similar constructions using {@code CyclicBarrier},
@@ -97,9 +95,10 @@
  *       state of the phaser. If necessary, you can perform any
  *       associated recovery within handlers of those exceptions,
  *       often after invoking {@code forceTermination}.  Phasers may
- *       also be used by tasks executing in a {@link ForkJoinPool},
- *       which will ensure sufficient parallelism to execute tasks
- *       when others are blocked waiting for a phase to advance.
+ *       also be used by tasks executing in a {@link ForkJoinPool}.
+ *       Progress is ensured if the pool's parallelismLevel can
+ *       accommodate the maximum number of simultaneously blocked
+ *       parties.
  *
  * </ul>
  *
@@ -155,7 +154,7 @@
  * The typical idiom is for the method setting this up to first
  * register, then start the actions, then deregister, as in:
  *
- *  <pre> {@code
+ * <pre> {@code
  * void runTasks(List<Runnable> tasks) {
  *   final Phaser phaser = new Phaser(1); // "1" to register self
  *   // create and start threads
@@ -176,7 +175,7 @@
  * <p>One way to cause a set of threads to repeatedly perform actions
  * for a given number of iterations is to override {@code onAdvance}:
  *
- *  <pre> {@code
+ * <pre> {@code
  * void startTasks(List<Runnable> tasks, final int iterations) {
  *   final Phaser phaser = new Phaser() {
  *     protected boolean onAdvance(int phase, int registeredParties) {
@@ -200,7 +199,7 @@
  *
  * If the main task must later await termination, it
  * may re-register and then execute a similar loop:
- *  <pre> {@code
+ * <pre> {@code
  *   // ...
  *   phaser.register();
  *   while (!phaser.isTerminated())
@@ -210,7 +209,7 @@
  * in contexts where you are sure that the phase will never wrap around
  * {@code Integer.MAX_VALUE}. For example:
  *
- *  <pre> {@code
+ * <pre> {@code
  * void awaitPhase(Phaser phaser, int phase) {
  *   int p = phaser.register(); // assumes caller not already registered
  *   while (p < phase) {
@@ -230,7 +229,7 @@
  * new Phaser())}, these tasks could then be started, for example by
  * submitting to a pool:
  *
- *  <pre> {@code
+ * <pre> {@code
  * void build(Task[] tasks, int lo, int hi, Phaser ph) {
  *   if (hi - lo > TASKS_PER_PHASER) {
  *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
@@ -331,7 +330,7 @@
     }
 
     /**
-     * The parent of this phaser, or null if none
+     * The parent of this phaser, or null if none.
      */
     private final Phaser parent;
 
@@ -389,7 +388,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adjust)) {
+            if (U.compareAndSwapLong(this, STATE, s, s-=adjust)) {
                 if (unarrived == 1) {
                     long n = s & PARTIES_MASK;  // base of next state
                     int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -402,13 +401,12 @@
                             n |= nextUnarrived;
                         int nextPhase = (phase + 1) & MAX_PHASE;
                         n |= (long)nextPhase << PHASE_SHIFT;
-                        UNSAFE.compareAndSwapLong(this, stateOffset, s, n);
+                        U.compareAndSwapLong(this, STATE, s, n);
                         releaseWaiters(phase);
                     }
                     else if (nextUnarrived == 0) { // propagate deregistration
                         phase = parent.doArrive(ONE_DEREGISTER);
-                        UNSAFE.compareAndSwapLong(this, stateOffset,
-                                                  s, s | EMPTY);
+                        U.compareAndSwapLong(this, STATE, s, s | EMPTY);
                     }
                     else
                         phase = parent.doArrive(ONE_ARRIVAL);
@@ -419,7 +417,7 @@
     }
 
     /**
-     * Implementation of register, bulkRegister
+     * Implementation of register, bulkRegister.
      *
      * @param registrations number to add to both parties and
      * unarrived fields. Must be greater than zero.
@@ -443,14 +441,13 @@
                 if (parent == null || reconcileState() == s) {
                     if (unarrived == 0)             // wait out advance
                         root.internalAwaitAdvance(phase, null);
-                    else if (UNSAFE.compareAndSwapLong(this, stateOffset,
-                                                       s, s + adjust))
+                    else if (U.compareAndSwapLong(this, STATE, s, s + adjust))
                         break;
                 }
             }
             else if (parent == null) {              // 1st root registration
                 long next = ((long)phase << PHASE_SHIFT) | adjust;
-                if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next))
+                if (U.compareAndSwapLong(this, STATE, s, next))
                     break;
             }
             else {
@@ -462,8 +459,8 @@
                         // finish registration whenever parent registration
                         // succeeded, even when racing with termination,
                         // since these are part of the same "transaction".
-                        while (!UNSAFE.compareAndSwapLong
-                               (this, stateOffset, s,
+                        while (!U.compareAndSwapLong
+                               (this, STATE, s,
                                 ((long)phase << PHASE_SHIFT) | adjust)) {
                             s = state;
                             phase = (int)(root.state >>> PHASE_SHIFT);
@@ -494,8 +491,8 @@
             // CAS to root phase with current parties, tripping unarrived
             while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
                    (int)(s >>> PHASE_SHIFT) &&
-                   !UNSAFE.compareAndSwapLong
-                   (this, stateOffset, s,
+                   !U.compareAndSwapLong
+                   (this, STATE, s,
                     s = (((long)phase << PHASE_SHIFT) |
                          ((phase < 0) ? (s & COUNTS_MASK) :
                           (((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -684,8 +681,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (UNSAFE.compareAndSwapLong(this, stateOffset, s,
-                                          s -= ONE_ARRIVAL)) {
+            if (U.compareAndSwapLong(this, STATE, s, s -= ONE_ARRIVAL)) {
                 if (unarrived > 1)
                     return root.internalAwaitAdvance(phase, null);
                 if (root != this)
@@ -700,7 +696,7 @@
                     n |= nextUnarrived;
                 int nextPhase = (phase + 1) & MAX_PHASE;
                 n |= (long)nextPhase << PHASE_SHIFT;
-                if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n))
+                if (!U.compareAndSwapLong(this, STATE, s, n))
                     return (int)(state >>> PHASE_SHIFT); // terminated
                 releaseWaiters(phase);
                 return nextPhase;
@@ -816,8 +812,7 @@
         final Phaser root = this.root;
         long s;
         while ((s = root.state) >= 0) {
-            if (UNSAFE.compareAndSwapLong(root, stateOffset,
-                                          s, s | TERMINATION_BIT)) {
+            if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
                 // signal all threads
                 releaseWaiters(0); // Waiters on evenQ
                 releaseWaiters(1); // Waiters on oddQ
@@ -956,7 +951,7 @@
     }
 
     /**
-     * Implementation of toString and string-based error messages
+     * Implementation of toString and string-based error messages.
      */
     private String stateToString(long s) {
         return super.toString() +
@@ -1065,7 +1060,7 @@
             else {
                 try {
                     ForkJoinPool.managedBlock(node);
-                } catch (InterruptedException ie) {
+                } catch (InterruptedException cantHappen) {
                     node.wasInterrupted = true;
                 }
             }
@@ -1084,7 +1079,7 @@
     }
 
     /**
-     * Wait nodes for Treiber stack representing wait queue
+     * Wait nodes for Treiber stack representing wait queue.
      */
     static final class QNode implements ForkJoinPool.ManagedBlocker {
         final Phaser phaser;
@@ -1121,41 +1116,39 @@
                 thread = null;
                 return true;
             }
-            if (timed) {
-                if (nanos > 0L) {
-                    nanos = deadline - System.nanoTime();
-                }
-                if (nanos <= 0L) {
-                    thread = null;
-                    return true;
-                }
+            if (timed &&
+                (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
+                thread = null;
+                return true;
             }
             return false;
         }
 
         public boolean block() {
-            if (isReleasable())
-                return true;
-            else if (!timed)
-                LockSupport.park(this);
-            else if (nanos > 0L)
-                LockSupport.parkNanos(this, nanos);
-            return isReleasable();
+            while (!isReleasable()) {
+                if (timed)
+                    LockSupport.parkNanos(this, nanos);
+                else
+                    LockSupport.park(this);
+            }
+            return true;
         }
     }
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long stateOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long STATE;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = Phaser.class;
-            stateOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("state"));
-        } catch (Exception e) {
+            STATE = U.objectFieldOffset
+                (Phaser.class.getDeclaredField("state"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
+
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,8 +35,6 @@
 
 package java.util.concurrent;
 
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -47,6 +45,8 @@
 import java.util.Queue;
 import java.util.SortedSet;
 import java.util.Spliterator;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 
 /**
@@ -78,7 +78,7 @@
  * tie-breaking to comparable elements. To use it, you would insert a
  * {@code new FIFOEntry(anEntry)} instead of a plain entry object.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class FIFOEntry<E extends Comparable<? super E>>
  *     implements Comparable<FIFOEntry<E>> {
  *   static final AtomicLong seq = new AtomicLong(0);
@@ -103,7 +103,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 @SuppressWarnings("unchecked")
 public class PriorityBlockingQueue<E> extends AbstractQueue<E>
@@ -161,12 +161,12 @@
     private transient Comparator<? super E> comparator;
 
     /**
-     * Lock used for all public operations
+     * Lock used for all public operations.
      */
     private final ReentrantLock lock;
 
     /**
-     * Condition for blocking when empty
+     * Condition for blocking when empty.
      */
     private final Condition notEmpty;
 
@@ -289,8 +289,7 @@
         lock.unlock(); // must release and then re-acquire main lock
         Object[] newArray = null;
         if (allocationSpinLock == 0 &&
-            UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
-                                     0, 1)) {
+            U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
             try {
                 int newCap = oldCap + ((oldCap < 64) ?
                                        (oldCap + 2) : // grow faster if small
@@ -672,7 +671,7 @@
     }
 
     /**
-     * Identity-based version for use in Itr.remove
+     * Identity-based version for use in Itr.remove.
      */
     void removeEQ(Object o) {
         final ReentrantLock lock = this.lock;
@@ -708,48 +707,8 @@
         }
     }
 
-    /**
-     * Returns an array containing all of the elements in this queue.
-     * The returned array elements are in no particular order.
-     *
-     * <p>The returned array will be "safe" in that no references to it are
-     * maintained by this queue.  (In other words, this method must allocate
-     * a new array).  The caller is thus free to modify the returned array.
-     *
-     * <p>This method acts as bridge between array-based and collection-based
-     * APIs.
-     *
-     * @return an array containing all of the elements in this queue
-     */
-    public Object[] toArray() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return Arrays.copyOf(queue, size);
-        } finally {
-            lock.unlock();
-        }
-    }
-
     public String toString() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int n = size;
-            if (n == 0)
-                return "[]";
-            StringBuilder sb = new StringBuilder();
-            sb.append('[');
-            for (int i = 0; i < n; ++i) {
-                Object e = queue[i];
-                sb.append(e == this ? "(this Collection)" : e);
-                if (i != n - 1)
-                    sb.append(',').append(' ');
-            }
-            return sb.append(']').toString();
-        } finally {
-            lock.unlock();
-        }
+        return Helpers.collectionToString(this);
     }
 
     /**
@@ -808,6 +767,29 @@
     }
 
     /**
+     * Returns an array containing all of the elements in this queue.
+     * The returned array elements are in no particular order.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
+    public Object[] toArray() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return Arrays.copyOf(queue, size);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
      * Returns an array containing all of the elements in this queue; the
      * runtime type of the returned array is that of the specified array.
      * The returned array elements are in no particular order.
@@ -829,7 +811,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+     * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -971,7 +953,7 @@
             return hi;
         }
 
-        public Spliterator<E> trySplit() {
+        public PBQSpliterator<E> trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
                 new PBQSpliterator<E>(queue, array, lo, index = mid);
@@ -1028,15 +1010,13 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long allocationSpinLockOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long ALLOCATIONSPINLOCK;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = PriorityBlockingQueue.class;
-            allocationSpinLockOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("allocationSpinLock"));
-        } catch (Exception e) {
+            ALLOCATIONSPINLOCK = U.objectFieldOffset
+                (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveAction.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveAction.java	Wed Jul 05 20:54:58 2017 +0200
@@ -45,7 +45,7 @@
  * <p><b>Sample Usages.</b> Here is a simple but complete ForkJoin
  * sort that sorts a given {@code long[]} array:
  *
- *  <pre> {@code
+ * <pre> {@code
  * static class SortTask extends RecursiveAction {
  *   final long[] array; final int lo, hi;
  *   SortTask(long[] array, int lo, int hi) {
@@ -79,7 +79,7 @@
  * SortTask(anArray)} and invoking it in a ForkJoinPool.  As a more
  * concrete simple example, the following task increments each element
  * of an array:
- *  <pre> {@code
+ * <pre> {@code
  * class IncrementTask extends RecursiveAction {
  *   final long[] array; final int lo, hi;
  *   IncrementTask(long[] array, int lo, int hi) {
@@ -110,7 +110,7 @@
  * performing leaf actions on unstolen tasks rather than further
  * subdividing.
  *
- *  <pre> {@code
+ * <pre> {@code
  * double sumOfSquares(ForkJoinPool pool, double[] array) {
  *   int n = array.length;
  *   Applyer a = new Applyer(array, 0, n, null);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveTask.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveTask.java	Wed Jul 05 20:54:58 2017 +0200
@@ -40,11 +40,11 @@
  *
  * <p>For a classic example, here is a task computing Fibonacci numbers:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Fibonacci extends RecursiveTask<Integer> {
  *   final int n;
  *   Fibonacci(int n) { this.n = n; }
- *   Integer compute() {
+ *   protected Integer compute() {
  *     if (n <= 1)
  *       return n;
  *     Fibonacci f1 = new Fibonacci(n - 1);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java	Wed Jul 05 20:54:58 2017 +0200
@@ -70,7 +70,7 @@
  * Here is a class with a method that sets up a ScheduledExecutorService
  * to beep every ten seconds for an hour:
  *
- *  <pre> {@code
+ * <pre> {@code
  * import static java.util.concurrent.TimeUnit.*;
  * class BeeperControl {
  *   private final ScheduledExecutorService scheduler =
@@ -129,23 +129,37 @@
     /**
      * Creates and executes a periodic action that becomes enabled first
      * after the given initial delay, and subsequently with the given
-     * period; that is executions will commence after
-     * {@code initialDelay} then {@code initialDelay+period}, then
+     * period; that is, executions will commence after
+     * {@code initialDelay}, then {@code initialDelay + period}, then
      * {@code initialDelay + 2 * period}, and so on.
-     * If any execution of the task
-     * encounters an exception, subsequent executions are suppressed.
-     * Otherwise, the task will only terminate via cancellation or
-     * termination of the executor.  If any execution of this task
-     * takes longer than its period, then subsequent executions
-     * may start late, but will not concurrently execute.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>The executor terminates, also resulting in task cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will
+     * throw {@link ExecutionException}.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
+     *
+     * <p>If any execution of this task takes longer than its period, then
+     * subsequent executions may start late, but will not concurrently
+     * execute.
      *
      * @param command the task to execute
      * @param initialDelay the time to delay first execution
      * @param period the period between successive executions
      * @param unit the time unit of the initialDelay and period parameters
      * @return a ScheduledFuture representing pending completion of
-     *         the task, and whose {@code get()} method will throw an
-     *         exception upon cancellation
+     *         the series of repeated tasks.  The future's {@link
+     *         Future#get() get()} method will never return normally,
+     *         and will throw an exception upon task cancellation or
+     *         abnormal termination of a task execution.
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      * @throws NullPointerException if command is null
@@ -160,10 +174,21 @@
      * Creates and executes a periodic action that becomes enabled first
      * after the given initial delay, and subsequently with the
      * given delay between the termination of one execution and the
-     * commencement of the next.  If any execution of the task
-     * encounters an exception, subsequent executions are suppressed.
-     * Otherwise, the task will only terminate via cancellation or
-     * termination of the executor.
+     * commencement of the next.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>The executor terminates, also resulting in task cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will
+     * throw {@link ExecutionException}.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
      *
      * @param command the task to execute
      * @param initialDelay the time to delay first execution
@@ -171,8 +196,10 @@
      * execution and the commencement of the next
      * @param unit the time unit of the initialDelay and delay parameters
      * @return a ScheduledFuture representing pending completion of
-     *         the task, and whose {@code get()} method will throw an
-     *         exception upon cancellation
+     *         the series of repeated tasks.  The future's {@link
+     *         Future#get() get()} method will never return normally,
+     *         and will throw an exception upon task cancellation or
+     *         abnormal termination of a task execution.
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      * @throws NullPointerException if command is null
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,19 +34,27 @@
  */
 
 package java.util.concurrent;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.AbstractQueue;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
 
 /**
  * A {@link ThreadPoolExecutor} that can additionally schedule
- * commands to run after a given delay, or to execute
- * periodically. This class is preferable to {@link java.util.Timer}
- * when multiple worker threads are needed, or when the additional
- * flexibility or capabilities of {@link ThreadPoolExecutor} (which
- * this class extends) are required.
+ * commands to run after a given delay, or to execute periodically.
+ * This class is preferable to {@link java.util.Timer} when multiple
+ * worker threads are needed, or when the additional flexibility or
+ * capabilities of {@link ThreadPoolExecutor} (which this class
+ * extends) are required.
  *
  * <p>Delayed tasks execute no sooner than they are enabled, but
  * without any real-time guarantees about when, after they are
@@ -55,20 +63,19 @@
  * submission.
  *
  * <p>When a submitted task is cancelled before it is run, execution
- * is suppressed. By default, such a cancelled task is not
- * automatically removed from the work queue until its delay
- * elapses. While this enables further inspection and monitoring, it
- * may also cause unbounded retention of cancelled tasks. To avoid
- * this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which
- * causes tasks to be immediately removed from the work queue at
- * time of cancellation.
+ * is suppressed.  By default, such a cancelled task is not
+ * automatically removed from the work queue until its delay elapses.
+ * While this enables further inspection and monitoring, it may also
+ * cause unbounded retention of cancelled tasks.  To avoid this, use
+ * {@link #setRemoveOnCancelPolicy} to cause tasks to be immediately
+ * removed from the work queue at time of cancellation.
  *
- * <p>Successive executions of a task scheduled via
- * {@code scheduleAtFixedRate} or
- * {@code scheduleWithFixedDelay} do not overlap. While different
- * executions may be performed by different threads, the effects of
- * prior executions <a
- * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * <p>Successive executions of a periodic task scheduled via
+ * {@link #scheduleAtFixedRate scheduleAtFixedRate} or
+ * {@link #scheduleWithFixedDelay scheduleWithFixedDelay}
+ * do not overlap. While different executions may be performed by
+ * different threads, the effects of prior executions
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  * those of subsequent ones.
  *
  * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
@@ -98,7 +105,7 @@
  * {@link FutureTask}. However, this may be modified or replaced using
  * subclasses of the form:
  *
- *  <pre> {@code
+ * <pre> {@code
  * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
  *
  *   static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
@@ -160,9 +167,9 @@
     private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
 
     /**
-     * True if ScheduledFutureTask.cancel should remove from queue
+     * True if ScheduledFutureTask.cancel should remove from queue.
      */
-    private volatile boolean removeOnCancel = false;
+    volatile boolean removeOnCancel;
 
     /**
      * Sequence number to break scheduling ties, and in turn to
@@ -173,7 +180,7 @@
     /**
      * Returns current nanosecond time.
      */
-    final long now() {
+    static final long now() {
         return System.nanoTime();
     }
 
@@ -184,13 +191,13 @@
         private final long sequenceNumber;
 
         /** The time the task is enabled to execute in nanoTime units */
-        private long time;
+        private volatile long time;
 
         /**
-         * Period in nanoseconds for repeating tasks.  A positive
-         * value indicates fixed-rate execution.  A negative value
-         * indicates fixed-delay execution.  A value of 0 indicates a
-         * non-repeating task.
+         * Period in nanoseconds for repeating tasks.
+         * A positive value indicates fixed-rate execution.
+         * A negative value indicates fixed-delay execution.
+         * A value of 0 indicates a non-repeating (one-shot) task.
          */
         private final long period;
 
@@ -205,31 +212,35 @@
         /**
          * Creates a one-shot action with given nanoTime-based trigger time.
          */
-        ScheduledFutureTask(Runnable r, V result, long ns) {
+        ScheduledFutureTask(Runnable r, V result, long triggerTime,
+                            long sequenceNumber) {
             super(r, result);
-            this.time = ns;
+            this.time = triggerTime;
             this.period = 0;
-            this.sequenceNumber = sequencer.getAndIncrement();
+            this.sequenceNumber = sequenceNumber;
         }
 
         /**
-         * Creates a periodic action with given nano time and period.
+         * Creates a periodic action with given nanoTime-based initial
+         * trigger time and period.
          */
-        ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+        ScheduledFutureTask(Runnable r, V result, long triggerTime,
+                            long period, long sequenceNumber) {
             super(r, result);
-            this.time = ns;
+            this.time = triggerTime;
             this.period = period;
-            this.sequenceNumber = sequencer.getAndIncrement();
+            this.sequenceNumber = sequenceNumber;
         }
 
         /**
          * Creates a one-shot action with given nanoTime-based trigger time.
          */
-        ScheduledFutureTask(Callable<V> callable, long ns) {
+        ScheduledFutureTask(Callable<V> callable, long triggerTime,
+                            long sequenceNumber) {
             super(callable);
-            this.time = ns;
+            this.time = triggerTime;
             this.period = 0;
-            this.sequenceNumber = sequencer.getAndIncrement();
+            this.sequenceNumber = sequenceNumber;
         }
 
         public long getDelay(TimeUnit unit) {
@@ -290,8 +301,8 @@
             if (!canRunInCurrentRunState(periodic))
                 cancel(false);
             else if (!periodic)
-                ScheduledFutureTask.super.run();
-            else if (ScheduledFutureTask.super.runAndReset()) {
+                super.run();
+            else if (super.runAndReset()) {
                 setNextRunTime();
                 reExecutePeriodic(outerTask);
             }
@@ -419,6 +430,22 @@
     }
 
     /**
+     * The default keep-alive time for pool threads.
+     *
+     * Normally, this value is unused because all pool threads will be
+     * core threads, but if a user creates a pool with a corePoolSize
+     * of zero (against our advice), we keep a thread alive as long as
+     * there are queued tasks.  If the keep alive time is zero (the
+     * historic value), we end up hot-spinning in getTask, wasting a
+     * CPU.  But on the other hand, if we set the value too high, and
+     * users create a one-shot pool which they don't cleanly shutdown,
+     * the pool's non-daemon threads will prevent JVM termination.  A
+     * small but non-zero value (relative to a JVM's lifetime) seems
+     * best.
+     */
+    private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
+
+    /**
      * Creates a new {@code ScheduledThreadPoolExecutor} with the
      * given core pool size.
      *
@@ -427,7 +454,8 @@
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      */
     public ScheduledThreadPoolExecutor(int corePoolSize) {
-        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+        super(corePoolSize, Integer.MAX_VALUE,
+              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
               new DelayedWorkQueue());
     }
 
@@ -444,13 +472,14 @@
      */
     public ScheduledThreadPoolExecutor(int corePoolSize,
                                        ThreadFactory threadFactory) {
-        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+        super(corePoolSize, Integer.MAX_VALUE,
+              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
               new DelayedWorkQueue(), threadFactory);
     }
 
     /**
-     * Creates a new ScheduledThreadPoolExecutor with the given
-     * initial parameters.
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given initial parameters.
      *
      * @param corePoolSize the number of threads to keep in the pool, even
      *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -461,13 +490,14 @@
      */
     public ScheduledThreadPoolExecutor(int corePoolSize,
                                        RejectedExecutionHandler handler) {
-        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+        super(corePoolSize, Integer.MAX_VALUE,
+              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
               new DelayedWorkQueue(), handler);
     }
 
     /**
-     * Creates a new ScheduledThreadPoolExecutor with the given
-     * initial parameters.
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given initial parameters.
      *
      * @param corePoolSize the number of threads to keep in the pool, even
      *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -482,19 +512,20 @@
     public ScheduledThreadPoolExecutor(int corePoolSize,
                                        ThreadFactory threadFactory,
                                        RejectedExecutionHandler handler) {
-        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+        super(corePoolSize, Integer.MAX_VALUE,
+              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
               new DelayedWorkQueue(), threadFactory, handler);
     }
 
     /**
-     * Returns the trigger time of a delayed action.
+     * Returns the nanoTime-based trigger time of a delayed action.
      */
     private long triggerTime(long delay, TimeUnit unit) {
         return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
     }
 
     /**
-     * Returns the trigger time of a delayed action.
+     * Returns the nanoTime-based trigger time of a delayed action.
      */
     long triggerTime(long delay) {
         return now() +
@@ -527,9 +558,10 @@
                                        TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        RunnableScheduledFuture<?> t = decorateTask(command,
+        RunnableScheduledFuture<Void> t = decorateTask(command,
             new ScheduledFutureTask<Void>(command, null,
-                                          triggerTime(delay, unit)));
+                                          triggerTime(delay, unit),
+                                          sequencer.getAndIncrement()));
         delayedExecute(t);
         return t;
     }
@@ -545,7 +577,8 @@
             throw new NullPointerException();
         RunnableScheduledFuture<V> t = decorateTask(callable,
             new ScheduledFutureTask<V>(callable,
-                                       triggerTime(delay, unit)));
+                                       triggerTime(delay, unit),
+                                       sequencer.getAndIncrement()));
         delayedExecute(t);
         return t;
     }
@@ -561,13 +594,14 @@
                                                   TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        if (period <= 0)
+        if (period <= 0L)
             throw new IllegalArgumentException();
         ScheduledFutureTask<Void> sft =
             new ScheduledFutureTask<Void>(command,
                                           null,
                                           triggerTime(initialDelay, unit),
-                                          unit.toNanos(period));
+                                          unit.toNanos(period),
+                                          sequencer.getAndIncrement());
         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
         sft.outerTask = t;
         delayedExecute(t);
@@ -585,13 +619,14 @@
                                                      TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        if (delay <= 0)
+        if (delay <= 0L)
             throw new IllegalArgumentException();
         ScheduledFutureTask<Void> sft =
             new ScheduledFutureTask<Void>(command,
                                           null,
                                           triggerTime(initialDelay, unit),
-                                          unit.toNanos(-delay));
+                                          -unit.toNanos(delay),
+                                          sequencer.getAndIncrement());
         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
         sft.outerTask = t;
         delayedExecute(t);
@@ -764,7 +799,8 @@
     /**
      * Attempts to stop all actively executing tasks, halts the
      * processing of waiting tasks, and returns a list of the tasks
-     * that were awaiting execution.
+     * that were awaiting execution. These tasks are drained (removed)
+     * from the task queue upon return from this method.
      *
      * <p>This method does not wait for actively executing tasks to
      * terminate.  Use {@link #awaitTermination awaitTermination} to
@@ -772,13 +808,15 @@
      *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  This implementation
-     * cancels tasks via {@link Thread#interrupt}, so any task that
+     * interrupts tasks via {@link Thread#interrupt}; any task that
      * fails to respond to interrupts may never terminate.
      *
      * @return list of tasks that never commenced execution.
-     *         Each element of this list is a {@link ScheduledFuture},
-     *         including those tasks submitted using {@code execute},
-     *         which are for scheduling purposes used as the basis of a
+     *         Each element of this list is a {@link ScheduledFuture}.
+     *         For tasks submitted via one of the {@code schedule}
+     *         methods, the element will be identical to the returned
+     *         {@code ScheduledFuture}.  For tasks submitted using
+     *         {@link #execute execute}, the element will be a
      *         zero-delay {@code ScheduledFuture}.
      * @throws SecurityException {@inheritDoc}
      */
@@ -787,13 +825,19 @@
     }
 
     /**
-     * Returns the task queue used by this executor.  Each element of
-     * this queue is a {@link ScheduledFuture}, including those
-     * tasks submitted using {@code execute} which are for scheduling
-     * purposes used as the basis of a zero-delay
-     * {@code ScheduledFuture}.  Iteration over this queue is
-     * <em>not</em> guaranteed to traverse tasks in the order in
-     * which they will execute.
+     * Returns the task queue used by this executor.  Access to the
+     * task queue is intended primarily for debugging and monitoring.
+     * This queue may be in active use.  Retrieving the task queue
+     * does not prevent queued tasks from executing.
+     *
+     * <p>Each element of this queue is a {@link ScheduledFuture}.
+     * For tasks submitted via one of the {@code schedule} methods, the
+     * element will be identical to the returned {@code ScheduledFuture}.
+     * For tasks submitted using {@link #execute execute}, the element
+     * will be a zero-delay {@code ScheduledFuture}.
+     *
+     * <p>Iteration over this queue is <em>not</em> guaranteed to traverse
+     * tasks in the order in which they will execute.
      *
      * @return the task queue
      */
@@ -836,7 +880,7 @@
         private RunnableScheduledFuture<?>[] queue =
             new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
         private final ReentrantLock lock = new ReentrantLock();
-        private int size = 0;
+        private int size;
 
         /**
          * Thread designated to wait for the task at the head of the
@@ -854,7 +898,7 @@
          * signalled.  So waiting threads must be prepared to acquire
          * and lose leadership while waiting.
          */
-        private Thread leader = null;
+        private Thread leader;
 
         /**
          * Condition signalled when a newer task becomes available at the
@@ -1062,10 +1106,9 @@
             lock.lock();
             try {
                 RunnableScheduledFuture<?> first = queue[0];
-                if (first == null || first.getDelay(NANOSECONDS) > 0)
-                    return null;
-                else
-                    return finishPoll(first);
+                return (first == null || first.getDelay(NANOSECONDS) > 0)
+                    ? null
+                    : finishPoll(first);
             } finally {
                 lock.unlock();
             }
@@ -1081,7 +1124,7 @@
                         available.await();
                     else {
                         long delay = first.getDelay(NANOSECONDS);
-                        if (delay <= 0)
+                        if (delay <= 0L)
                             return finishPoll(first);
                         first = null; // don't retain ref while waiting
                         if (leader != null)
@@ -1114,15 +1157,15 @@
                 for (;;) {
                     RunnableScheduledFuture<?> first = queue[0];
                     if (first == null) {
-                        if (nanos <= 0)
+                        if (nanos <= 0L)
                             return null;
                         else
                             nanos = available.awaitNanos(nanos);
                     } else {
                         long delay = first.getDelay(NANOSECONDS);
-                        if (delay <= 0)
+                        if (delay <= 0L)
                             return finishPoll(first);
-                        if (nanos <= 0)
+                        if (nanos <= 0L)
                             return null;
                         first = null; // don't retain ref while waiting
                         if (nanos < delay || leader != null)
@@ -1254,8 +1297,8 @@
          */
         private class Itr implements Iterator<Runnable> {
             final RunnableScheduledFuture<?>[] array;
-            int cursor = 0;     // index of next element to return
-            int lastRet = -1;   // index of last element, or -1 if no such
+            int cursor;        // index of next element to return; initially 0
+            int lastRet = -1;  // index of last element returned; -1 if no such
 
             Itr(RunnableScheduledFuture<?>[] array) {
                 this.array = array;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent;
+
 import java.util.Collection;
 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
 
@@ -48,7 +49,7 @@
  * <p>Semaphores are often used to restrict the number of threads than can
  * access some (physical or logical) resource. For example, here is
  * a class that uses a semaphore to control access to a pool of items:
- *  <pre> {@code
+ * <pre> {@code
  * class Pool {
  *   private static final int MAX_AVAILABLE = 100;
  *   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
@@ -114,7 +115,7 @@
  * ownership).  This can be useful in some specialized contexts, such
  * as deadlock recovery.
  *
- * <p> The constructor for this class optionally accepts a
+ * <p>The constructor for this class optionally accepts a
  * <em>fairness</em> parameter. When set false, this class makes no
  * guarantees about the order in which threads acquire permits. In
  * particular, <em>barging</em> is permitted, that is, a thread
@@ -141,8 +142,13 @@
  *
  * <p>This class also provides convenience methods to {@link
  * #acquire(int) acquire} and {@link #release(int) release} multiple
- * permits at a time.  Beware of the increased risk of indefinite
- * postponement when these methods are used without fairness set true.
+ * permits at a time. These methods are generally more efficient and
+ * effective than loops. However, they do not establish any preference
+ * order. For example, if thread A invokes {@code s.acquire(3}) and
+ * thread B invokes {@code s.acquire(2)}, and two permits become
+ * available, then there is no guarantee that thread B will obtain
+ * them unless its acquire came first and Semaphore {@code s} is in
+ * fair mode.
  *
  * <p>Memory consistency effects: Actions in a thread prior to calling
  * a "release" method such as {@code release()}
@@ -433,14 +439,16 @@
      *
      * <p>Acquires the given number of permits, if they are available,
      * and returns immediately, reducing the number of available permits
-     * by the given amount.
+     * by the given amount. This method has the same effect as the
+     * loop {@code for (int i = 0; i < permits; ++i) acquire();} except
+     * that it atomically acquires the permits all at once:
      *
      * <p>If insufficient permits are available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
      * one of two things happens:
      * <ul>
      * <li>Some other thread invokes one of the {@link #release() release}
-     * methods for this semaphore, the current thread is next to be assigned
+     * methods for this semaphore and the current thread is next to be assigned
      * permits and the number of available permits satisfies this request; or
      * <li>Some other thread {@linkplain Thread#interrupt interrupts}
      * the current thread.
@@ -473,12 +481,14 @@
      *
      * <p>Acquires the given number of permits, if they are available,
      * and returns immediately, reducing the number of available permits
-     * by the given amount.
+     * by the given amount. This method has the same effect as the
+     * loop {@code for (int i = 0; i < permits; ++i) acquireUninterruptibly();}
+     * except that it atomically acquires the permits all at once:
      *
      * <p>If insufficient permits are available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
      * some other thread invokes one of the {@link #release() release}
-     * methods for this semaphore, the current thread is next to be assigned
+     * methods for this semaphore and the current thread is next to be assigned
      * permits and the number of available permits satisfies this request.
      *
      * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
@@ -540,7 +550,7 @@
      * purposes and lies dormant until one of three things happens:
      * <ul>
      * <li>Some other thread invokes one of the {@link #release() release}
-     * methods for this semaphore, the current thread is next to be assigned
+     * methods for this semaphore and the current thread is next to be assigned
      * permits and the number of available permits satisfies this request; or
      * <li>Some other thread {@linkplain Thread#interrupt interrupts}
      * the current thread; or
@@ -587,7 +597,7 @@
      *
      * <p>Releases the given number of permits, increasing the number of
      * available permits by that amount.
-     * If any threads are trying to acquire permits, then one
+     * If any threads are trying to acquire permits, then one thread
      * is selected and given the permits that were just released.
      * If the number of available permits satisfies that thread's request
      * then that thread is (re)enabled for thread scheduling purposes;
@@ -671,7 +681,7 @@
      * Returns an estimate of the number of threads waiting to acquire.
      * The value is only an estimate because the number of threads may
      * change dynamically while this method traverses internal data
-     * structures.  This method is designed for use in monitoring of the
+     * structures.  This method is designed for use in monitoring
      * system state, not for synchronization control.
      *
      * @return the estimated number of threads waiting for this lock
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,1632 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.locks.LockSupport;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+/**
+ * A {@link Flow.Publisher} that asynchronously issues submitted
+ * (non-null) items to current subscribers until it is closed.  Each
+ * current subscriber receives newly submitted items in the same order
+ * unless drops or exceptions are encountered.  Using a
+ * SubmissionPublisher allows item generators to act as compliant <a
+ * href="http://www.reactive-streams.org/"> reactive-streams</a>
+ * Publishers relying on drop handling and/or blocking for flow
+ * control.
+ *
+ * <p>A SubmissionPublisher uses the {@link Executor} supplied in its
+ * constructor for delivery to subscribers. The best choice of
+ * Executor depends on expected usage. If the generator(s) of
+ * submitted items run in separate threads, and the number of
+ * subscribers can be estimated, consider using a {@link
+ * Executors#newFixedThreadPool}. Otherwise consider using the
+ * default, normally the {@link ForkJoinPool#commonPool}.
+ *
+ * <p>Buffering allows producers and consumers to transiently operate
+ * at different rates.  Each subscriber uses an independent buffer.
+ * Buffers are created upon first use and expanded as needed up to the
+ * given maximum. (The enforced capacity may be rounded up to the
+ * nearest power of two and/or bounded by the largest value supported
+ * by this implementation.)  Invocations of {@link
+ * Flow.Subscription#request(long) request} do not directly result in
+ * buffer expansion, but risk saturation if unfilled requests exceed
+ * the maximum capacity.  The default value of {@link
+ * Flow#defaultBufferSize()} may provide a useful starting point for
+ * choosing a capacity based on expected rates, resources, and usages.
+ *
+ * <p>Publication methods support different policies about what to do
+ * when buffers are saturated. Method {@link #submit(Object) submit}
+ * blocks until resources are available. This is simplest, but least
+ * responsive.  The {@code offer} methods may drop items (either
+ * immediately or with bounded timeout), but provide an opportunity to
+ * interpose a handler and then retry.
+ *
+ * <p>If any Subscriber method throws an exception, its subscription
+ * is cancelled.  If a handler is supplied as a constructor argument,
+ * it is invoked before cancellation upon an exception in method
+ * {@link Flow.Subscriber#onNext onNext}, but exceptions in methods
+ * {@link Flow.Subscriber#onSubscribe onSubscribe},
+ * {@link Flow.Subscriber#onError(Throwable) onError} and
+ * {@link Flow.Subscriber#onComplete() onComplete} are not recorded or
+ * handled before cancellation.  If the supplied Executor throws
+ * {@link RejectedExecutionException} (or any other RuntimeException
+ * or Error) when attempting to execute a task, or a drop handler
+ * throws an exception when processing a dropped item, then the
+ * exception is rethrown. In these cases, not all subscribers will
+ * have been issued the published item. It is usually good practice to
+ * {@link #closeExceptionally closeExceptionally} in these cases.
+ *
+ * <p>Method {@link #consume(Consumer)} simplifies support for a
+ * common case in which the only action of a subscriber is to request
+ * and process all items using a supplied function.
+ *
+ * <p>This class may also serve as a convenient base for subclasses
+ * that generate items, and use the methods in this class to publish
+ * them.  For example here is a class that periodically publishes the
+ * items generated from a supplier. (In practice you might add methods
+ * to independently start and stop generation, to share Executors
+ * among publishers, and so on, or use a SubmissionPublisher as a
+ * component rather than a superclass.)
+ *
+ * <pre> {@code
+ * class PeriodicPublisher<T> extends SubmissionPublisher<T> {
+ *   final ScheduledFuture<?> periodicTask;
+ *   final ScheduledExecutorService scheduler;
+ *   PeriodicPublisher(Executor executor, int maxBufferCapacity,
+ *                     Supplier<? extends T> supplier,
+ *                     long period, TimeUnit unit) {
+ *     super(executor, maxBufferCapacity);
+ *     scheduler = new ScheduledThreadPoolExecutor(1);
+ *     periodicTask = scheduler.scheduleAtFixedRate(
+ *       () -> submit(supplier.get()), 0, period, unit);
+ *   }
+ *   public void close() {
+ *     periodicTask.cancel(false);
+ *     scheduler.shutdown();
+ *     super.close();
+ *   }
+ * }}</pre>
+ *
+ * <p>Here is an example of a {@link Flow.Processor} implementation.
+ * It uses single-step requests to its publisher for simplicity of
+ * illustration. A more adaptive version could monitor flow using the
+ * lag estimate returned from {@code submit}, along with other utility
+ * methods.
+ *
+ * <pre> {@code
+ * class TransformProcessor<S,T> extends SubmissionPublisher<T>
+ *   implements Flow.Processor<S,T> {
+ *   final Function<? super S, ? extends T> function;
+ *   Flow.Subscription subscription;
+ *   TransformProcessor(Executor executor, int maxBufferCapacity,
+ *                      Function<? super S, ? extends T> function) {
+ *     super(executor, maxBufferCapacity);
+ *     this.function = function;
+ *   }
+ *   public void onSubscribe(Flow.Subscription subscription) {
+ *     (this.subscription = subscription).request(1);
+ *   }
+ *   public void onNext(S item) {
+ *     subscription.request(1);
+ *     submit(function.apply(item));
+ *   }
+ *   public void onError(Throwable ex) { closeExceptionally(ex); }
+ *   public void onComplete() { close(); }
+ * }}</pre>
+ *
+ * @param <T> the published item type
+ * @author Doug Lea
+ * @since 1.9
+ */
+public class SubmissionPublisher<T> implements Flow.Publisher<T>,
+                                               AutoCloseable {
+    /*
+     * Most mechanics are handled by BufferedSubscription. This class
+     * mainly tracks subscribers and ensures sequentiality, by using
+     * built-in synchronization locks across public methods. (Using
+     * built-in locks works well in the most typical case in which
+     * only one thread submits items).
+     */
+
+    /** The largest possible power of two array size. */
+    static final int BUFFER_CAPACITY_LIMIT = 1 << 30;
+
+    /** Round capacity to power of 2, at most limit. */
+    static final int roundCapacity(int cap) {
+        int n = cap - 1;
+        n |= n >>> 1;
+        n |= n >>> 2;
+        n |= n >>> 4;
+        n |= n >>> 8;
+        n |= n >>> 16;
+        return (n <= 0) ? 1 : // at least 1
+            (n >= BUFFER_CAPACITY_LIMIT) ? BUFFER_CAPACITY_LIMIT : n + 1;
+    }
+
+    // default Executor setup; nearly the same as CompletableFuture
+
+    /**
+     * Default executor -- ForkJoinPool.commonPool() unless it cannot
+     * support parallelism.
+     */
+    private static final Executor ASYNC_POOL =
+        (ForkJoinPool.getCommonPoolParallelism() > 1) ?
+        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
+
+    /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
+    private static final class ThreadPerTaskExecutor implements Executor {
+        public void execute(Runnable r) { new Thread(r).start(); }
+    }
+
+    /**
+     * Clients (BufferedSubscriptions) are maintained in a linked list
+     * (via their "next" fields). This works well for publish loops.
+     * It requires O(n) traversal to check for duplicate subscribers,
+     * but we expect that subscribing is much less common than
+     * publishing. Unsubscribing occurs only during traversal loops,
+     * when BufferedSubscription methods return negative values
+     * signifying that they have been disabled.  To reduce
+     * head-of-line blocking, submit and offer methods first call
+     * BufferedSubscription.offer on each subscriber, and place
+     * saturated ones in retries list (using nextRetry field), and
+     * retry, possibly blocking or dropping.
+     */
+    BufferedSubscription<T> clients;
+
+    /** Run status, updated only within locks */
+    volatile boolean closed;
+    /** If non-null, the exception in closeExceptionally */
+    volatile Throwable closedException;
+
+    // Parameters for constructing BufferedSubscriptions
+    final Executor executor;
+    final BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
+    final int maxBufferCapacity;
+
+    /**
+     * Creates a new SubmissionPublisher using the given Executor for
+     * async delivery to subscribers, with the given maximum buffer size
+     * for each subscriber, and, if non-null, the given handler invoked
+     * when any Subscriber throws an exception in method {@link
+     * Flow.Subscriber#onNext(Object) onNext}.
+     *
+     * @param executor the executor to use for async delivery,
+     * supporting creation of at least one independent thread
+     * @param maxBufferCapacity the maximum capacity for each
+     * subscriber's buffer (the enforced capacity may be rounded up to
+     * the nearest power of two and/or bounded by the largest value
+     * supported by this implementation; method {@link #getMaxBufferCapacity}
+     * returns the actual value)
+     * @param handler if non-null, procedure to invoke upon exception
+     * thrown in method {@code onNext}
+     * @throws NullPointerException if executor is null
+     * @throws IllegalArgumentException if maxBufferCapacity not
+     * positive
+     */
+    public SubmissionPublisher(Executor executor, int maxBufferCapacity,
+                               BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> handler) {
+        if (executor == null)
+            throw new NullPointerException();
+        if (maxBufferCapacity <= 0)
+            throw new IllegalArgumentException("capacity must be positive");
+        this.executor = executor;
+        this.onNextHandler = handler;
+        this.maxBufferCapacity = roundCapacity(maxBufferCapacity);
+    }
+
+    /**
+     * Creates a new SubmissionPublisher using the given Executor for
+     * async delivery to subscribers, with the given maximum buffer size
+     * for each subscriber, and no handler for Subscriber exceptions in
+     * method {@link Flow.Subscriber#onNext(Object) onNext}.
+     *
+     * @param executor the executor to use for async delivery,
+     * supporting creation of at least one independent thread
+     * @param maxBufferCapacity the maximum capacity for each
+     * subscriber's buffer (the enforced capacity may be rounded up to
+     * the nearest power of two and/or bounded by the largest value
+     * supported by this implementation; method {@link #getMaxBufferCapacity}
+     * returns the actual value)
+     * @throws NullPointerException if executor is null
+     * @throws IllegalArgumentException if maxBufferCapacity not
+     * positive
+     */
+    public SubmissionPublisher(Executor executor, int maxBufferCapacity) {
+        this(executor, maxBufferCapacity, null);
+    }
+
+    /**
+     * Creates a new SubmissionPublisher using the {@link
+     * ForkJoinPool#commonPool()} for async delivery to subscribers
+     * (unless it does not support a parallelism level of at least two,
+     * in which case, a new Thread is created to run each task), with
+     * maximum buffer capacity of {@link Flow#defaultBufferSize}, and no
+     * handler for Subscriber exceptions in method {@link
+     * Flow.Subscriber#onNext(Object) onNext}.
+     */
+    public SubmissionPublisher() {
+        this(ASYNC_POOL, Flow.defaultBufferSize(), null);
+    }
+
+    /**
+     * Adds the given Subscriber unless already subscribed.  If already
+     * subscribed, the Subscriber's {@link
+     * Flow.Subscriber#onError(Throwable) onError} method is invoked on
+     * the existing subscription with an {@link IllegalStateException}.
+     * Otherwise, upon success, the Subscriber's {@link
+     * Flow.Subscriber#onSubscribe onSubscribe} method is invoked
+     * asynchronously with a new {@link Flow.Subscription}.  If {@link
+     * Flow.Subscriber#onSubscribe onSubscribe} throws an exception, the
+     * subscription is cancelled. Otherwise, if this SubmissionPublisher
+     * was closed exceptionally, then the subscriber's {@link
+     * Flow.Subscriber#onError onError} method is invoked with the
+     * corresponding exception, or if closed without exception, the
+     * subscriber's {@link Flow.Subscriber#onComplete() onComplete}
+     * method is invoked.  Subscribers may enable receiving items by
+     * invoking the {@link Flow.Subscription#request(long) request}
+     * method of the new Subscription, and may unsubscribe by invoking
+     * its {@link Flow.Subscription#cancel() cancel} method.
+     *
+     * @param subscriber the subscriber
+     * @throws NullPointerException if subscriber is null
+     */
+    public void subscribe(Flow.Subscriber<? super T> subscriber) {
+        if (subscriber == null) throw new NullPointerException();
+        BufferedSubscription<T> subscription =
+            new BufferedSubscription<T>(subscriber, executor,
+                                        onNextHandler, maxBufferCapacity);
+        synchronized (this) {
+            for (BufferedSubscription<T> b = clients, pred = null;;) {
+                if (b == null) {
+                    Throwable ex;
+                    subscription.onSubscribe();
+                    if ((ex = closedException) != null)
+                        subscription.onError(ex);
+                    else if (closed)
+                        subscription.onComplete();
+                    else if (pred == null)
+                        clients = subscription;
+                    else
+                        pred.next = subscription;
+                    break;
+                }
+                BufferedSubscription<T> next = b.next;
+                if (b.isDisabled()) { // remove
+                    b.next = null;    // detach
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else if (subscriber.equals(b.subscriber)) {
+                    b.onError(new IllegalStateException("Duplicate subscribe"));
+                    break;
+                }
+                else
+                    pred = b;
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Publishes the given item to each current subscriber by
+     * asynchronously invoking its {@link Flow.Subscriber#onNext(Object)
+     * onNext} method, blocking uninterruptibly while resources for any
+     * subscriber are unavailable. This method returns an estimate of
+     * the maximum lag (number of items submitted but not yet consumed)
+     * among all current subscribers. This value is at least one
+     * (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers,
+     * then this exception is rethrown, in which case not all
+     * subscribers will have been issued this item.
+     *
+     * @param item the (non-null) item to publish
+     * @return the estimated maximum lag among subscribers
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int submit(T item) {
+        if (item == null) throw new NullPointerException();
+        int lag = 0;
+        boolean complete;
+        synchronized (this) {
+            complete = closed;
+            BufferedSubscription<T> b = clients;
+            if (!complete) {
+                BufferedSubscription<T> pred = null, r = null, rtail = null;
+                while (b != null) {
+                    BufferedSubscription<T> next = b.next;
+                    int stat = b.offer(item);
+                    if (stat < 0) {           // disabled
+                        b.next = null;
+                        if (pred == null)
+                            clients = next;
+                        else
+                            pred.next = next;
+                    }
+                    else {
+                        if (stat > lag)
+                            lag = stat;
+                        else if (stat == 0) { // place on retry list
+                            b.nextRetry = null;
+                            if (rtail == null)
+                                r = b;
+                            else
+                                rtail.nextRetry = b;
+                            rtail = b;
+                        }
+                        pred = b;
+                    }
+                    b = next;
+                }
+                while (r != null) {
+                    BufferedSubscription<T> nextRetry = r.nextRetry;
+                    r.nextRetry = null;
+                    int stat = r.submit(item);
+                    if (stat > lag)
+                        lag = stat;
+                    else if (stat < 0 && clients == r)
+                        clients = r.next; // postpone internal unsubscribes
+                    r = nextRetry;
+                }
+            }
+        }
+        if (complete)
+            throw new IllegalStateException("Closed");
+        else
+            return lag;
+    }
+
+    /**
+     * Publishes the given item, if possible, to each current subscriber
+     * by asynchronously invoking its {@link
+     * Flow.Subscriber#onNext(Object) onNext} method. The item may be
+     * dropped by one or more subscribers if resource limits are
+     * exceeded, in which case the given handler (if non-null) is
+     * invoked, and if it returns true, retried once.  Other calls to
+     * methods in this class by other threads are blocked while the
+     * handler is invoked.  Unless recovery is assured, options are
+     * usually limited to logging the error and/or issuing an {@link
+     * Flow.Subscriber#onError(Throwable) onError} signal to the
+     * subscriber.
+     *
+     * <p>This method returns a status indicator: If negative, it
+     * represents the (negative) number of drops (failed attempts to
+     * issue the item to a subscriber). Otherwise it is an estimate of
+     * the maximum lag (number of items submitted but not yet
+     * consumed) among all current subscribers. This value is at least
+     * one (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers, or
+     * the drop handler throws an exception when processing a dropped
+     * item, then this exception is rethrown.
+     *
+     * @param item the (non-null) item to publish
+     * @param onDrop if non-null, the handler invoked upon a drop to a
+     * subscriber, with arguments of the subscriber and item; if it
+     * returns true, an offer is re-attempted (once)
+     * @return if negative, the (negative) number of drops; otherwise
+     * an estimate of maximum lag
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int offer(T item,
+                     BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+        return doOffer(0L, item, onDrop);
+    }
+
+    /**
+     * Publishes the given item, if possible, to each current subscriber
+     * by asynchronously invoking its {@link
+     * Flow.Subscriber#onNext(Object) onNext} method, blocking while
+     * resources for any subscription are unavailable, up to the
+     * specified timeout or until the caller thread is interrupted, at
+     * which point the given handler (if non-null) is invoked, and if it
+     * returns true, retried once. (The drop handler may distinguish
+     * timeouts from interrupts by checking whether the current thread
+     * is interrupted.)  Other calls to methods in this class by other
+     * threads are blocked while the handler is invoked.  Unless
+     * recovery is assured, options are usually limited to logging the
+     * error and/or issuing an {@link Flow.Subscriber#onError(Throwable)
+     * onError} signal to the subscriber.
+     *
+     * <p>This method returns a status indicator: If negative, it
+     * represents the (negative) number of drops (failed attempts to
+     * issue the item to a subscriber). Otherwise it is an estimate of
+     * the maximum lag (number of items submitted but not yet
+     * consumed) among all current subscribers. This value is at least
+     * one (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers, or
+     * the drop handler throws an exception when processing a dropped
+     * item, then this exception is rethrown.
+     *
+     * @param item the (non-null) item to publish
+     * @param timeout how long to wait for resources for any subscriber
+     * before giving up, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     * {@code timeout} parameter
+     * @param onDrop if non-null, the handler invoked upon a drop to a
+     * subscriber, with arguments of the subscriber and item; if it
+     * returns true, an offer is re-attempted (once)
+     * @return if negative, the (negative) number of drops; otherwise
+     * an estimate of maximum lag
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int offer(T item, long timeout, TimeUnit unit,
+                     BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+        return doOffer(unit.toNanos(timeout), item, onDrop);
+    }
+
+    /** Common implementation for both forms of offer */
+    final int doOffer(long nanos, T item,
+                      BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+        if (item == null) throw new NullPointerException();
+        int lag = 0, drops = 0;
+        boolean complete;
+        synchronized (this) {
+            complete = closed;
+            BufferedSubscription<T> b = clients;
+            if (!complete) {
+                BufferedSubscription<T> pred = null, r = null, rtail = null;
+                while (b != null) {
+                    BufferedSubscription<T> next = b.next;
+                    int stat = b.offer(item);
+                    if (stat < 0) {
+                        b.next = null;
+                        if (pred == null)
+                            clients = next;
+                        else
+                            pred.next = next;
+                    }
+                    else {
+                        if (stat > lag)
+                            lag = stat;
+                        else if (stat == 0) {
+                            b.nextRetry = null;
+                            if (rtail == null)
+                                r = b;
+                            else
+                                rtail.nextRetry = b;
+                            rtail = b;
+                        }
+                        else if (stat > lag)
+                            lag = stat;
+                        pred = b;
+                    }
+                    b = next;
+                }
+                while (r != null) {
+                    BufferedSubscription<T> nextRetry = r.nextRetry;
+                    r.nextRetry = null;
+                    int stat = (nanos > 0L) ? r.timedOffer(item, nanos) :
+                        r.offer(item);
+                    if (stat == 0 && onDrop != null &&
+                        onDrop.test(r.subscriber, item))
+                        stat = r.offer(item);
+                    if (stat == 0)
+                        ++drops;
+                    else if (stat > lag)
+                        lag = stat;
+                    else if (stat < 0 && clients == r)
+                        clients = r.next;
+                    r = nextRetry;
+                }
+            }
+        }
+        if (complete)
+            throw new IllegalStateException("Closed");
+        else
+            return (drops > 0) ? -drops : lag;
+    }
+
+    /**
+     * Unless already closed, issues {@link
+     * Flow.Subscriber#onComplete() onComplete} signals to current
+     * subscribers, and disallows subsequent attempts to publish.
+     * Upon return, this method does <em>NOT</em> guarantee that all
+     * subscribers have yet completed.
+     */
+    public void close() {
+        if (!closed) {
+            BufferedSubscription<T> b;
+            synchronized (this) {
+                b = clients;
+                clients = null;
+                closed = true;
+            }
+            while (b != null) {
+                BufferedSubscription<T> next = b.next;
+                b.next = null;
+                b.onComplete();
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Unless already closed, issues {@link
+     * Flow.Subscriber#onError(Throwable) onError} signals to current
+     * subscribers with the given error, and disallows subsequent
+     * attempts to publish.  Future subscribers also receive the given
+     * error. Upon return, this method does <em>NOT</em> guarantee
+     * that all subscribers have yet completed.
+     *
+     * @param error the {@code onError} argument sent to subscribers
+     * @throws NullPointerException if error is null
+     */
+    public void closeExceptionally(Throwable error) {
+        if (error == null)
+            throw new NullPointerException();
+        if (!closed) {
+            BufferedSubscription<T> b;
+            synchronized (this) {
+                b = clients;
+                clients = null;
+                closed = true;
+                closedException = error;
+            }
+            while (b != null) {
+                BufferedSubscription<T> next = b.next;
+                b.next = null;
+                b.onError(error);
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Returns true if this publisher is not accepting submissions.
+     *
+     * @return true if closed
+     */
+    public boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * Returns the exception associated with {@link
+     * #closeExceptionally(Throwable) closeExceptionally}, or null if
+     * not closed or if closed normally.
+     *
+     * @return the exception, or null if none
+     */
+    public Throwable getClosedException() {
+        return closedException;
+    }
+
+    /**
+     * Returns true if this publisher has any subscribers.
+     *
+     * @return true if this publisher has any subscribers
+     */
+    public boolean hasSubscribers() {
+        boolean nonEmpty = false;
+        if (!closed) {
+            synchronized (this) {
+                for (BufferedSubscription<T> b = clients; b != null;) {
+                    BufferedSubscription<T> next = b.next;
+                    if (b.isDisabled()) {
+                        b.next = null;
+                        b = clients = next;
+                    }
+                    else {
+                        nonEmpty = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return nonEmpty;
+    }
+
+    /**
+     * Returns the number of current subscribers.
+     *
+     * @return the number of current subscribers
+     */
+    public int getNumberOfSubscribers() {
+        int count = 0;
+        if (!closed) {
+            synchronized (this) {
+                BufferedSubscription<T> pred = null, next;
+                for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                    next = b.next;
+                    if (b.isDisabled()) {
+                        b.next = null;
+                        if (pred == null)
+                            clients = next;
+                        else
+                            pred.next = next;
+                    }
+                    else {
+                        pred = b;
+                        ++count;
+                    }
+                }
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Returns the Executor used for asynchronous delivery.
+     *
+     * @return the Executor used for asynchronous delivery
+     */
+    public Executor getExecutor() {
+        return executor;
+    }
+
+    /**
+     * Returns the maximum per-subscriber buffer capacity.
+     *
+     * @return the maximum per-subscriber buffer capacity
+     */
+    public int getMaxBufferCapacity() {
+        return maxBufferCapacity;
+    }
+
+    /**
+     * Returns a list of current subscribers for monitoring and
+     * tracking purposes, not for invoking {@link Flow.Subscriber}
+     * methods on the subscribers.
+     *
+     * @return list of current subscribers
+     */
+    public List<Flow.Subscriber<? super T>> getSubscribers() {
+        ArrayList<Flow.Subscriber<? super T>> subs = new ArrayList<>();
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                next = b.next;
+                if (b.isDisabled()) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else
+                    subs.add(b.subscriber);
+            }
+        }
+        return subs;
+    }
+
+    /**
+     * Returns true if the given Subscriber is currently subscribed.
+     *
+     * @param subscriber the subscriber
+     * @return true if currently subscribed
+     * @throws NullPointerException if subscriber is null
+     */
+    public boolean isSubscribed(Flow.Subscriber<? super T> subscriber) {
+        if (subscriber == null) throw new NullPointerException();
+        if (!closed) {
+            synchronized (this) {
+                BufferedSubscription<T> pred = null, next;
+                for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                    next = b.next;
+                    if (b.isDisabled()) {
+                        b.next = null;
+                        if (pred == null)
+                            clients = next;
+                        else
+                            pred.next = next;
+                    }
+                    else if (subscriber.equals(b.subscriber))
+                        return true;
+                    else
+                        pred = b;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns an estimate of the minimum number of items requested
+     * (via {@link Flow.Subscription#request(long) request}) but not
+     * yet produced, among all current subscribers.
+     *
+     * @return the estimate, or zero if no subscribers
+     */
+    public long estimateMinimumDemand() {
+        long min = Long.MAX_VALUE;
+        boolean nonEmpty = false;
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                int n; long d;
+                next = b.next;
+                if ((n = b.estimateLag()) < 0) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else {
+                    if ((d = b.demand - n) < min)
+                        min = d;
+                    nonEmpty = true;
+                    pred = b;
+                }
+            }
+        }
+        return nonEmpty ? min : 0;
+    }
+
+    /**
+     * Returns an estimate of the maximum number of items produced but
+     * not yet consumed among all current subscribers.
+     *
+     * @return the estimate
+     */
+    public int estimateMaximumLag() {
+        int max = 0;
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                int n;
+                next = b.next;
+                if ((n = b.estimateLag()) < 0) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else {
+                    if (n > max)
+                        max = n;
+                    pred = b;
+                }
+            }
+        }
+        return max;
+    }
+
+    /**
+     * Processes all published items using the given Consumer function.
+     * Returns a CompletableFuture that is completed normally when this
+     * publisher signals {@link Flow.Subscriber#onComplete()
+     * onComplete}, or completed exceptionally upon any error, or an
+     * exception is thrown by the Consumer, or the returned
+     * CompletableFuture is cancelled, in which case no further items
+     * are processed.
+     *
+     * @param consumer the function applied to each onNext item
+     * @return a CompletableFuture that is completed normally
+     * when the publisher signals onComplete, and exceptionally
+     * upon any error or cancellation
+     * @throws NullPointerException if consumer is null
+     */
+    public CompletableFuture<Void> consume(Consumer<? super T> consumer) {
+        if (consumer == null)
+            throw new NullPointerException();
+        CompletableFuture<Void> status = new CompletableFuture<>();
+        subscribe(new ConsumerSubscriber<T>(status, consumer));
+        return status;
+    }
+
+    /** Subscriber for method consume */
+    private static final class ConsumerSubscriber<T>
+            implements Flow.Subscriber<T> {
+        final CompletableFuture<Void> status;
+        final Consumer<? super T> consumer;
+        Flow.Subscription subscription;
+        ConsumerSubscriber(CompletableFuture<Void> status,
+                           Consumer<? super T> consumer) {
+            this.status = status; this.consumer = consumer;
+        }
+        public final void onSubscribe(Flow.Subscription subscription) {
+            this.subscription = subscription;
+            status.whenComplete((v, e) -> subscription.cancel());
+            if (!status.isDone())
+                subscription.request(Long.MAX_VALUE);
+        }
+        public final void onError(Throwable ex) {
+            status.completeExceptionally(ex);
+        }
+        public final void onComplete() {
+            status.complete(null);
+        }
+        public final void onNext(T item) {
+            try {
+                consumer.accept(item);
+            } catch (Throwable ex) {
+                subscription.cancel();
+                status.completeExceptionally(ex);
+            }
+        }
+    }
+
+    /**
+     * A task for consuming buffer items and signals, created and
+     * executed whenever they become available. A task consumes as
+     * many items/signals as possible before terminating, at which
+     * point another task is created when needed. The dual Runnable
+     * and ForkJoinTask declaration saves overhead when executed by
+     * ForkJoinPools, without impacting other kinds of Executors.
+     */
+    @SuppressWarnings("serial")
+    static final class ConsumerTask<T> extends ForkJoinTask<Void>
+        implements Runnable {
+        final BufferedSubscription<T> consumer;
+        ConsumerTask(BufferedSubscription<T> consumer) {
+            this.consumer = consumer;
+        }
+        public final Void getRawResult() { return null; }
+        public final void setRawResult(Void v) {}
+        public final boolean exec() { consumer.consume(); return false; }
+        public final void run() { consumer.consume(); }
+    }
+
+    /**
+     * A bounded (ring) buffer with integrated control to start a
+     * consumer task whenever items are available.  The buffer
+     * algorithm is similar to one used inside ForkJoinPool (see its
+     * internal documentation for details) specialized for the case of
+     * at most one concurrent producer and consumer, and power of two
+     * buffer sizes. This allows methods to operate without locks even
+     * while supporting resizing, blocking, task-triggering, and
+     * garbage-free buffers (nulling out elements when consumed),
+     * although supporting these does impose a bit of overhead
+     * compared to plain fixed-size ring buffers.
+     *
+     * The publisher guarantees a single producer via its lock.  We
+     * ensure in this class that there is at most one consumer.  The
+     * request and cancel methods must be fully thread-safe but are
+     * coded to exploit the most common case in which they are only
+     * called by consumers (usually within onNext).
+     *
+     * Execution control is managed using the ACTIVE ctl bit. We
+     * ensure that a task is active when consumable items (and
+     * usually, SUBSCRIBE, ERROR or COMPLETE signals) are present and
+     * there is demand (unfilled requests).  This is complicated on
+     * the creation side by the possibility of exceptions when trying
+     * to execute tasks. These eventually force DISABLED state, but
+     * sometimes not directly. On the task side, termination (clearing
+     * ACTIVE) that would otherwise race with producers or request()
+     * calls uses the CONSUME keep-alive bit to force a recheck.
+     *
+     * The ctl field also manages run state. When DISABLED, no further
+     * updates are possible. Disabling may be preceded by setting
+     * ERROR or COMPLETE (or both -- ERROR has precedence), in which
+     * case the associated Subscriber methods are invoked, possibly
+     * synchronously if there is no active consumer task (including
+     * cases where execute() failed). The cancel() method is supported
+     * by treating as ERROR but suppressing onError signal.
+     *
+     * Support for blocking also exploits the fact that there is only
+     * one possible waiter. ManagedBlocker-compatible control fields
+     * are placed in this class itself rather than in wait-nodes.
+     * Blocking control relies on the "waiter" field. Producers set
+     * the field before trying to block, but must then recheck (via
+     * offer) before parking. Signalling then just unparks and clears
+     * waiter field. If the producer and consumer are both in the same
+     * ForkJoinPool, or consumers are running in commonPool, the
+     * producer attempts to help run consumer tasks that it forked
+     * before blocking.  To avoid potential cycles, only one level of
+     * helping is currently supported.
+     *
+     * This class uses @Contended and heuristic field declaration
+     * ordering to reduce false-sharing-based memory contention among
+     * instances of BufferedSubscription, but it does not currently
+     * attempt to avoid memory contention among buffers. This field
+     * and element packing can hurt performance especially when each
+     * publisher has only one client operating at a high rate.
+     * Addressing this may require allocating substantially more space
+     * than users expect.
+     */
+    @SuppressWarnings("serial")
+    @sun.misc.Contended
+    private static final class BufferedSubscription<T>
+        implements Flow.Subscription, ForkJoinPool.ManagedBlocker {
+        // Order-sensitive field declarations
+        long timeout;                      // > 0 if timed wait
+        volatile long demand;              // # unfilled requests
+        int maxCapacity;                   // reduced on OOME
+        int putStat;                       // offer result for ManagedBlocker
+        int helpDepth;                     // nested helping depth (at most 1)
+        volatile int ctl;                  // atomic run state flags
+        volatile int head;                 // next position to take
+        int tail;                          // next position to put
+        Object[] array;                    // buffer: null if disabled
+        Flow.Subscriber<? super T> subscriber; // null if disabled
+        Executor executor;                 // null if disabled
+        BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
+        volatile Throwable pendingError;   // holds until onError issued
+        volatile Thread waiter;            // blocked producer thread
+        T putItem;                         // for offer within ManagedBlocker
+        BufferedSubscription<T> next;      // used only by publisher
+        BufferedSubscription<T> nextRetry; // used only by publisher
+
+        // ctl values
+        static final int ACTIVE    = 0x01; // consumer task active
+        static final int CONSUME   = 0x02; // keep-alive for consumer task
+        static final int DISABLED  = 0x04; // final state
+        static final int ERROR     = 0x08; // signal onError then disable
+        static final int SUBSCRIBE = 0x10; // signal onSubscribe
+        static final int COMPLETE  = 0x20; // signal onComplete when done
+
+        static final long INTERRUPTED = -1L; // timeout vs interrupt sentinel
+
+        /**
+         * Initial buffer capacity used when maxBufferCapacity is
+         * greater. Must be a power of two.
+         */
+        static final int DEFAULT_INITIAL_CAP = 32;
+
+        BufferedSubscription(Flow.Subscriber<? super T> subscriber,
+                             Executor executor,
+                             BiConsumer<? super Flow.Subscriber<? super T>,
+                             ? super Throwable> onNextHandler,
+                             int maxBufferCapacity) {
+            this.subscriber = subscriber;
+            this.executor = executor;
+            this.onNextHandler = onNextHandler;
+            this.maxCapacity = maxBufferCapacity;
+            this.array = new Object[maxBufferCapacity < DEFAULT_INITIAL_CAP ?
+                                    (maxBufferCapacity < 2 ? // at least 2 slots
+                                     2 : maxBufferCapacity) :
+                                    DEFAULT_INITIAL_CAP];
+        }
+
+        final boolean isDisabled() {
+            return ctl == DISABLED;
+        }
+
+        /**
+         * Returns estimated number of buffered items, or -1 if
+         * disabled.
+         */
+        final int estimateLag() {
+            int n;
+            return (ctl == DISABLED) ? -1 : ((n = tail - head) > 0) ? n : 0;
+        }
+
+        /**
+         * Tries to add item and start consumer task if necessary.
+         * @return -1 if disabled, 0 if dropped, else estimated lag
+         */
+        final int offer(T item) {
+            int h = head, t = tail, cap, size, stat;
+            Object[] a = array;
+            if (a != null && (cap = a.length) > 0 && cap >= (size = t + 1 - h)) {
+                a[(cap - 1) & t] = item;    // relaxed writes OK
+                tail = t + 1;
+                stat = size;
+            }
+            else
+                stat = growAndAdd(a, item);
+            return (stat > 0 &&
+                    (ctl & (ACTIVE | CONSUME)) != (ACTIVE | CONSUME)) ?
+                startOnOffer(stat) : stat;
+        }
+
+        /**
+         * Tries to create or expand buffer, then adds item if possible.
+         */
+        private int growAndAdd(Object[] a, T item) {
+            boolean alloc;
+            int cap, stat;
+            if ((ctl & (ERROR | DISABLED)) != 0) {
+                cap = 0;
+                stat = -1;
+                alloc = false;
+            }
+            else if (a == null || (cap = a.length) <= 0) {
+                cap = 0;
+                stat = 1;
+                alloc = true;
+            }
+            else {
+                U.fullFence();                   // recheck
+                int h = head, t = tail, size = t + 1 - h;
+                if (cap >= size) {
+                    a[(cap - 1) & t] = item;
+                    tail = t + 1;
+                    stat = size;
+                    alloc = false;
+                }
+                else if (cap >= maxCapacity) {
+                    stat = 0;                    // cannot grow
+                    alloc = false;
+                }
+                else {
+                    stat = cap + 1;
+                    alloc = true;
+                }
+            }
+            if (alloc) {
+                int newCap = (cap > 0) ? cap << 1 : 1;
+                if (newCap <= cap)
+                    stat = 0;
+                else {
+                    Object[] newArray = null;
+                    try {
+                        newArray = new Object[newCap];
+                    } catch (Throwable ex) {     // try to cope with OOME
+                    }
+                    if (newArray == null) {
+                        if (cap > 0)
+                            maxCapacity = cap;   // avoid continuous failure
+                        stat = 0;
+                    }
+                    else {
+                        array = newArray;
+                        int t = tail;
+                        int newMask = newCap - 1;
+                        if (a != null && cap > 0) {
+                            int mask = cap - 1;
+                            for (int j = head; j != t; ++j) {
+                                long k = ((long)(j & mask) << ASHIFT) + ABASE;
+                                Object x = U.getObjectVolatile(a, k);
+                                if (x != null && // races with consumer
+                                    U.compareAndSwapObject(a, k, x, null))
+                                    newArray[j & newMask] = x;
+                            }
+                        }
+                        newArray[t & newMask] = item;
+                        tail = t + 1;
+                    }
+                }
+            }
+            return stat;
+        }
+
+        /**
+         * Spins/helps/blocks while offer returns 0.  Called only if
+         * initial offer return 0.
+         */
+        final int submit(T item) {
+            int stat; Executor e; ForkJoinWorkerThread w;
+            if ((stat = offer(item)) == 0 && helpDepth == 0 &&
+                ((e = executor) instanceof ForkJoinPool)) {
+                helpDepth = 1;
+                Thread thread = Thread.currentThread();
+                if ((thread instanceof ForkJoinWorkerThread) &&
+                    ((w = (ForkJoinWorkerThread)thread)).getPool() == e)
+                    stat = internalHelpConsume(w.workQueue, item);
+                else if (e == ForkJoinPool.commonPool())
+                    stat = externalHelpConsume
+                        (ForkJoinPool.commonSubmitterQueue(), item);
+                helpDepth = 0;
+            }
+            if (stat == 0 && (stat = offer(item)) == 0) {
+                putItem = item;
+                timeout = 0L;
+                try {
+                    ForkJoinPool.managedBlock(this);
+                } catch (InterruptedException ie) {
+                    timeout = INTERRUPTED;
+                }
+                stat = putStat;
+                if (timeout < 0L)
+                    Thread.currentThread().interrupt();
+            }
+            return stat;
+        }
+
+        /**
+         * Tries helping for FJ submitter.
+         */
+        private int internalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
+            int stat = 0;
+            if (w != null) {
+                ForkJoinTask<?> t;
+                while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
+                    if ((stat = offer(item)) != 0 || !w.tryUnpush(t))
+                        break;
+                    ((ConsumerTask<?>)t).consumer.consume();
+                }
+            }
+            return stat;
+        }
+
+        /**
+         * Tries helping for non-FJ submitter.
+         */
+        private int externalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
+            int stat = 0;
+            if (w != null) {
+                ForkJoinTask<?> t;
+                while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
+                    if ((stat = offer(item)) != 0 || !w.trySharedUnpush(t))
+                        break;
+                    ((ConsumerTask<?>)t).consumer.consume();
+                }
+            }
+            return stat;
+        }
+
+        /**
+         * Timeout version; similar to submit.
+         */
+        final int timedOffer(T item, long nanos) {
+            int stat; Executor e;
+            if ((stat = offer(item)) == 0 && helpDepth == 0 &&
+                ((e = executor) instanceof ForkJoinPool)) {
+                Thread thread = Thread.currentThread();
+                if (((thread instanceof ForkJoinWorkerThread) &&
+                     ((ForkJoinWorkerThread)thread).getPool() == e) ||
+                    e == ForkJoinPool.commonPool()) {
+                    helpDepth = 1;
+                    ForkJoinTask<?> t;
+                    long deadline = System.nanoTime() + nanos;
+                    while ((t = ForkJoinTask.peekNextLocalTask()) != null &&
+                           (t instanceof ConsumerTask)) {
+                        if ((stat = offer(item)) != 0 ||
+                            (nanos = deadline - System.nanoTime()) <= 0L ||
+                            !t.tryUnfork())
+                            break;
+                        ((ConsumerTask<?>)t).consumer.consume();
+                    }
+                    helpDepth = 0;
+                }
+            }
+            if (stat == 0 && (stat = offer(item)) == 0 &&
+                (timeout = nanos) > 0L) {
+                putItem = item;
+                try {
+                    ForkJoinPool.managedBlock(this);
+                } catch (InterruptedException ie) {
+                    timeout = INTERRUPTED;
+                }
+                stat = putStat;
+                if (timeout < 0L)
+                    Thread.currentThread().interrupt();
+            }
+            return stat;
+        }
+
+        /**
+         * Tries to start consumer task after offer.
+         * @return -1 if now disabled, else argument
+         */
+        private int startOnOffer(int stat) {
+            for (;;) {
+                Executor e; int c;
+                if ((c = ctl) == DISABLED || (e = executor) == null) {
+                    stat = -1;
+                    break;
+                }
+                else if ((c & ACTIVE) != 0) { // ensure keep-alive
+                    if ((c & CONSUME) != 0 ||
+                        U.compareAndSwapInt(this, CTL, c,
+                                            c | CONSUME))
+                        break;
+                }
+                else if (demand == 0L || tail == head)
+                    break;
+                else if (U.compareAndSwapInt(this, CTL, c,
+                                             c | (ACTIVE | CONSUME))) {
+                    try {
+                        e.execute(new ConsumerTask<T>(this));
+                        break;
+                    } catch (RuntimeException | Error ex) { // back out
+                        do {} while (((c = ctl) & DISABLED) == 0 &&
+                                     (c & ACTIVE) != 0 &&
+                                     !U.compareAndSwapInt(this, CTL, c,
+                                                          c & ~ACTIVE));
+                        throw ex;
+                    }
+                }
+            }
+            return stat;
+        }
+
+        private void signalWaiter(Thread w) {
+            waiter = null;
+            LockSupport.unpark(w);    // release producer
+        }
+
+        /**
+         * Nulls out most fields, mainly to avoid garbage retention
+         * until publisher unsubscribes, but also to help cleanly stop
+         * upon error by nulling required components.
+         */
+        private void detach() {
+            Thread w = waiter;
+            executor = null;
+            subscriber = null;
+            pendingError = null;
+            signalWaiter(w);
+        }
+
+        /**
+         * Issues error signal, asynchronously if a task is running,
+         * else synchronously.
+         */
+        final void onError(Throwable ex) {
+            for (int c;;) {
+                if (((c = ctl) & (ERROR | DISABLED)) != 0)
+                    break;
+                else if ((c & ACTIVE) != 0) {
+                    pendingError = ex;
+                    if (U.compareAndSwapInt(this, CTL, c, c | ERROR))
+                        break; // cause consumer task to exit
+                }
+                else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                    Flow.Subscriber<? super T> s = subscriber;
+                    if (s != null && ex != null) {
+                        try {
+                            s.onError(ex);
+                        } catch (Throwable ignore) {
+                        }
+                    }
+                    detach();
+                    break;
+                }
+            }
+        }
+
+        /**
+         * Tries to start consumer task upon a signal or request;
+         * disables on failure.
+         */
+        private void startOrDisable() {
+            Executor e;
+            if ((e = executor) != null) { // skip if already disabled
+                try {
+                    e.execute(new ConsumerTask<T>(this));
+                } catch (Throwable ex) {  // back out and force signal
+                    for (int c;;) {
+                        if ((c = ctl) == DISABLED || (c & ACTIVE) == 0)
+                            break;
+                        if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
+                            onError(ex);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        final void onComplete() {
+            for (int c;;) {
+                if ((c = ctl) == DISABLED)
+                    break;
+                if (U.compareAndSwapInt(this, CTL, c,
+                                        c | (ACTIVE | CONSUME | COMPLETE))) {
+                    if ((c & ACTIVE) == 0)
+                        startOrDisable();
+                    break;
+                }
+            }
+        }
+
+        final void onSubscribe() {
+            for (int c;;) {
+                if ((c = ctl) == DISABLED)
+                    break;
+                if (U.compareAndSwapInt(this, CTL, c,
+                                        c | (ACTIVE | CONSUME | SUBSCRIBE))) {
+                    if ((c & ACTIVE) == 0)
+                        startOrDisable();
+                    break;
+                }
+            }
+        }
+
+        /**
+         * Causes consumer task to exit if active (without reporting
+         * onError unless there is already a pending error), and
+         * disables.
+         */
+        public void cancel() {
+            for (int c;;) {
+                if ((c = ctl) == DISABLED)
+                    break;
+                else if ((c & ACTIVE) != 0) {
+                    if (U.compareAndSwapInt(this, CTL, c,
+                                            c | (CONSUME | ERROR)))
+                        break;
+                }
+                else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                    detach();
+                    break;
+                }
+            }
+        }
+
+        /**
+         * Adds to demand and possibly starts task.
+         */
+        public void request(long n) {
+            if (n > 0L) {
+                for (;;) {
+                    long prev = demand, d;
+                    if ((d = prev + n) < prev) // saturate
+                        d = Long.MAX_VALUE;
+                    if (U.compareAndSwapLong(this, DEMAND, prev, d)) {
+                        for (int c, h;;) {
+                            if ((c = ctl) == DISABLED)
+                                break;
+                            else if ((c & ACTIVE) != 0) {
+                                if ((c & CONSUME) != 0 ||
+                                    U.compareAndSwapInt(this, CTL, c,
+                                                        c | CONSUME))
+                                    break;
+                            }
+                            else if ((h = head) != tail) {
+                                if (U.compareAndSwapInt(this, CTL, c,
+                                                        c | (ACTIVE|CONSUME))) {
+                                    startOrDisable();
+                                    break;
+                                }
+                            }
+                            else if (head == h && tail == h)
+                                break;          // else stale
+                            if (demand == 0L)
+                                break;
+                        }
+                        break;
+                    }
+                }
+            }
+            else if (n < 0L)
+                onError(new IllegalArgumentException(
+                            "negative subscription request"));
+        }
+
+        public final boolean isReleasable() { // for ManagedBlocker
+            T item = putItem;
+            if (item != null) {
+                if ((putStat = offer(item)) == 0)
+                    return false;
+                putItem = null;
+            }
+            return true;
+        }
+
+        public final boolean block() { // for ManagedBlocker
+            T item = putItem;
+            if (item != null) {
+                putItem = null;
+                long nanos = timeout;
+                long deadline = (nanos > 0L) ? System.nanoTime() + nanos : 0L;
+                while ((putStat = offer(item)) == 0) {
+                    if (Thread.interrupted()) {
+                        timeout = INTERRUPTED;
+                        if (nanos > 0L)
+                            break;
+                    }
+                    else if (nanos > 0L &&
+                             (nanos = deadline - System.nanoTime()) <= 0L)
+                        break;
+                    else if (waiter == null)
+                        waiter = Thread.currentThread();
+                    else {
+                        if (nanos > 0L)
+                            LockSupport.parkNanos(this, nanos);
+                        else
+                            LockSupport.park(this);
+                        waiter = null;
+                    }
+                }
+            }
+            waiter = null;
+            return true;
+        }
+
+        /**
+         * Consumer loop, called from ConsumerTask, or indirectly
+         * when helping during submit.
+         */
+        final void consume() {
+            Flow.Subscriber<? super T> s;
+            int h = head;
+            if ((s = subscriber) != null) {           // else disabled
+                for (;;) {
+                    long d = demand;
+                    int c; Object[] a; int n; long i; Object x; Thread w;
+                    if (((c = ctl) & (ERROR | SUBSCRIBE | DISABLED)) != 0) {
+                        if (!checkControl(s, c))
+                            break;
+                    }
+                    else if ((a = array) == null || h == tail ||
+                             (n = a.length) == 0 ||
+                             (x = U.getObjectVolatile
+                              (a, (i = ((long)((n - 1) & h) << ASHIFT) + ABASE)))
+                             == null) {
+                        if (!checkEmpty(s, c))
+                            break;
+                    }
+                    else if (d == 0L) {
+                        if (!checkDemand(c))
+                            break;
+                    }
+                    else if (((c & CONSUME) != 0 ||
+                              U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
+                             U.compareAndSwapObject(a, i, x, null)) {
+                        U.putOrderedInt(this, HEAD, ++h);
+                        U.getAndAddLong(this, DEMAND, -1L);
+                        if ((w = waiter) != null)
+                            signalWaiter(w);
+                        try {
+                            @SuppressWarnings("unchecked") T y = (T) x;
+                            s.onNext(y);
+                        } catch (Throwable ex) {
+                            handleOnNext(s, ex);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Responds to control events in consume().
+         */
+        private boolean checkControl(Flow.Subscriber<? super T> s, int c) {
+            boolean stat = true;
+            if ((c & ERROR) != 0) {
+                Throwable ex = pendingError;
+                ctl = DISABLED;           // no need for CAS
+                if (ex != null) {         // null if errorless cancel
+                    try {
+                        if (s != null)
+                            s.onError(ex);
+                    } catch (Throwable ignore) {
+                    }
+                }
+            }
+            else if ((c & SUBSCRIBE) != 0) {
+                if (U.compareAndSwapInt(this, CTL, c, c & ~SUBSCRIBE)) {
+                    try {
+                        if (s != null)
+                            s.onSubscribe(this);
+                    } catch (Throwable ex) {
+                        onError(ex);
+                    }
+                }
+            }
+            else {
+                detach();
+                stat = false;
+            }
+            return stat;
+        }
+
+        /**
+         * Responds to apparent emptiness in consume().
+         */
+        private boolean checkEmpty(Flow.Subscriber<? super T> s, int c) {
+            boolean stat = true;
+            if (head == tail) {
+                if ((c & CONSUME) != 0)
+                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
+                else if ((c & COMPLETE) != 0) {
+                    if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                        try {
+                            if (s != null)
+                                s.onComplete();
+                        } catch (Throwable ignore) {
+                        }
+                    }
+                }
+                else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+                    stat = false;
+            }
+            return stat;
+        }
+
+        /**
+         * Responds to apparent zero demand in consume().
+         */
+        private boolean checkDemand(int c) {
+            boolean stat = true;
+            if (demand == 0L) {
+                if ((c & CONSUME) != 0)
+                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
+                else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+                    stat = false;
+            }
+            return stat;
+        }
+
+        /**
+         * Processes exception in Subscriber.onNext.
+         */
+        private void handleOnNext(Flow.Subscriber<? super T> s, Throwable ex) {
+            BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> h;
+            if ((h = onNextHandler) != null) {
+                try {
+                    h.accept(s, ex);
+                } catch (Throwable ignore) {
+                }
+            }
+            onError(ex);
+        }
+
+        // Unsafe mechanics
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long CTL;
+        private static final long TAIL;
+        private static final long HEAD;
+        private static final long DEMAND;
+        private static final int ABASE;
+        private static final int ASHIFT;
+
+        static {
+            try {
+                CTL = U.objectFieldOffset
+                    (BufferedSubscription.class.getDeclaredField("ctl"));
+                TAIL = U.objectFieldOffset
+                    (BufferedSubscription.class.getDeclaredField("tail"));
+                HEAD = U.objectFieldOffset
+                    (BufferedSubscription.class.getDeclaredField("head"));
+                DEMAND = U.objectFieldOffset
+                    (BufferedSubscription.class.getDeclaredField("demand"));
+
+                ABASE = U.arrayBaseOffset(Object[].class);
+                int scale = U.arrayIndexScale(Object[].class);
+                if ((scale & (scale - 1)) != 0)
+                    throw new Error("data type scale not a power of two");
+                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            } catch (ReflectiveOperationException e) {
+                throw new Error(e);
+            }
+
+            // Reduce the risk of rare disastrous classloading in first call to
+            // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+            Class<?> ensureLoaded = LockSupport.class;
+        }
+    }
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,11 +35,15 @@
  */
 
 package java.util.concurrent;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.concurrent.locks.LockSupport;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
-import java.util.Spliterator;
-import java.util.Spliterators;
 
 /**
  * A {@linkplain BlockingQueue blocking queue} in which each insert
@@ -79,7 +83,7 @@
  *
  * @since 1.5
  * @author Doug Lea and Bill Scherer and Michael Scott
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public class SynchronousQueue<E> extends AbstractQueue<E>
     implements BlockingQueue<E>, java.io.Serializable {
@@ -182,9 +186,6 @@
         abstract E transfer(E e, boolean timed, long nanos);
     }
 
-    /** The number of CPUs, for spin control */
-    static final int NCPUS = Runtime.getRuntime().availableProcessors();
-
     /**
      * The number of times to spin before blocking in timed waits.
      * The value is empirically derived -- it works well across a
@@ -192,20 +193,21 @@
      * seems not to vary with number of CPUs (beyond 2) so is just
      * a constant.
      */
-    static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
+    static final int MAX_TIMED_SPINS =
+        (Runtime.getRuntime().availableProcessors() < 2) ? 0 : 32;
 
     /**
      * The number of times to spin before blocking in untimed waits.
      * This is greater than timed value because untimed waits spin
      * faster since they don't need to check times on each spin.
      */
-    static final int maxUntimedSpins = maxTimedSpins * 16;
+    static final int MAX_UNTIMED_SPINS = MAX_TIMED_SPINS * 16;
 
     /**
      * The number of nanoseconds for which it is faster to spin
      * rather than to use timed park. A rough estimate suffices.
      */
-    static final long spinForTimeoutThreshold = 1000L;
+    static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
 
     /** Dual stack */
     static final class TransferStack<E> extends Transferer<E> {
@@ -245,7 +247,7 @@
 
             boolean casNext(SNode cmp, SNode val) {
                 return cmp == next &&
-                    UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+                    U.compareAndSwapObject(this, NEXT, cmp, val);
             }
 
             /**
@@ -258,7 +260,7 @@
              */
             boolean tryMatch(SNode s) {
                 if (match == null &&
-                    UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
+                    U.compareAndSwapObject(this, MATCH, null, s)) {
                     Thread w = waiter;
                     if (w != null) {    // waiters need at most one unpark
                         waiter = null;
@@ -273,7 +275,7 @@
              * Tries to cancel a wait by matching node to itself.
              */
             void tryCancel() {
-                UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
+                U.compareAndSwapObject(this, MATCH, null, this);
             }
 
             boolean isCancelled() {
@@ -281,19 +283,17 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe UNSAFE;
-            private static final long matchOffset;
-            private static final long nextOffset;
+            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final long MATCH;
+            private static final long NEXT;
 
             static {
                 try {
-                    UNSAFE = sun.misc.Unsafe.getUnsafe();
-                    Class<?> k = SNode.class;
-                    matchOffset = UNSAFE.objectFieldOffset
-                        (k.getDeclaredField("match"));
-                    nextOffset = UNSAFE.objectFieldOffset
-                        (k.getDeclaredField("next"));
-                } catch (Exception e) {
+                    MATCH = U.objectFieldOffset
+                        (SNode.class.getDeclaredField("match"));
+                    NEXT = U.objectFieldOffset
+                        (SNode.class.getDeclaredField("next"));
+                } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
             }
@@ -304,7 +304,7 @@
 
         boolean casHead(SNode h, SNode nh) {
             return h == head &&
-                UNSAFE.compareAndSwapObject(this, headOffset, h, nh);
+                U.compareAndSwapObject(this, HEAD, h, nh);
         }
 
         /**
@@ -353,7 +353,7 @@
             for (;;) {
                 SNode h = head;
                 if (h == null || h.mode == mode) {  // empty or same-mode
-                    if (timed && nanos <= 0) {      // can't wait
+                    if (timed && nanos <= 0L) {     // can't wait
                         if (h != null && h.isCancelled())
                             casHead(h, h.next);     // pop cancelled node
                         else
@@ -435,8 +435,9 @@
              */
             final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
-            int spins = (shouldSpin(s) ?
-                         (timed ? maxTimedSpins : maxUntimedSpins) : 0);
+            int spins = shouldSpin(s)
+                ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
+                : 0;
             for (;;) {
                 if (w.isInterrupted())
                     s.tryCancel();
@@ -451,12 +452,12 @@
                     }
                 }
                 if (spins > 0)
-                    spins = shouldSpin(s) ? (spins-1) : 0;
+                    spins = shouldSpin(s) ? (spins - 1) : 0;
                 else if (s.waiter == null)
                     s.waiter = w; // establish waiter so can park next iter
                 else if (!timed)
                     LockSupport.park(this);
-                else if (nanos > spinForTimeoutThreshold)
+                else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanos);
             }
         }
@@ -508,15 +509,13 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long headOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long HEAD;
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = TransferStack.class;
-                headOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("head"));
-            } catch (Exception e) {
+                HEAD = U.objectFieldOffset
+                    (TransferStack.class.getDeclaredField("head"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -547,19 +546,19 @@
 
             boolean casNext(QNode cmp, QNode val) {
                 return next == cmp &&
-                    UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+                    U.compareAndSwapObject(this, NEXT, cmp, val);
             }
 
             boolean casItem(Object cmp, Object val) {
                 return item == cmp &&
-                    UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+                    U.compareAndSwapObject(this, ITEM, cmp, val);
             }
 
             /**
              * Tries to cancel by CAS'ing ref to this as item.
              */
             void tryCancel(Object cmp) {
-                UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this);
+                U.compareAndSwapObject(this, ITEM, cmp, this);
             }
 
             boolean isCancelled() {
@@ -576,19 +575,17 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe UNSAFE;
-            private static final long itemOffset;
-            private static final long nextOffset;
+            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final long ITEM;
+            private static final long NEXT;
 
             static {
                 try {
-                    UNSAFE = sun.misc.Unsafe.getUnsafe();
-                    Class<?> k = QNode.class;
-                    itemOffset = UNSAFE.objectFieldOffset
-                        (k.getDeclaredField("item"));
-                    nextOffset = UNSAFE.objectFieldOffset
-                        (k.getDeclaredField("next"));
-                } catch (Exception e) {
+                    ITEM = U.objectFieldOffset
+                        (QNode.class.getDeclaredField("item"));
+                    NEXT = U.objectFieldOffset
+                        (QNode.class.getDeclaredField("next"));
+                } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
             }
@@ -617,7 +614,7 @@
          */
         void advanceHead(QNode h, QNode nh) {
             if (h == head &&
-                UNSAFE.compareAndSwapObject(this, headOffset, h, nh))
+                U.compareAndSwapObject(this, HEAD, h, nh))
                 h.next = h; // forget old next
         }
 
@@ -626,7 +623,7 @@
          */
         void advanceTail(QNode t, QNode nt) {
             if (tail == t)
-                UNSAFE.compareAndSwapObject(this, tailOffset, t, nt);
+                U.compareAndSwapObject(this, TAIL, t, nt);
         }
 
         /**
@@ -634,7 +631,7 @@
          */
         boolean casCleanMe(QNode cmp, QNode val) {
             return cleanMe == cmp &&
-                UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
+                U.compareAndSwapObject(this, CLEANME, cmp, val);
         }
 
         /**
@@ -684,7 +681,7 @@
                         advanceTail(t, tn);
                         continue;
                     }
-                    if (timed && nanos <= 0)        // can't wait
+                    if (timed && nanos <= 0L)       // can't wait
                         return null;
                     if (s == null)
                         s = new QNode(e, isData);
@@ -739,8 +736,9 @@
             /* Same idea as TransferStack.awaitFulfill */
             final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
-            int spins = ((head.next == s) ?
-                         (timed ? maxTimedSpins : maxUntimedSpins) : 0);
+            int spins = (head.next == s)
+                ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
+                : 0;
             for (;;) {
                 if (w.isInterrupted())
                     s.tryCancel(e);
@@ -760,7 +758,7 @@
                     s.waiter = w;
                 else if (!timed)
                     LockSupport.park(this);
-                else if (nanos > spinForTimeoutThreshold)
+                else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanos);
             }
         }
@@ -819,21 +817,19 @@
             }
         }
 
-        private static final sun.misc.Unsafe UNSAFE;
-        private static final long headOffset;
-        private static final long tailOffset;
-        private static final long cleanMeOffset;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long HEAD;
+        private static final long TAIL;
+        private static final long CLEANME;
         static {
             try {
-                UNSAFE = sun.misc.Unsafe.getUnsafe();
-                Class<?> k = TransferQueue.class;
-                headOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("head"));
-                tailOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("tail"));
-                cleanMeOffset = UNSAFE.objectFieldOffset
-                    (k.getDeclaredField("cleanMe"));
-            } catch (Exception e) {
+                HEAD = U.objectFieldOffset
+                    (TransferQueue.class.getDeclaredField("head"));
+                TAIL = U.objectFieldOffset
+                    (TransferQueue.class.getDeclaredField("tail"));
+                CLEANME = U.objectFieldOffset
+                    (TransferQueue.class.getDeclaredField("cleanMe"));
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
         }
@@ -1088,7 +1084,7 @@
     }
 
     /**
-     * Sets the zeroeth element of the specified array to {@code null}
+     * Sets the zeroth element of the specified array to {@code null}
      * (if the array has non-zero length) and returns it.
      *
      * @param a the array
@@ -1102,6 +1098,14 @@
     }
 
     /**
+     * Always returns {@code "[]"}.
+     * @return {@code "[]"}
+     */
+    public String toString() {
+        return "[]";
+    }
+
+    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -1196,17 +1200,9 @@
             transferer = new TransferStack<E>();
     }
 
-    // Unsafe mechanics
-    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
-                                  String field, Class<?> klazz) {
-        try {
-            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
-        } catch (NoSuchFieldException e) {
-            // Convert Exception to corresponding Error
-            NoSuchFieldError error = new NoSuchFieldError(field);
-            error.initCause(e);
-            throw error;
-        }
+    static {
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
-
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -42,7 +42,7 @@
  *
  * <p>
  * The simplest implementation of this interface is just:
- *  <pre> {@code
+ * <pre> {@code
  * class SimpleThreadFactory implements ThreadFactory {
  *   public Thread newThread(Runnable r) {
  *     return new Thread(r);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Wed Jul 05 20:54:58 2017 +0200
@@ -126,8 +126,7 @@
      */
 
     /** Generates per-thread initialization/probe field */
-    private static final AtomicInteger probeGenerator =
-        new AtomicInteger();
+    private static final AtomicInteger probeGenerator = new AtomicInteger();
 
     /**
      * The next seed for default constructors.
@@ -150,17 +149,17 @@
     }
 
     /**
-     * The seed increment
+     * The seed increment.
      */
     private static final long GAMMA = 0x9e3779b97f4a7c15L;
 
     /**
-     * The increment for generating probe values
+     * The increment for generating probe values.
      */
     private static final int PROBE_INCREMENT = 0x9e3779b9;
 
     /**
-     * The increment of seeder per new instance
+     * The increment of seeder per new instance.
      */
     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
 
@@ -170,7 +169,7 @@
 
     /** Rarely-used holder for the second of a pair of Gaussians */
     private static final ThreadLocal<Double> nextLocalGaussian =
-        new ThreadLocal<Double>();
+        new ThreadLocal<>();
 
     private static long mix64(long z) {
         z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
@@ -209,8 +208,8 @@
         int probe = (p == 0) ? 1 : p; // skip 0
         long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
         Thread t = Thread.currentThread();
-        UNSAFE.putLong(t, SEED, seed);
-        UNSAFE.putInt(t, PROBE, probe);
+        U.putLong(t, SEED, seed);
+        U.putInt(t, PROBE, probe);
     }
 
     /**
@@ -219,7 +218,7 @@
      * @return the current thread's {@code ThreadLocalRandom}
      */
     public static ThreadLocalRandom current() {
-        if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
+        if (U.getInt(Thread.currentThread(), PROBE) == 0)
             localInit();
         return instance;
     }
@@ -238,8 +237,8 @@
 
     final long nextSeed() {
         Thread t; long r; // read and update per-thread seed
-        UNSAFE.putLong(t = Thread.currentThread(), SEED,
-                       r = UNSAFE.getLong(t, SEED) + GAMMA);
+        U.putLong(t = Thread.currentThread(), SEED,
+                  r = U.getLong(t, SEED) + GAMMA);
         return r;
     }
 
@@ -249,9 +248,9 @@
     }
 
     // IllegalArgumentException messages
-    static final String BadBound = "bound must be positive";
-    static final String BadRange = "bound must be greater than origin";
-    static final String BadSize  = "size must be non-negative";
+    static final String BAD_BOUND = "bound must be positive";
+    static final String BAD_RANGE = "bound must be greater than origin";
+    static final String BAD_SIZE  = "size must be non-negative";
 
     /**
      * The form of nextLong used by LongStream Spliterators.  If
@@ -349,7 +348,7 @@
      */
     public int nextInt(int bound) {
         if (bound <= 0)
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         int r = mix32(nextSeed());
         int m = bound - 1;
         if ((bound & m) == 0) // power of two
@@ -376,7 +375,7 @@
      */
     public int nextInt(int origin, int bound) {
         if (origin >= bound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextInt(origin, bound);
     }
 
@@ -400,7 +399,7 @@
      */
     public long nextLong(long bound) {
         if (bound <= 0)
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         long r = mix64(nextSeed());
         long m = bound - 1;
         if ((bound & m) == 0L) // power of two
@@ -427,7 +426,7 @@
      */
     public long nextLong(long origin, long bound) {
         if (origin >= bound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextLong(origin, bound);
     }
 
@@ -453,9 +452,9 @@
      */
     public double nextDouble(double bound) {
         if (!(bound > 0.0))
-            throw new IllegalArgumentException(BadBound);
+            throw new IllegalArgumentException(BAD_BOUND);
         double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
-        return (result < bound) ?  result : // correct for rounding
+        return (result < bound) ? result : // correct for rounding
             Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
     }
 
@@ -472,7 +471,7 @@
      */
     public double nextDouble(double origin, double bound) {
         if (!(origin < bound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return internalNextDouble(origin, bound);
     }
 
@@ -529,7 +528,7 @@
      */
     public IntStream ints(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (0L, streamSize, Integer.MAX_VALUE, 0),
@@ -571,9 +570,9 @@
     public IntStream ints(long streamSize, int randomNumberOrigin,
                           int randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -598,7 +597,7 @@
      */
     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.intStream
             (new RandomIntsSpliterator
              (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -617,7 +616,7 @@
      */
     public LongStream longs(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (0L, streamSize, Long.MAX_VALUE, 0L),
@@ -659,9 +658,9 @@
     public LongStream longs(long streamSize, long randomNumberOrigin,
                             long randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -686,7 +685,7 @@
      */
     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
         if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.longStream
             (new RandomLongsSpliterator
              (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -706,7 +705,7 @@
      */
     public DoubleStream doubles(long streamSize) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (0L, streamSize, Double.MAX_VALUE, 0.0),
@@ -750,9 +749,9 @@
     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
                                 double randomNumberBound) {
         if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
+            throw new IllegalArgumentException(BAD_SIZE);
         if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -777,7 +776,7 @@
      */
     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
         if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
+            throw new IllegalArgumentException(BAD_RANGE);
         return StreamSupport.doubleStream
             (new RandomDoublesSpliterator
              (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -792,7 +791,8 @@
      * approach. The long and double versions of this class are
      * identical except for types.
      */
-    static final class RandomIntsSpliterator implements Spliterator.OfInt {
+    private static final class RandomIntsSpliterator
+            implements Spliterator.OfInt {
         long index;
         final long fence;
         final int origin;
@@ -846,7 +846,8 @@
     /**
      * Spliterator for long streams.
      */
-    static final class RandomLongsSpliterator implements Spliterator.OfLong {
+    private static final class RandomLongsSpliterator
+            implements Spliterator.OfLong {
         long index;
         final long fence;
         final long origin;
@@ -901,7 +902,8 @@
     /**
      * Spliterator for double streams.
      */
-    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+    private static final class RandomDoublesSpliterator
+            implements Spliterator.OfDouble {
         long index;
         final long fence;
         final double origin;
@@ -978,7 +980,7 @@
      * can be used to force initialization on zero return.
      */
     static final int getProbe() {
-        return UNSAFE.getInt(Thread.currentThread(), PROBE);
+        return U.getInt(Thread.currentThread(), PROBE);
     }
 
     /**
@@ -989,7 +991,7 @@
         probe ^= probe << 13;   // xorshift
         probe ^= probe >>> 17;
         probe ^= probe << 5;
-        UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
+        U.putInt(Thread.currentThread(), PROBE, probe);
         return probe;
     }
 
@@ -999,17 +1001,14 @@
     static final int nextSecondarySeed() {
         int r;
         Thread t = Thread.currentThread();
-        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
+        if ((r = U.getInt(t, SECONDARY)) != 0) {
             r ^= r << 13;   // xorshift
             r ^= r >>> 17;
             r ^= r << 5;
         }
-        else {
-            localInit();
-            if ((r = (int)UNSAFE.getLong(t, SEED)) == 0)
-                r = 1; // avoid zero
-        }
-        UNSAFE.putInt(t, SECONDARY, r);
+        else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
+            r = 1; // avoid zero
+        U.putInt(t, SECONDARY, r);
         return r;
     }
 
@@ -1024,8 +1023,8 @@
      *              always true
      */
     private static final ObjectStreamField[] serialPersistentFields = {
-            new ObjectStreamField("rnd", long.class),
-            new ObjectStreamField("initialized", boolean.class),
+        new ObjectStreamField("rnd", long.class),
+        new ObjectStreamField("initialized", boolean.class),
     };
 
     /**
@@ -1037,7 +1036,7 @@
         throws java.io.IOException {
 
         java.io.ObjectOutputStream.PutField fields = s.putFields();
-        fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
+        fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
         fields.put("initialized", true);
         s.writeFields();
     }
@@ -1051,21 +1050,19 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long SEED;
     private static final long PROBE;
     private static final long SECONDARY;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> tk = Thread.class;
-            SEED = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomSeed"));
-            PROBE = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomProbe"));
-            SECONDARY = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
-        } catch (Exception e) {
+            SEED = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocalRandomSeed"));
+            PROBE = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+            SECONDARY = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,11 +34,16 @@
  */
 
 package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.*;
 
 /**
  * An {@link ExecutorService} that executes each submitted task using
@@ -69,7 +74,8 @@
  *
  * <dt>Core and maximum pool sizes</dt>
  *
- * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * A {@code ThreadPoolExecutor} will automatically adjust the
  * pool size (see {@link #getPoolSize})
  * according to the bounds set by
  * corePoolSize (see {@link #getCorePoolSize}) and
@@ -91,7 +97,8 @@
  *
  * <dt>On-demand construction</dt>
  *
- * <dd>By default, even core threads are initially created and
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * By default, even core threads are initially created and
  * started only when new tasks arrive, but this can be overridden
  * dynamically using method {@link #prestartCoreThread} or {@link
  * #prestartAllCoreThreads}.  You probably want to prestart threads if
@@ -99,7 +106,8 @@
  *
  * <dt>Creating new threads</dt>
  *
- * <dd>New threads are created using a {@link ThreadFactory}.  If not
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * New threads are created using a {@link ThreadFactory}.  If not
  * otherwise specified, a {@link Executors#defaultThreadFactory} is
  * used, that creates threads to all be in the same {@link
  * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and
@@ -116,7 +124,8 @@
  *
  * <dt>Keep-alive times</dt>
  *
- * <dd>If the pool currently has more than corePoolSize threads,
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * If the pool currently has more than corePoolSize threads,
  * excess threads will be terminated if they have been idle for more
  * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
  * This provides a means of reducing resource consumption when the
@@ -126,36 +135,37 @@
  * TimeUnit)}.  Using a value of {@code Long.MAX_VALUE} {@link
  * TimeUnit#NANOSECONDS} effectively disables idle threads from ever
  * terminating prior to shut down. By default, the keep-alive policy
- * applies only when there are more than corePoolSize threads. But
+ * applies only when there are more than corePoolSize threads, but
  * method {@link #allowCoreThreadTimeOut(boolean)} can be used to
  * apply this time-out policy to core threads as well, so long as the
  * keepAliveTime value is non-zero. </dd>
  *
  * <dt>Queuing</dt>
  *
- * <dd>Any {@link BlockingQueue} may be used to transfer and hold
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * Any {@link BlockingQueue} may be used to transfer and hold
  * submitted tasks.  The use of this queue interacts with pool sizing:
  *
  * <ul>
  *
- * <li> If fewer than corePoolSize threads are running, the Executor
+ * <li>If fewer than corePoolSize threads are running, the Executor
  * always prefers adding a new thread
- * rather than queuing.</li>
+ * rather than queuing.
  *
- * <li> If corePoolSize or more threads are running, the Executor
+ * <li>If corePoolSize or more threads are running, the Executor
  * always prefers queuing a request rather than adding a new
- * thread.</li>
+ * thread.
  *
- * <li> If a request cannot be queued, a new thread is created unless
+ * <li>If a request cannot be queued, a new thread is created unless
  * this would exceed maximumPoolSize, in which case, the task will be
- * rejected.</li>
+ * rejected.
  *
  * </ul>
  *
  * There are three general strategies for queuing:
  * <ol>
  *
- * <li> <em> Direct handoffs.</em> A good default choice for a work
+ * <li><em> Direct handoffs.</em> A good default choice for a work
  * queue is a {@link SynchronousQueue} that hands off tasks to threads
  * without otherwise holding them. Here, an attempt to queue a task
  * will fail if no threads are immediately available to run it, so a
@@ -164,7 +174,7 @@
  * Direct handoffs generally require unbounded maximumPoolSizes to
  * avoid rejection of new submitted tasks. This in turn admits the
  * possibility of unbounded thread growth when commands continue to
- * arrive on average faster than they can be processed.  </li>
+ * arrive on average faster than they can be processed.
  *
  * <li><em> Unbounded queues.</em> Using an unbounded queue (for
  * example a {@link LinkedBlockingQueue} without a predefined
@@ -177,7 +187,7 @@
  * While this style of queuing can be useful in smoothing out
  * transient bursts of requests, it admits the possibility of
  * unbounded work queue growth when commands continue to arrive on
- * average faster than they can be processed.  </li>
+ * average faster than they can be processed.
  *
  * <li><em>Bounded queues.</em> A bounded queue (for example, an
  * {@link ArrayBlockingQueue}) helps prevent resource exhaustion when
@@ -190,7 +200,7 @@
  * time for more threads than you otherwise allow. Use of small queues
  * generally requires larger pool sizes, which keeps CPUs busier but
  * may encounter unacceptable scheduling overhead, which also
- * decreases throughput.  </li>
+ * decreases throughput.
  *
  * </ol>
  *
@@ -198,7 +208,8 @@
  *
  * <dt>Rejected tasks</dt>
  *
- * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * New tasks submitted in method {@link #execute(Runnable)} will be
  * <em>rejected</em> when the Executor has been shut down, and also when
  * the Executor uses finite bounds for both maximum threads and work queue
  * capacity, and is saturated.  In either case, the {@code execute} method
@@ -209,22 +220,22 @@
  *
  * <ol>
  *
- * <li> In the default {@link ThreadPoolExecutor.AbortPolicy}, the
+ * <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the
  * handler throws a runtime {@link RejectedExecutionException} upon
- * rejection. </li>
+ * rejection.
  *
- * <li> In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
+ * <li>In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
  * that invokes {@code execute} itself runs the task. This provides a
  * simple feedback control mechanism that will slow down the rate that
- * new tasks are submitted. </li>
+ * new tasks are submitted.
  *
- * <li> In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
- * cannot be executed is simply dropped.  </li>
+ * <li>In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
+ * cannot be executed is simply dropped.
  *
  * <li>In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the
  * executor is not shut down, the task at the head of the work queue
  * is dropped, and then execution is retried (which can fail again,
- * causing this to be repeated.) </li>
+ * causing this to be repeated.)
  *
  * </ol>
  *
@@ -235,7 +246,8 @@
  *
  * <dt>Hook methods</dt>
  *
- * <dd>This class provides {@code protected} overridable
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * This class provides {@code protected} overridable
  * {@link #beforeExecute(Thread, Runnable)} and
  * {@link #afterExecute(Runnable, Throwable)} methods that are called
  * before and after execution of each task.  These can be used to
@@ -245,12 +257,14 @@
  * any special processing that needs to be done once the Executor has
  * fully terminated.
  *
- * <p>If hook or callback methods throw exceptions, internal worker
- * threads may in turn fail and abruptly terminate.</dd>
+ * <p>If hook, callback, or BlockingQueue methods throw exceptions,
+ * internal worker threads may in turn fail, abruptly terminate, and
+ * possibly be replaced.</dd>
  *
  * <dt>Queue maintenance</dt>
  *
- * <dd>Method {@link #getQueue()} allows access to the work queue
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * Method {@link #getQueue()} allows access to the work queue
  * for purposes of monitoring and debugging.  Use of this method for
  * any other purpose is strongly discouraged.  Two supplied methods,
  * {@link #remove(Runnable)} and {@link #purge} are available to
@@ -259,7 +273,8 @@
  *
  * <dt>Finalization</dt>
  *
- * <dd>A pool that is no longer referenced in a program <em>AND</em>
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * A pool that is no longer referenced in a program <em>AND</em>
  * has no remaining threads will be {@code shutdown} automatically. If
  * you would like to ensure that unreferenced pools are reclaimed even
  * if users forget to call {@link #shutdown}, then you must arrange
@@ -273,7 +288,7 @@
  * override one or more of the protected hook methods. For example,
  * here is a subclass that adds a simple pause/resume feature:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
  *   private boolean isPaused;
  *   private ReentrantLock pauseLock = new ReentrantLock();
@@ -462,10 +477,10 @@
      * Set containing all worker threads in pool. Accessed only when
      * holding mainLock.
      */
-    private final HashSet<Worker> workers = new HashSet<Worker>();
+    private final HashSet<Worker> workers = new HashSet<>();
 
     /**
-     * Wait condition to support awaitTermination
+     * Wait condition to support awaitTermination.
      */
     private final Condition termination = mainLock.newCondition();
 
@@ -541,7 +556,7 @@
     private volatile int maximumPoolSize;
 
     /**
-     * The default rejected execution handler
+     * The default rejected execution handler.
      */
     private static final RejectedExecutionHandler defaultHandler =
         new AbortPolicy();
@@ -612,7 +627,7 @@
             this.thread = getThreadFactory().newThread(this);
         }
 
-        /** Delegates main run loop to outer runWorker  */
+        /** Delegates main run loop to outer runWorker. */
         public void run() {
             runWorker(this);
         }
@@ -668,6 +683,7 @@
      *        (but not TIDYING or TERMINATED -- use tryTerminate for that)
      */
     private void advanceRunState(int targetState) {
+        // assert targetState == SHUTDOWN || targetState == STOP;
         for (;;) {
             int c = ctl.get();
             if (runStateAtLeast(c, targetState) ||
@@ -850,7 +866,7 @@
      */
     private List<Runnable> drainQueue() {
         BlockingQueue<Runnable> q = workQueue;
-        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
+        ArrayList<Runnable> taskList = new ArrayList<>();
         q.drainTo(taskList);
         if (!q.isEmpty()) {
             for (Runnable r : q.toArray(new Runnable[0])) {
@@ -1406,7 +1422,7 @@
      *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  This implementation
-     * cancels tasks via {@link Thread#interrupt}, so any task that
+     * interrupts tasks via {@link Thread#interrupt}; any task that
      * fails to respond to interrupts may never terminate.
      *
      * @throws SecurityException {@inheritDoc}
@@ -1457,13 +1473,12 @@
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            for (;;) {
-                if (runStateAtLeast(ctl.get(), TERMINATED))
-                    return true;
-                if (nanos <= 0)
+            while (!runStateAtLeast(ctl.get(), TERMINATED)) {
+                if (nanos <= 0L)
                     return false;
                 nanos = termination.awaitNanos(nanos);
             }
+            return true;
         } finally {
             mainLock.unlock();
         }
@@ -1680,11 +1695,13 @@
     }
 
     /**
-     * Sets the time limit for which threads may remain idle before
-     * being terminated.  If there are more than the core number of
-     * threads currently in the pool, after waiting this amount of
-     * time without processing a task, excess threads will be
-     * terminated.  This overrides any value set in the constructor.
+     * Sets the thread keep-alive time, which is the amount of time
+     * that threads may remain idle before being terminated.
+     * Threads that wait this amount of time without processing a
+     * task will be terminated if there are more than the core
+     * number of threads currently in the pool, or if this pool
+     * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}.
+     * This overrides any value set in the constructor.
      *
      * @param time the time to wait.  A time value of zero will cause
      *        excess threads to terminate immediately after executing tasks.
@@ -1707,8 +1724,11 @@
 
     /**
      * Returns the thread keep-alive time, which is the amount of time
-     * that threads in excess of the core pool size may remain
-     * idle before being terminated.
+     * that threads may remain idle before being terminated.
+     * Threads that wait this amount of time without processing a
+     * task will be terminated if there are more than the core
+     * number of threads currently in the pool, or if this pool
+     * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}.
      *
      * @param unit the desired time unit of the result
      * @return the time limit
@@ -1739,8 +1759,8 @@
      *
      * <p>This method may be useful as one part of a cancellation
      * scheme.  It may fail to remove tasks that have been converted
-     * into other forms before being placed on the internal queue. For
-     * example, a task entered using {@code submit} might be
+     * into other forms before being placed on the internal queue.
+     * For example, a task entered using {@code submit} might be
      * converted into a form that maintains {@code Future} status.
      * However, in such cases, method {@link #purge} may be used to
      * remove those Futures that have been cancelled.
@@ -1912,11 +1932,12 @@
             mainLock.unlock();
         }
         int c = ctl.get();
-        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
-                     (runStateAtLeast(c, TERMINATED) ? "Terminated" :
-                      "Shutting down"));
+        String runState =
+            runStateLessThan(c, SHUTDOWN) ? "Running" :
+            runStateAtLeast(c, TERMINATED) ? "Terminated" :
+            "Shutting down";
         return super.toString() +
-            "[" + rs +
+            "[" + runState +
             ", pool size = " + nworkers +
             ", active threads = " + nactive +
             ", queued tasks = " + workQueue.size() +
@@ -1963,20 +1984,23 @@
      * as in this sample subclass that prints either the direct cause
      * or the underlying exception if a task has been aborted:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * class ExtendedExecutor extends ThreadPoolExecutor {
      *   // ...
      *   protected void afterExecute(Runnable r, Throwable t) {
      *     super.afterExecute(r, t);
-     *     if (t == null && r instanceof Future<?>) {
+     *     if (t == null
+     *         && r instanceof Future<?>
+     *         && ((Future<?>)r).isDone()) {
      *       try {
      *         Object result = ((Future<?>) r).get();
      *       } catch (CancellationException ce) {
-     *           t = ce;
+     *         t = ce;
      *       } catch (ExecutionException ee) {
-     *           t = ee.getCause();
+     *         t = ee.getCause();
      *       } catch (InterruptedException ie) {
-     *           Thread.currentThread().interrupt(); // ignore/reset
+     *         // ignore/reset
+     *         Thread.currentThread().interrupt();
      *       }
      *     }
      *     if (t != null)
--- a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java	Wed Jul 05 20:54:58 2017 +0200
@@ -52,12 +52,12 @@
  * the following code will timeout in 50 milliseconds if the {@link
  * java.util.concurrent.locks.Lock lock} is not available:
  *
- *  <pre> {@code
+ * <pre> {@code
  * Lock lock = ...;
  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
  *
  * while this code will timeout in 50 seconds:
- *  <pre> {@code
+ * <pre> {@code
  * Lock lock = ...;
  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
  *
@@ -70,7 +70,7 @@
  */
 public enum TimeUnit {
     /**
-     * Time unit representing one thousandth of a microsecond
+     * Time unit representing one thousandth of a microsecond.
      */
     NANOSECONDS {
         public long toNanos(long d)   { return d; }
@@ -85,7 +85,7 @@
     },
 
     /**
-     * Time unit representing one thousandth of a millisecond
+     * Time unit representing one thousandth of a millisecond.
      */
     MICROSECONDS {
         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
@@ -100,7 +100,7 @@
     },
 
     /**
-     * Time unit representing one thousandth of a second
+     * Time unit representing one thousandth of a second.
      */
     MILLISECONDS {
         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
@@ -115,7 +115,7 @@
     },
 
     /**
-     * Time unit representing one second
+     * Time unit representing one second.
      */
     SECONDS {
         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
@@ -130,7 +130,7 @@
     },
 
     /**
-     * Time unit representing sixty seconds
+     * Time unit representing sixty seconds.
      * @since 1.6
      */
     MINUTES {
@@ -146,7 +146,7 @@
     },
 
     /**
-     * Time unit representing sixty minutes
+     * Time unit representing sixty minutes.
      * @since 1.6
      */
     HOURS {
@@ -162,7 +162,7 @@
     },
 
     /**
-     * Time unit representing twenty four hours
+     * Time unit representing twenty four hours.
      * @since 1.6
      */
     DAYS {
@@ -193,7 +193,7 @@
      * This has a short name to make above code more readable.
      */
     static long x(long d, long m, long over) {
-        if (d >  over) return Long.MAX_VALUE;
+        if (d > +over) return Long.MAX_VALUE;
         if (d < -over) return Long.MIN_VALUE;
         return d * m;
     }
@@ -329,7 +329,7 @@
      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
      * using:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * public synchronized Object poll(long timeout, TimeUnit unit)
      *     throws InterruptedException {
      *   while (empty) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/TransferQueue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TransferQueue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -63,7 +63,7 @@
  *
  * @since 1.7
  * @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
  */
 public interface TransferQueue<E> extends BlockingQueue<E> {
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Jul 05 20:54:58 2017 +0200
@@ -53,9 +53,9 @@
     private static final long serialVersionUID = -6209656149925076980L;
 
     private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long ARRAY;
     private static final int ABASE;
     private static final int ASHIFT;
-    private static final long ARRAY;
     private final Object[] array; // must have exact type Object[]
 
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,11 +34,12 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.concurrent.TimeUnit;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
-import sun.misc.Unsafe;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.Node;
 
 /**
  * A version of {@link AbstractQueuedSynchronizer} in
@@ -77,221 +78,6 @@
     protected AbstractQueuedLongSynchronizer() { }
 
     /**
-     * Wait queue node class.
-     *
-     * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
-     * Hagersten) lock queue. CLH locks are normally used for
-     * spinlocks.  We instead use them for blocking synchronizers, but
-     * use the same basic tactic of holding some of the control
-     * information about a thread in the predecessor of its node.  A
-     * "status" field in each node keeps track of whether a thread
-     * should block.  A node is signalled when its predecessor
-     * releases.  Each node of the queue otherwise serves as a
-     * specific-notification-style monitor holding a single waiting
-     * thread. The status field does NOT control whether threads are
-     * granted locks etc though.  A thread may try to acquire if it is
-     * first in the queue. But being first does not guarantee success;
-     * it only gives the right to contend.  So the currently released
-     * contender thread may need to rewait.
-     *
-     * <p>To enqueue into a CLH lock, you atomically splice it in as new
-     * tail. To dequeue, you just set the head field.
-     * <pre>
-     *      +------+  prev +-----+       +-----+
-     * head |      | <---- |     | <---- |     |  tail
-     *      +------+       +-----+       +-----+
-     * </pre>
-     *
-     * <p>Insertion into a CLH queue requires only a single atomic
-     * operation on "tail", so there is a simple atomic point of
-     * demarcation from unqueued to queued. Similarly, dequeuing
-     * involves only updating the "head". However, it takes a bit
-     * more work for nodes to determine who their successors are,
-     * in part to deal with possible cancellation due to timeouts
-     * and interrupts.
-     *
-     * <p>The "prev" links (not used in original CLH locks), are mainly
-     * needed to handle cancellation. If a node is cancelled, its
-     * successor is (normally) relinked to a non-cancelled
-     * predecessor. For explanation of similar mechanics in the case
-     * of spin locks, see the papers by Scott and Scherer at
-     * http://www.cs.rochester.edu/u/scott/synchronization/
-     *
-     * <p>We also use "next" links to implement blocking mechanics.
-     * The thread id for each node is kept in its own node, so a
-     * predecessor signals the next node to wake up by traversing
-     * next link to determine which thread it is.  Determination of
-     * successor must avoid races with newly queued nodes to set
-     * the "next" fields of their predecessors.  This is solved
-     * when necessary by checking backwards from the atomically
-     * updated "tail" when a node's successor appears to be null.
-     * (Or, said differently, the next-links are an optimization
-     * so that we don't usually need a backward scan.)
-     *
-     * <p>Cancellation introduces some conservatism to the basic
-     * algorithms.  Since we must poll for cancellation of other
-     * nodes, we can miss noticing whether a cancelled node is
-     * ahead or behind us. This is dealt with by always unparking
-     * successors upon cancellation, allowing them to stabilize on
-     * a new predecessor, unless we can identify an uncancelled
-     * predecessor who will carry this responsibility.
-     *
-     * <p>CLH queues need a dummy header node to get started. But
-     * we don't create them on construction, because it would be wasted
-     * effort if there is never contention. Instead, the node
-     * is constructed and head and tail pointers are set upon first
-     * contention.
-     *
-     * <p>Threads waiting on Conditions use the same nodes, but
-     * use an additional link. Conditions only need to link nodes
-     * in simple (non-concurrent) linked queues because they are
-     * only accessed when exclusively held.  Upon await, a node is
-     * inserted into a condition queue.  Upon signal, the node is
-     * transferred to the main queue.  A special value of status
-     * field is used to mark which queue a node is on.
-     *
-     * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
-     * Scherer and Michael Scott, along with members of JSR-166
-     * expert group, for helpful ideas, discussions, and critiques
-     * on the design of this class.
-     */
-    static final class Node {
-        /** Marker to indicate a node is waiting in shared mode */
-        static final Node SHARED = new Node();
-        /** Marker to indicate a node is waiting in exclusive mode */
-        static final Node EXCLUSIVE = null;
-
-        /** waitStatus value to indicate thread has cancelled */
-        static final int CANCELLED =  1;
-        /** waitStatus value to indicate successor's thread needs unparking */
-        static final int SIGNAL    = -1;
-        /** waitStatus value to indicate thread is waiting on condition */
-        static final int CONDITION = -2;
-        /**
-         * waitStatus value to indicate the next acquireShared should
-         * unconditionally propagate
-         */
-        static final int PROPAGATE = -3;
-
-        /**
-         * Status field, taking on only the values:
-         *   SIGNAL:     The successor of this node is (or will soon be)
-         *               blocked (via park), so the current node must
-         *               unpark its successor when it releases or
-         *               cancels. To avoid races, acquire methods must
-         *               first indicate they need a signal,
-         *               then retry the atomic acquire, and then,
-         *               on failure, block.
-         *   CANCELLED:  This node is cancelled due to timeout or interrupt.
-         *               Nodes never leave this state. In particular,
-         *               a thread with cancelled node never again blocks.
-         *   CONDITION:  This node is currently on a condition queue.
-         *               It will not be used as a sync queue node
-         *               until transferred, at which time the status
-         *               will be set to 0. (Use of this value here has
-         *               nothing to do with the other uses of the
-         *               field, but simplifies mechanics.)
-         *   PROPAGATE:  A releaseShared should be propagated to other
-         *               nodes. This is set (for head node only) in
-         *               doReleaseShared to ensure propagation
-         *               continues, even if other operations have
-         *               since intervened.
-         *   0:          None of the above
-         *
-         * The values are arranged numerically to simplify use.
-         * Non-negative values mean that a node doesn't need to
-         * signal. So, most code doesn't need to check for particular
-         * values, just for sign.
-         *
-         * The field is initialized to 0 for normal sync nodes, and
-         * CONDITION for condition nodes.  It is modified using CAS
-         * (or when possible, unconditional volatile writes).
-         */
-        volatile int waitStatus;
-
-        /**
-         * Link to predecessor node that current node/thread relies on
-         * for checking waitStatus. Assigned during enqueuing, and nulled
-         * out (for sake of GC) only upon dequeuing.  Also, upon
-         * cancellation of a predecessor, we short-circuit while
-         * finding a non-cancelled one, which will always exist
-         * because the head node is never cancelled: A node becomes
-         * head only as a result of successful acquire. A
-         * cancelled thread never succeeds in acquiring, and a thread only
-         * cancels itself, not any other node.
-         */
-        volatile Node prev;
-
-        /**
-         * Link to the successor node that the current node/thread
-         * unparks upon release. Assigned during enqueuing, adjusted
-         * when bypassing cancelled predecessors, and nulled out (for
-         * sake of GC) when dequeued.  The enq operation does not
-         * assign next field of a predecessor until after attachment,
-         * so seeing a null next field does not necessarily mean that
-         * node is at end of queue. However, if a next field appears
-         * to be null, we can scan prev's from the tail to
-         * double-check.  The next field of cancelled nodes is set to
-         * point to the node itself instead of null, to make life
-         * easier for isOnSyncQueue.
-         */
-        volatile Node next;
-
-        /**
-         * The thread that enqueued this node.  Initialized on
-         * construction and nulled out after use.
-         */
-        volatile Thread thread;
-
-        /**
-         * Link to next node waiting on condition, or the special
-         * value SHARED.  Because condition queues are accessed only
-         * when holding in exclusive mode, we just need a simple
-         * linked queue to hold nodes while they are waiting on
-         * conditions. They are then transferred to the queue to
-         * re-acquire. And because conditions can only be exclusive,
-         * we save a field by using special value to indicate shared
-         * mode.
-         */
-        Node nextWaiter;
-
-        /**
-         * Returns true if node is waiting in shared mode.
-         */
-        final boolean isShared() {
-            return nextWaiter == SHARED;
-        }
-
-        /**
-         * Returns previous node, or throws NullPointerException if null.
-         * Use when predecessor cannot be null.  The null check could
-         * be elided, but is present to help the VM.
-         *
-         * @return the predecessor of this node
-         */
-        final Node predecessor() throws NullPointerException {
-            Node p = prev;
-            if (p == null)
-                throw new NullPointerException();
-            else
-                return p;
-        }
-
-        Node() {    // Used to establish initial head or SHARED marker
-        }
-
-        Node(Thread thread, Node mode) {     // Used by addWaiter
-            this.nextWaiter = mode;
-            this.thread = thread;
-        }
-
-        Node(Thread thread, int waitStatus) { // Used by Condition
-            this.waitStatus = waitStatus;
-            this.thread = thread;
-        }
-    }
-
-    /**
      * Head of the wait queue, lazily initialized.  Except for
      * initialization, it is modified only via method setHead.  Note:
      * If head exists, its waitStatus is guaranteed not to be
@@ -325,7 +111,9 @@
      * @param newState the new state value
      */
     protected final void setState(long newState) {
-        state = newState;
+        // Use putLongVolatile instead of ordinary volatile store when
+        // using compareAndSwapLong, for sake of some 32bit systems.
+        U.putLongVolatile(this, STATE, newState);
     }
 
     /**
@@ -340,8 +128,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(long expect, long update) {
-        // See below for intrinsics setup to support this
-        return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
+        return U.compareAndSwapLong(this, STATE, expect, update);
     }
 
     // Queuing utilities
@@ -351,25 +138,24 @@
      * rather than to use timed park. A rough estimate suffices
      * to improve responsiveness with very short timeouts.
      */
-    static final long spinForTimeoutThreshold = 1000L;
+    static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
 
     /**
      * Inserts node into queue, initializing if necessary. See picture above.
      * @param node the node to insert
      * @return node's predecessor
      */
-    private Node enq(final Node node) {
+    private Node enq(Node node) {
         for (;;) {
-            Node t = tail;
-            if (t == null) { // Must initialize
-                if (compareAndSetHead(new Node()))
-                    tail = head;
+            Node oldTail = tail;
+            if (oldTail != null) {
+                U.putObject(node, Node.PREV, oldTail);
+                if (compareAndSetTail(oldTail, node)) {
+                    oldTail.next = node;
+                    return oldTail;
+                }
             } else {
-                node.prev = t;
-                if (compareAndSetTail(t, node)) {
-                    t.next = node;
-                    return t;
-                }
+                initializeSyncQueue();
             }
         }
     }
@@ -381,18 +167,20 @@
      * @return the new node
      */
     private Node addWaiter(Node mode) {
-        Node node = new Node(Thread.currentThread(), mode);
-        // Try the fast path of enq; backup to full enq on failure
-        Node pred = tail;
-        if (pred != null) {
-            node.prev = pred;
-            if (compareAndSetTail(pred, node)) {
-                pred.next = node;
-                return node;
+        Node node = new Node(mode);
+
+        for (;;) {
+            Node oldTail = tail;
+            if (oldTail != null) {
+                U.putObject(node, Node.PREV, oldTail);
+                if (compareAndSetTail(oldTail, node)) {
+                    oldTail.next = node;
+                    return node;
+                }
+            } else {
+                initializeSyncQueue();
             }
         }
-        enq(node);
-        return node;
     }
 
     /**
@@ -421,7 +209,7 @@
          */
         int ws = node.waitStatus;
         if (ws < 0)
-            compareAndSetWaitStatus(node, ws, 0);
+            node.compareAndSetWaitStatus(ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -432,9 +220,9 @@
         Node s = node.next;
         if (s == null || s.waitStatus > 0) {
             s = null;
-            for (Node t = tail; t != null && t != node; t = t.prev)
-                if (t.waitStatus <= 0)
-                    s = t;
+            for (Node p = tail; p != node && p != null; p = p.prev)
+                if (p.waitStatus <= 0)
+                    s = p;
         }
         if (s != null)
             LockSupport.unpark(s.thread);
@@ -462,12 +250,12 @@
             if (h != null && h != tail) {
                 int ws = h.waitStatus;
                 if (ws == Node.SIGNAL) {
-                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+                    if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
                         continue;            // loop to recheck cases
                     unparkSuccessor(h);
                 }
                 else if (ws == 0 &&
-                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+                         !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
                     continue;                // loop on failed CAS
             }
             if (h == head)                   // loop if head changed
@@ -541,18 +329,18 @@
 
         // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
-            compareAndSetNext(pred, predNext, null);
+            pred.compareAndSetNext(predNext, null);
         } else {
             // If successor needs signal, try to set pred's next-link
             // so it will get one. Otherwise wake it up to propagate.
             int ws;
             if (pred != head &&
                 ((ws = pred.waitStatus) == Node.SIGNAL ||
-                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+                 (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
                 pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
-                    compareAndSetNext(pred, predNext, next);
+                    pred.compareAndSetNext(predNext, next);
             } else {
                 unparkSuccessor(node);
             }
@@ -593,7 +381,7 @@
              * need a signal, but don't park yet.  Caller will need to
              * retry to make sure it cannot acquire before parking.
              */
-            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
         }
         return false;
     }
@@ -606,7 +394,7 @@
     }
 
     /**
-     * Convenience method to park and then check if interrupted
+     * Convenience method to park and then check if interrupted.
      *
      * @return {@code true} if interrupted
      */
@@ -633,7 +421,6 @@
      * @return {@code true} if interrupted while waiting
      */
     final boolean acquireQueued(final Node node, long arg) {
-        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -641,16 +428,15 @@
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return interrupted;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -661,23 +447,21 @@
     private void doAcquireInterruptibly(long arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.EXCLUSIVE);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -694,28 +478,28 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.EXCLUSIVE);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return true;
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L)
+                if (nanosTimeout <= 0L) {
+                    cancelAcquire(node);
                     return false;
+                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > spinForTimeoutThreshold)
+                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -725,7 +509,6 @@
      */
     private void doAcquireShared(long arg) {
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -737,7 +520,6 @@
                         p.next = null; // help GC
                         if (interrupted)
                             selfInterrupt();
-                        failed = false;
                         return;
                     }
                 }
@@ -745,9 +527,9 @@
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -758,7 +540,6 @@
     private void doAcquireSharedInterruptibly(long arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -767,7 +548,6 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        failed = false;
                         return;
                     }
                 }
@@ -775,9 +555,9 @@
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -794,7 +574,6 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -803,22 +582,23 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        failed = false;
                         return true;
                     }
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L)
+                if (nanosTimeout <= 0L) {
+                    cancelAcquire(node);
                     return false;
+                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > spinForTimeoutThreshold)
+                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -1170,7 +950,7 @@
     }
 
     /**
-     * Version of getFirstQueuedThread called when fastpath fails
+     * Version of getFirstQueuedThread called when fastpath fails.
      */
     private Thread fullGetFirstQueuedThread() {
         /*
@@ -1250,7 +1030,7 @@
      *
      * <p>An invocation of this method is equivalent to (but may be
      * more efficient than):
-     *  <pre> {@code
+     * <pre> {@code
      * getFirstQueuedThread() != Thread.currentThread() &&
      * hasQueuedThreads()}</pre>
      *
@@ -1270,7 +1050,7 @@
      * tryAcquire} method for a fair, reentrant, exclusive mode
      * synchronizer might look like this:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * protected boolean tryAcquire(int arg) {
      *   if (isHeldExclusively()) {
      *     // A reentrant acquire; increment hold count
@@ -1306,8 +1086,7 @@
      * acquire.  The value is only an estimate because the number of
      * threads may change dynamically while this method traverses
      * internal data structures.  This method is designed for use in
-     * monitoring system state, not for synchronization
-     * control.
+     * monitoring system state, not for synchronization control.
      *
      * @return the estimated number of threads waiting to acquire
      */
@@ -1332,7 +1111,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             Thread t = p.thread;
             if (t != null)
@@ -1350,7 +1129,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (!p.isShared()) {
                 Thread t = p.thread;
@@ -1370,7 +1149,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getSharedQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (p.isShared()) {
                 Thread t = p.thread;
@@ -1391,10 +1170,9 @@
      * @return a string identifying this synchronizer, as well as its state
      */
     public String toString() {
-        long s = getState();
-        String q  = hasQueuedThreads() ? "non" : "";
-        return super.toString() +
-            "[State = " + s + ", " + q + "empty queue]";
+        return super.toString()
+            + "[State = " + getState() + ", "
+            + (hasQueuedThreads() ? "non" : "") + "empty queue]";
     }
 
 
@@ -1428,13 +1206,15 @@
      * @return true if present
      */
     private boolean findNodeFromTail(Node node) {
-        Node t = tail;
-        for (;;) {
-            if (t == node)
+        // We check for node first, since it's likely to be at or near tail.
+        // tail is known to be non-null, so we could re-order to "save"
+        // one null check, but we leave it this way to help the VM.
+        for (Node p = tail;;) {
+            if (p == node)
                 return true;
-            if (t == null)
+            if (p == null)
                 return false;
-            t = t.prev;
+            p = p.prev;
         }
     }
 
@@ -1449,7 +1229,7 @@
         /*
          * If cannot change waitStatus, the node has been cancelled.
          */
-        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+        if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
             return false;
 
         /*
@@ -1460,7 +1240,7 @@
          */
         Node p = enq(node);
         int ws = p.waitStatus;
-        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
+        if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
@@ -1473,7 +1253,7 @@
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
-        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+        if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
             enq(node);
             return true;
         }
@@ -1495,18 +1275,14 @@
      * @return previous sync state
      */
     final long fullyRelease(Node node) {
-        boolean failed = true;
         try {
             long savedState = getState();
-            if (release(savedState)) {
-                failed = false;
+            if (release(savedState))
                 return savedState;
-            } else {
-                throw new IllegalMonitorStateException();
-            }
-        } finally {
-            if (failed)
-                node.waitStatus = Node.CANCELLED;
+            throw new IllegalMonitorStateException();
+        } catch (Throwable t) {
+            node.waitStatus = Node.CANCELLED;
+            throw t;
         }
     }
 
@@ -1551,8 +1327,8 @@
      * given condition associated with this synchronizer. Note that
      * because timeouts and interrupts may occur at any time, the
      * estimate serves only as an upper bound on the actual number of
-     * waiters.  This method is designed for use in monitoring of the
-     * system state, not for synchronization control.
+     * waiters.  This method is designed for use in monitoring system
+     * state, not for synchronization control.
      *
      * @param condition the condition
      * @return the estimated number of waiting threads
@@ -1632,7 +1408,9 @@
                 unlinkCancelledWaiters();
                 t = lastWaiter;
             }
-            Node node = new Node(Thread.currentThread(), Node.CONDITION);
+
+            Node node = new Node(Node.CONDITION);
+
             if (t == null)
                 firstWaiter = node;
             else
@@ -1740,12 +1518,12 @@
         /**
          * Implements uninterruptible condition wait.
          * <ol>
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
          * </ol>
          */
         public final void awaitUninterruptibly() {
@@ -1799,14 +1577,14 @@
         /**
          * Implements interruptible condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled or interrupted.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled or interrupted.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
          */
         public final void await() throws InterruptedException {
@@ -1831,30 +1609,33 @@
         /**
          * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
          */
         public final long awaitNanos(long nanosTimeout)
                 throws InterruptedException {
             if (Thread.interrupted())
                 throw new InterruptedException();
+            // We don't check for nanosTimeout <= 0L here, to allow
+            // awaitNanos(0) as a way to "yield the lock".
+            final long deadline = System.nanoTime() + nanosTimeout;
+            long initialNanos = nanosTimeout;
             Node node = addConditionWaiter();
             long savedState = fullyRelease(node);
-            final long deadline = System.nanoTime() + nanosTimeout;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
                     transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout >= spinForTimeoutThreshold)
+                if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -1866,21 +1647,22 @@
                 unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
-            return deadline - System.nanoTime();
+            long remaining = deadline - System.nanoTime(); // avoid overflow
+            return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
         }
 
         /**
          * Implements absolute timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
-         * <li> If timed out while blocked in step 4, return false, else true.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If timed out while blocked in step 4, return false, else true.
          * </ol>
          */
         public final boolean awaitUntil(Date deadline)
@@ -1893,7 +1675,7 @@
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
-                if (System.currentTimeMillis() > abstime) {
+                if (System.currentTimeMillis() >= abstime) {
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
@@ -1913,15 +1695,15 @@
         /**
          * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
-         * <li> If timed out while blocked in step 4, return false, else true.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If timed out while blocked in step 4, return false, else true.
          * </ol>
          */
         public final boolean await(long time, TimeUnit unit)
@@ -1929,9 +1711,11 @@
             long nanosTimeout = unit.toNanos(time);
             if (Thread.interrupted())
                 throw new InterruptedException();
+            // We don't check for nanosTimeout <= 0L here, to allow
+            // await(0, unit) as a way to "yield the lock".
+            final long deadline = System.nanoTime() + nanosTimeout;
             Node node = addConditionWaiter();
             long savedState = fullyRelease(node);
-            final long deadline = System.nanoTime() + nanosTimeout;
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
@@ -1939,7 +1723,7 @@
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout >= spinForTimeoutThreshold)
+                if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -2016,7 +1800,7 @@
         protected final Collection<Thread> getWaitingThreads() {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
-            ArrayList<Thread> list = new ArrayList<Thread>();
+            ArrayList<Thread> list = new ArrayList<>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION) {
                     Thread t = w.thread;
@@ -2037,59 +1821,40 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-    private static final long stateOffset;
-    private static final long headOffset;
-    private static final long tailOffset;
-    private static final long waitStatusOffset;
-    private static final long nextOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long STATE;
+    private static final long HEAD;
+    private static final long TAIL;
 
     static {
         try {
-            stateOffset = unsafe.objectFieldOffset
+            STATE = U.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
-            headOffset = unsafe.objectFieldOffset
+            HEAD = U.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
-            tailOffset = unsafe.objectFieldOffset
+            TAIL = U.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
-            waitStatusOffset = unsafe.objectFieldOffset
-                (Node.class.getDeclaredField("waitStatus"));
-            nextOffset = unsafe.objectFieldOffset
-                (Node.class.getDeclaredField("next"));
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
 
-        } catch (Exception ex) { throw new Error(ex); }
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 
     /**
-     * CAS head field. Used only by enq.
+     * Initializes head and tail fields on first contention.
      */
-    private final boolean compareAndSetHead(Node update) {
-        return unsafe.compareAndSwapObject(this, headOffset, null, update);
-    }
-
-    /**
-     * CAS tail field. Used only by enq.
-     */
-    private final boolean compareAndSetTail(Node expect, Node update) {
-        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+    private final void initializeSyncQueue() {
+        if (U.compareAndSwapObject(this, HEAD, null, new Node()))
+            tail = head;
     }
 
     /**
-     * CAS waitStatus field of a node.
+     * CASes tail field.
      */
-    private static final boolean compareAndSetWaitStatus(Node node,
-                                                         int expect,
-                                                         int update) {
-        return unsafe.compareAndSwapInt(node, waitStatusOffset,
-                                        expect, update);
-    }
-
-    /**
-     * CAS next field of a node.
-     */
-    private static final boolean compareAndSetNext(Node node,
-                                                   Node expect,
-                                                   Node update) {
-        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+    private final boolean compareAndSetTail(Node expect, Node update) {
+        return U.compareAndSwapObject(this, TAIL, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,11 +34,11 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.concurrent.TimeUnit;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
-import sun.misc.Unsafe;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Provides a framework for implementing blocking locks and related
@@ -110,11 +110,11 @@
  * #setState} and/or {@link #compareAndSetState}:
  *
  * <ul>
- * <li> {@link #tryAcquire}
- * <li> {@link #tryRelease}
- * <li> {@link #tryAcquireShared}
- * <li> {@link #tryReleaseShared}
- * <li> {@link #isHeldExclusively}
+ * <li>{@link #tryAcquire}
+ * <li>{@link #tryRelease}
+ * <li>{@link #tryAcquireShared}
+ * <li>{@link #tryReleaseShared}
+ * <li>{@link #isHeldExclusively}
  * </ul>
  *
  * Each of these methods by default throws {@link
@@ -195,7 +195,7 @@
  * It also supports conditions and exposes
  * one of the instrumentation methods:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class Mutex implements Lock, java.io.Serializable {
  *
  *   // Our internal helper class
@@ -259,7 +259,7 @@
  * fire. Because a latch is non-exclusive, it uses the {@code shared}
  * acquire and release methods.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class BooleanLatch {
  *
  *   private static class Sync extends AbstractQueuedSynchronizer {
@@ -383,15 +383,15 @@
         /** Marker to indicate a node is waiting in exclusive mode */
         static final Node EXCLUSIVE = null;
 
-        /** waitStatus value to indicate thread has cancelled */
+        /** waitStatus value to indicate thread has cancelled. */
         static final int CANCELLED =  1;
-        /** waitStatus value to indicate successor's thread needs unparking */
+        /** waitStatus value to indicate successor's thread needs unparking. */
         static final int SIGNAL    = -1;
-        /** waitStatus value to indicate thread is waiting on condition */
+        /** waitStatus value to indicate thread is waiting on condition. */
         static final int CONDITION = -2;
         /**
          * waitStatus value to indicate the next acquireShared should
-         * unconditionally propagate
+         * unconditionally propagate.
          */
         static final int PROPAGATE = -3;
 
@@ -499,17 +499,49 @@
                 return p;
         }
 
-        Node() {    // Used to establish initial head or SHARED marker
+        /** Establishes initial head or SHARED marker. */
+        Node() {}
+
+        /** Constructor used by addWaiter. */
+        Node(Node nextWaiter) {
+            this.nextWaiter = nextWaiter;
+            U.putObject(this, THREAD, Thread.currentThread());
+        }
+
+        /** Constructor used by addConditionWaiter. */
+        Node(int waitStatus) {
+            U.putInt(this, WAITSTATUS, waitStatus);
+            U.putObject(this, THREAD, Thread.currentThread());
+        }
+
+        /** CASes waitStatus field. */
+        final boolean compareAndSetWaitStatus(int expect, int update) {
+            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
         }
 
-        Node(Thread thread, Node mode) {     // Used by addWaiter
-            this.nextWaiter = mode;
-            this.thread = thread;
+        /** CASes next field. */
+        final boolean compareAndSetNext(Node expect, Node update) {
+            return U.compareAndSwapObject(this, NEXT, expect, update);
         }
 
-        Node(Thread thread, int waitStatus) { // Used by Condition
-            this.waitStatus = waitStatus;
-            this.thread = thread;
+        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final long NEXT;
+        static final long PREV;
+        private static final long THREAD;
+        private static final long WAITSTATUS;
+        static {
+            try {
+                NEXT = U.objectFieldOffset
+                    (Node.class.getDeclaredField("next"));
+                PREV = U.objectFieldOffset
+                    (Node.class.getDeclaredField("prev"));
+                THREAD = U.objectFieldOffset
+                    (Node.class.getDeclaredField("thread"));
+                WAITSTATUS = U.objectFieldOffset
+                    (Node.class.getDeclaredField("waitStatus"));
+            } catch (ReflectiveOperationException e) {
+                throw new Error(e);
+            }
         }
     }
 
@@ -562,8 +594,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
-        // See below for intrinsics setup to support this
-        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
+        return U.compareAndSwapInt(this, STATE, expect, update);
     }
 
     // Queuing utilities
@@ -573,25 +604,24 @@
      * rather than to use timed park. A rough estimate suffices
      * to improve responsiveness with very short timeouts.
      */
-    static final long spinForTimeoutThreshold = 1000L;
+    static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
 
     /**
      * Inserts node into queue, initializing if necessary. See picture above.
      * @param node the node to insert
      * @return node's predecessor
      */
-    private Node enq(final Node node) {
+    private Node enq(Node node) {
         for (;;) {
-            Node t = tail;
-            if (t == null) { // Must initialize
-                if (compareAndSetHead(new Node()))
-                    tail = head;
+            Node oldTail = tail;
+            if (oldTail != null) {
+                U.putObject(node, Node.PREV, oldTail);
+                if (compareAndSetTail(oldTail, node)) {
+                    oldTail.next = node;
+                    return oldTail;
+                }
             } else {
-                node.prev = t;
-                if (compareAndSetTail(t, node)) {
-                    t.next = node;
-                    return t;
-                }
+                initializeSyncQueue();
             }
         }
     }
@@ -603,18 +633,20 @@
      * @return the new node
      */
     private Node addWaiter(Node mode) {
-        Node node = new Node(Thread.currentThread(), mode);
-        // Try the fast path of enq; backup to full enq on failure
-        Node pred = tail;
-        if (pred != null) {
-            node.prev = pred;
-            if (compareAndSetTail(pred, node)) {
-                pred.next = node;
-                return node;
+        Node node = new Node(mode);
+
+        for (;;) {
+            Node oldTail = tail;
+            if (oldTail != null) {
+                U.putObject(node, Node.PREV, oldTail);
+                if (compareAndSetTail(oldTail, node)) {
+                    oldTail.next = node;
+                    return node;
+                }
+            } else {
+                initializeSyncQueue();
             }
         }
-        enq(node);
-        return node;
     }
 
     /**
@@ -643,7 +675,7 @@
          */
         int ws = node.waitStatus;
         if (ws < 0)
-            compareAndSetWaitStatus(node, ws, 0);
+            node.compareAndSetWaitStatus(ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -654,9 +686,9 @@
         Node s = node.next;
         if (s == null || s.waitStatus > 0) {
             s = null;
-            for (Node t = tail; t != null && t != node; t = t.prev)
-                if (t.waitStatus <= 0)
-                    s = t;
+            for (Node p = tail; p != node && p != null; p = p.prev)
+                if (p.waitStatus <= 0)
+                    s = p;
         }
         if (s != null)
             LockSupport.unpark(s.thread);
@@ -684,12 +716,12 @@
             if (h != null && h != tail) {
                 int ws = h.waitStatus;
                 if (ws == Node.SIGNAL) {
-                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+                    if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
                         continue;            // loop to recheck cases
                     unparkSuccessor(h);
                 }
                 else if (ws == 0 &&
-                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+                         !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
                     continue;                // loop on failed CAS
             }
             if (h == head)                   // loop if head changed
@@ -763,18 +795,18 @@
 
         // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
-            compareAndSetNext(pred, predNext, null);
+            pred.compareAndSetNext(predNext, null);
         } else {
             // If successor needs signal, try to set pred's next-link
             // so it will get one. Otherwise wake it up to propagate.
             int ws;
             if (pred != head &&
                 ((ws = pred.waitStatus) == Node.SIGNAL ||
-                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+                 (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
                 pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
-                    compareAndSetNext(pred, predNext, next);
+                    pred.compareAndSetNext(predNext, next);
             } else {
                 unparkSuccessor(node);
             }
@@ -815,7 +847,7 @@
              * need a signal, but don't park yet.  Caller will need to
              * retry to make sure it cannot acquire before parking.
              */
-            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
         }
         return false;
     }
@@ -828,7 +860,7 @@
     }
 
     /**
-     * Convenience method to park and then check if interrupted
+     * Convenience method to park and then check if interrupted.
      *
      * @return {@code true} if interrupted
      */
@@ -855,7 +887,6 @@
      * @return {@code true} if interrupted while waiting
      */
     final boolean acquireQueued(final Node node, int arg) {
-        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -863,16 +894,15 @@
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return interrupted;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -883,23 +913,21 @@
     private void doAcquireInterruptibly(int arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.EXCLUSIVE);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -916,28 +944,28 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.EXCLUSIVE);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
-                    failed = false;
                     return true;
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L)
+                if (nanosTimeout <= 0L) {
+                    cancelAcquire(node);
                     return false;
+                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > spinForTimeoutThreshold)
+                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -947,7 +975,6 @@
      */
     private void doAcquireShared(int arg) {
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -959,7 +986,6 @@
                         p.next = null; // help GC
                         if (interrupted)
                             selfInterrupt();
-                        failed = false;
                         return;
                     }
                 }
@@ -967,9 +993,9 @@
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -980,7 +1006,6 @@
     private void doAcquireSharedInterruptibly(int arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -989,7 +1014,6 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        failed = false;
                         return;
                     }
                 }
@@ -997,9 +1021,9 @@
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -1016,7 +1040,6 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
-        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -1025,22 +1048,23 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        failed = false;
                         return true;
                     }
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L)
+                if (nanosTimeout <= 0L) {
+                    cancelAcquire(node);
                     return false;
+                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > spinForTimeoutThreshold)
+                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } finally {
-            if (failed)
-                cancelAcquire(node);
+        } catch (Throwable t) {
+            cancelAcquire(node);
+            throw t;
         }
     }
 
@@ -1392,7 +1416,7 @@
     }
 
     /**
-     * Version of getFirstQueuedThread called when fastpath fails
+     * Version of getFirstQueuedThread called when fastpath fails.
      */
     private Thread fullGetFirstQueuedThread() {
         /*
@@ -1472,7 +1496,7 @@
      *
      * <p>An invocation of this method is equivalent to (but may be
      * more efficient than):
-     *  <pre> {@code
+     * <pre> {@code
      * getFirstQueuedThread() != Thread.currentThread() &&
      * hasQueuedThreads()}</pre>
      *
@@ -1492,7 +1516,7 @@
      * tryAcquire} method for a fair, reentrant, exclusive mode
      * synchronizer might look like this:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * protected boolean tryAcquire(int arg) {
      *   if (isHeldExclusively()) {
      *     // A reentrant acquire; increment hold count
@@ -1528,8 +1552,7 @@
      * acquire.  The value is only an estimate because the number of
      * threads may change dynamically while this method traverses
      * internal data structures.  This method is designed for use in
-     * monitoring system state, not for synchronization
-     * control.
+     * monitoring system state, not for synchronization control.
      *
      * @return the estimated number of threads waiting to acquire
      */
@@ -1554,7 +1577,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             Thread t = p.thread;
             if (t != null)
@@ -1572,7 +1595,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (!p.isShared()) {
                 Thread t = p.thread;
@@ -1592,7 +1615,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getSharedQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<Thread>();
+        ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (p.isShared()) {
                 Thread t = p.thread;
@@ -1613,10 +1636,9 @@
      * @return a string identifying this synchronizer, as well as its state
      */
     public String toString() {
-        int s = getState();
-        String q  = hasQueuedThreads() ? "non" : "";
-        return super.toString() +
-            "[State = " + s + ", " + q + "empty queue]";
+        return super.toString()
+            + "[State = " + getState() + ", "
+            + (hasQueuedThreads() ? "non" : "") + "empty queue]";
     }
 
 
@@ -1650,13 +1672,15 @@
      * @return true if present
      */
     private boolean findNodeFromTail(Node node) {
-        Node t = tail;
-        for (;;) {
-            if (t == node)
+        // We check for node first, since it's likely to be at or near tail.
+        // tail is known to be non-null, so we could re-order to "save"
+        // one null check, but we leave it this way to help the VM.
+        for (Node p = tail;;) {
+            if (p == node)
                 return true;
-            if (t == null)
+            if (p == null)
                 return false;
-            t = t.prev;
+            p = p.prev;
         }
     }
 
@@ -1671,7 +1695,7 @@
         /*
          * If cannot change waitStatus, the node has been cancelled.
          */
-        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+        if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
             return false;
 
         /*
@@ -1682,7 +1706,7 @@
          */
         Node p = enq(node);
         int ws = p.waitStatus;
-        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
+        if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
@@ -1695,7 +1719,7 @@
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
-        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+        if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
             enq(node);
             return true;
         }
@@ -1717,18 +1741,14 @@
      * @return previous sync state
      */
     final int fullyRelease(Node node) {
-        boolean failed = true;
         try {
             int savedState = getState();
-            if (release(savedState)) {
-                failed = false;
+            if (release(savedState))
                 return savedState;
-            } else {
-                throw new IllegalMonitorStateException();
-            }
-        } finally {
-            if (failed)
-                node.waitStatus = Node.CANCELLED;
+            throw new IllegalMonitorStateException();
+        } catch (Throwable t) {
+            node.waitStatus = Node.CANCELLED;
+            throw t;
         }
     }
 
@@ -1773,8 +1793,8 @@
      * given condition associated with this synchronizer. Note that
      * because timeouts and interrupts may occur at any time, the
      * estimate serves only as an upper bound on the actual number of
-     * waiters.  This method is designed for use in monitoring of the
-     * system state, not for synchronization control.
+     * waiters.  This method is designed for use in monitoring system
+     * state, not for synchronization control.
      *
      * @param condition the condition
      * @return the estimated number of waiting threads
@@ -1852,7 +1872,9 @@
                 unlinkCancelledWaiters();
                 t = lastWaiter;
             }
-            Node node = new Node(Thread.currentThread(), Node.CONDITION);
+
+            Node node = new Node(Node.CONDITION);
+
             if (t == null)
                 firstWaiter = node;
             else
@@ -1960,12 +1982,12 @@
         /**
          * Implements uninterruptible condition wait.
          * <ol>
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
          * </ol>
          */
         public final void awaitUninterruptibly() {
@@ -2019,14 +2041,14 @@
         /**
          * Implements interruptible condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled or interrupted.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled or interrupted.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
          */
         public final void await() throws InterruptedException {
@@ -2051,30 +2073,33 @@
         /**
          * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
          */
         public final long awaitNanos(long nanosTimeout)
                 throws InterruptedException {
             if (Thread.interrupted())
                 throw new InterruptedException();
+            // We don't check for nanosTimeout <= 0L here, to allow
+            // awaitNanos(0) as a way to "yield the lock".
+            final long deadline = System.nanoTime() + nanosTimeout;
+            long initialNanos = nanosTimeout;
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
-            final long deadline = System.nanoTime() + nanosTimeout;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
                     transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout >= spinForTimeoutThreshold)
+                if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -2086,21 +2111,22 @@
                 unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
-            return deadline - System.nanoTime();
+            long remaining = deadline - System.nanoTime(); // avoid overflow
+            return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
         }
 
         /**
          * Implements absolute timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
-         * <li> If timed out while blocked in step 4, return false, else true.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If timed out while blocked in step 4, return false, else true.
          * </ol>
          */
         public final boolean awaitUntil(Date deadline)
@@ -2113,7 +2139,7 @@
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
-                if (System.currentTimeMillis() > abstime) {
+                if (System.currentTimeMillis() >= abstime) {
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
@@ -2133,15 +2159,15 @@
         /**
          * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException.
-         * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with saved state as argument,
-         *      throwing IllegalMonitorStateException if it fails.
-         * <li> Block until signalled, interrupted, or timed out.
-         * <li> Reacquire by invoking specialized version of
-         *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException.
-         * <li> If timed out while blocked in step 4, return false, else true.
+         * <li>If current thread is interrupted, throw InterruptedException.
+         * <li>Save lock state returned by {@link #getState}.
+         * <li>Invoke {@link #release} with saved state as argument,
+         *     throwing IllegalMonitorStateException if it fails.
+         * <li>Block until signalled, interrupted, or timed out.
+         * <li>Reacquire by invoking specialized version of
+         *     {@link #acquire} with saved state as argument.
+         * <li>If interrupted while blocked in step 4, throw InterruptedException.
+         * <li>If timed out while blocked in step 4, return false, else true.
          * </ol>
          */
         public final boolean await(long time, TimeUnit unit)
@@ -2149,9 +2175,11 @@
             long nanosTimeout = unit.toNanos(time);
             if (Thread.interrupted())
                 throw new InterruptedException();
+            // We don't check for nanosTimeout <= 0L here, to allow
+            // await(0, unit) as a way to "yield the lock".
+            final long deadline = System.nanoTime() + nanosTimeout;
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
-            final long deadline = System.nanoTime() + nanosTimeout;
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
@@ -2159,7 +2187,7 @@
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout >= spinForTimeoutThreshold)
+                if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -2236,7 +2264,7 @@
         protected final Collection<Thread> getWaitingThreads() {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
-            ArrayList<Thread> list = new ArrayList<Thread>();
+            ArrayList<Thread> list = new ArrayList<>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION) {
                     Thread t = w.thread;
@@ -2257,59 +2285,40 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-    private static final long stateOffset;
-    private static final long headOffset;
-    private static final long tailOffset;
-    private static final long waitStatusOffset;
-    private static final long nextOffset;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long STATE;
+    private static final long HEAD;
+    private static final long TAIL;
 
     static {
         try {
-            stateOffset = unsafe.objectFieldOffset
+            STATE = U.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
-            headOffset = unsafe.objectFieldOffset
+            HEAD = U.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
-            tailOffset = unsafe.objectFieldOffset
+            TAIL = U.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
-            waitStatusOffset = unsafe.objectFieldOffset
-                (Node.class.getDeclaredField("waitStatus"));
-            nextOffset = unsafe.objectFieldOffset
-                (Node.class.getDeclaredField("next"));
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
 
-        } catch (Exception ex) { throw new Error(ex); }
+        // Reduce the risk of rare disastrous classloading in first call to
+        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+        Class<?> ensureLoaded = LockSupport.class;
     }
 
     /**
-     * CAS head field. Used only by enq.
+     * Initializes head and tail fields on first contention.
      */
-    private final boolean compareAndSetHead(Node update) {
-        return unsafe.compareAndSwapObject(this, headOffset, null, update);
-    }
-
-    /**
-     * CAS tail field. Used only by enq.
-     */
-    private final boolean compareAndSetTail(Node expect, Node update) {
-        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+    private final void initializeSyncQueue() {
+        if (U.compareAndSwapObject(this, HEAD, null, new Node()))
+            tail = head;
     }
 
     /**
-     * CAS waitStatus field of a node.
+     * CASes tail field.
      */
-    private static final boolean compareAndSetWaitStatus(Node node,
-                                                         int expect,
-                                                         int update) {
-        return unsafe.compareAndSwapInt(node, waitStatusOffset,
-                                        expect, update);
-    }
-
-    /**
-     * CAS next field of a node.
-     */
-    private static final boolean compareAndSetNext(Node node,
-                                                   Node expect,
-                                                   Node update) {
-        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+    private final boolean compareAndSetTail(Node expect, Node update) {
+        return U.compareAndSwapObject(this, TAIL, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,8 +34,9 @@
  */
 
 package java.util.concurrent.locks;
+
+import java.util.Date;
 import java.util.concurrent.TimeUnit;
-import java.util.Date;
 
 /**
  * {@code Condition} factors out the {@code Object} monitor
@@ -126,7 +127,7 @@
  * <p>Note that {@code Condition} instances are just normal objects and can
  * themselves be used as the target in a {@code synchronized} statement,
  * and can have their own monitor {@link Object#wait wait} and
- * {@link Object#notify notification} methods invoked.
+ * {@link Object#notify notify} methods invoked.
  * Acquiring the monitor lock of a {@code Condition} instance, or using its
  * monitor methods, has no specified relationship with acquiring the
  * {@link Lock} associated with that {@code Condition} or the use of its
@@ -308,7 +309,7 @@
      * condition still does not hold. Typical uses of this method take
      * the following form:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * boolean aMethod(long timeout, TimeUnit unit) {
      *   long nanos = unit.toNanos(timeout);
      *   lock.lock();
@@ -361,7 +362,7 @@
      * Causes the current thread to wait until it is signalled or interrupted,
      * or the specified waiting time elapses. This method is behaviorally
      * equivalent to:
-     *  <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
+     * <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
      *
      * @param time the maximum time to wait
      * @param unit the time unit of the {@code time} argument
@@ -410,7 +411,7 @@
      *
      * <p>The return value indicates whether the deadline has elapsed,
      * which can be used as follows:
-     *  <pre> {@code
+     * <pre> {@code
      * boolean aMethod(Date deadline) {
      *   boolean stillWaiting = true;
      *   lock.lock();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,6 +34,7 @@
  */
 
 package java.util.concurrent.locks;
+
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -77,7 +78,7 @@
  * methods and statements. In most cases, the following idiom
  * should be used:
  *
- *  <pre> {@code
+ * <pre> {@code
  * Lock l = ...;
  * l.lock();
  * try {
@@ -121,8 +122,9 @@
  * <p>All {@code Lock} implementations <em>must</em> enforce the same
  * memory synchronization semantics as provided by the built-in monitor
  * lock, as described in
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
- * The Java Language Specification (17.4 Memory Model)</a>:
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * Chapter 17 of
+ * <cite>The Java&trade; Language Specification</cite></a>:
  * <ul>
  * <li>A successful {@code lock} operation has the same memory
  * synchronization effects as a successful <em>Lock</em> action.
@@ -240,7 +242,7 @@
      * immediately with the value {@code false}.
      *
      * <p>A typical usage idiom for this method would be:
-     *  <pre> {@code
+     * <pre> {@code
      * Lock lock = ...;
      * if (lock.tryLock()) {
      *   try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,7 +34,6 @@
  */
 
 package java.util.concurrent.locks;
-import sun.misc.Unsafe;
 
 /**
  * Basic thread blocking primitives for creating locks and other
@@ -47,6 +46,10 @@
  * it <em>may</em> block.  A call to {@code unpark} makes the permit
  * available, if it was not already available. (Unlike with Semaphores
  * though, permits do not accumulate. There is at most one.)
+ * Reliable usage requires the use of volatile (or atomic) variables
+ * to control when to park or unpark.  Orderings of calls to these
+ * methods are maintained with respect to volatile variable accesses,
+ * but not necessarily non-volatile variable accesses.
  *
  * <p>Methods {@code park} and {@code unpark} provide efficient
  * means of blocking and unblocking threads that do not encounter the
@@ -77,7 +80,7 @@
  * useful for most concurrency control applications.  The {@code park}
  * method is designed for use only in constructions of the form:
  *
- *  <pre> {@code
+ * <pre> {@code
  * while (!canProceed()) { ... LockSupport.park(this); }}</pre>
  *
  * where neither {@code canProceed} nor any other actions prior to the
@@ -87,11 +90,11 @@
  *
  * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
  * non-reentrant lock class:
- *  <pre> {@code
+ * <pre> {@code
  * class FIFOMutex {
  *   private final AtomicBoolean locked = new AtomicBoolean(false);
  *   private final Queue<Thread> waiters
- *     = new ConcurrentLinkedQueue<Thread>();
+ *     = new ConcurrentLinkedQueue<>();
  *
  *   public void lock() {
  *     boolean wasInterrupted = false;
@@ -122,7 +125,7 @@
 
     private static void setBlocker(Thread t, Object arg) {
         // Even though volatile, hotspot doesn't need a write barrier here.
-        UNSAFE.putObject(t, parkBlockerOffset, arg);
+        U.putObject(t, PARKBLOCKER, arg);
     }
 
     /**
@@ -138,7 +141,7 @@
      */
     public static void unpark(Thread thread) {
         if (thread != null)
-            UNSAFE.unpark(thread);
+            U.unpark(thread);
     }
 
     /**
@@ -172,7 +175,7 @@
     public static void park(Object blocker) {
         Thread t = Thread.currentThread();
         setBlocker(t, blocker);
-        UNSAFE.park(false, 0L);
+        U.park(false, 0L);
         setBlocker(t, null);
     }
 
@@ -212,7 +215,7 @@
         if (nanos > 0) {
             Thread t = Thread.currentThread();
             setBlocker(t, blocker);
-            UNSAFE.park(false, nanos);
+            U.park(false, nanos);
             setBlocker(t, null);
         }
     }
@@ -253,7 +256,7 @@
     public static void parkUntil(Object blocker, long deadline) {
         Thread t = Thread.currentThread();
         setBlocker(t, blocker);
-        UNSAFE.park(true, deadline);
+        U.park(true, deadline);
         setBlocker(t, null);
     }
 
@@ -272,7 +275,7 @@
     public static Object getBlocker(Thread t) {
         if (t == null)
             throw new NullPointerException();
-        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
+        return U.getObjectVolatile(t, PARKBLOCKER);
     }
 
     /**
@@ -301,7 +304,7 @@
      * for example, the interrupt status of the thread upon return.
      */
     public static void park() {
-        UNSAFE.park(false, 0L);
+        U.park(false, 0L);
     }
 
     /**
@@ -335,7 +338,7 @@
      */
     public static void parkNanos(long nanos) {
         if (nanos > 0)
-            UNSAFE.park(false, nanos);
+            U.park(false, nanos);
     }
 
     /**
@@ -369,7 +372,7 @@
      *        to wait until
      */
     public static void parkUntil(long deadline) {
-        UNSAFE.park(true, deadline);
+        U.park(true, deadline);
     }
 
     /**
@@ -379,36 +382,30 @@
     static final int nextSecondarySeed() {
         int r;
         Thread t = Thread.currentThread();
-        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
+        if ((r = U.getInt(t, SECONDARY)) != 0) {
             r ^= r << 13;   // xorshift
             r ^= r >>> 17;
             r ^= r << 5;
         }
         else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
             r = 1; // avoid zero
-        UNSAFE.putInt(t, SECONDARY, r);
+        U.putInt(t, SECONDARY, r);
         return r;
     }
 
     // Hotspot implementation via intrinsics API
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long parkBlockerOffset;
-    private static final long SEED;
-    private static final long PROBE;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long PARKBLOCKER;
     private static final long SECONDARY;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> tk = Thread.class;
-            parkBlockerOffset = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("parkBlocker"));
-            SEED = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomSeed"));
-            PROBE = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomProbe"));
-            SECONDARY = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
-        } catch (Exception ex) { throw new Error(ex); }
+            PARKBLOCKER = U.objectFieldOffset
+                (Thread.class.getDeclaredField("parkBlocker"));
+            SECONDARY = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Wed Jul 05 20:54:58 2017 +0200
@@ -38,9 +38,9 @@
 /**
  * A {@code ReadWriteLock} maintains a pair of associated {@link
  * Lock locks}, one for read-only operations and one for writing.
- * The {@link #readLock read lock} may be held simultaneously by
- * multiple reader threads, so long as there are no writers.  The
- * {@link #writeLock write lock} is exclusive.
+ * The {@linkplain #readLock read lock} may be held simultaneously
+ * by multiple reader threads, so long as there are no writers.
+ * The {@linkplain #writeLock write lock} is exclusive.
  *
  * <p>All {@code ReadWriteLock} implementations must guarantee that
  * the memory synchronization effects of {@code writeLock} operations
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,8 +34,9 @@
  */
 
 package java.util.concurrent.locks;
+
+import java.util.Collection;
 import java.util.concurrent.TimeUnit;
-import java.util.Collection;
 
 /**
  * A reentrant mutual exclusion {@link Lock} with the same basic
@@ -72,7 +73,7 @@
  * follow a call to {@code lock} with a {@code try} block, most
  * typically in a before/after construction such as:
  *
- *  <pre> {@code
+ * <pre> {@code
  * class X {
  *   private final ReentrantLock lock = new ReentrantLock();
  *   // ...
@@ -378,7 +379,7 @@
      * method. If you want a timed {@code tryLock} that does permit barging on
      * a fair lock then combine the timed and un-timed forms together:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * if (lock.tryLock() ||
      *     lock.tryLock(timeout, unit)) {
      *   ...
@@ -484,7 +485,7 @@
      * InterruptedException} will be thrown, and the thread's
      * interrupted status will be cleared.
      *
-     * <li> Waiting threads are signalled in FIFO order.
+     * <li>Waiting threads are signalled in FIFO order.
      *
      * <li>The ordering of lock reacquisition for threads returning
      * from waiting methods is the same as for threads initially
@@ -511,7 +512,7 @@
      * not be entered with the lock already held then we can assert that
      * fact:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * class X {
      *   ReentrantLock lock = new ReentrantLock();
      *   // ...
@@ -541,7 +542,7 @@
      * debugging and testing. For example, a method that should only be
      * called while a lock is held can assert that this is the case:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * class X {
      *   ReentrantLock lock = new ReentrantLock();
      *   // ...
@@ -555,7 +556,7 @@
      * <p>It can also be used to ensure that a reentrant lock is used
      * in a non-reentrant manner, for example:
      *
-     *  <pre> {@code
+     * <pre> {@code
      * class X {
      *   ReentrantLock lock = new ReentrantLock();
      *   // ...
@@ -646,12 +647,11 @@
     }
 
     /**
-     * Returns an estimate of the number of threads waiting to
-     * acquire this lock.  The value is only an estimate because the number of
+     * Returns an estimate of the number of threads waiting to acquire
+     * this lock.  The value is only an estimate because the number of
      * threads may change dynamically while this method traverses
      * internal data structures.  This method is designed for use in
-     * monitoring of the system state, not for synchronization
-     * control.
+     * monitoring system state, not for synchronization control.
      *
      * @return the estimated number of threads waiting for this lock
      */
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,8 +34,9 @@
  */
 
 package java.util.concurrent.locks;
+
+import java.util.Collection;
 import java.util.concurrent.TimeUnit;
-import java.util.Collection;
 
 /**
  * An implementation of {@link ReadWriteLock} supporting similar
@@ -51,14 +52,16 @@
  *
  * <dl>
  * <dt><b><i>Non-fair mode (default)</i></b>
- * <dd>When constructed as non-fair (the default), the order of entry
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * When constructed as non-fair (the default), the order of entry
  * to the read and write lock is unspecified, subject to reentrancy
  * constraints.  A nonfair lock that is continuously contended may
  * indefinitely postpone one or more reader or writer threads, but
  * will normally have higher throughput than a fair lock.
  *
  * <dt><b><i>Fair mode</i></b>
- * <dd>When constructed as fair, threads contend for entry using an
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * When constructed as fair, threads contend for entry using an
  * approximately arrival-order policy. When the currently held lock
  * is released, either the longest-waiting single writer thread will
  * be assigned the write lock, or if there is a group of reader threads
@@ -173,9 +176,9 @@
  * is a class using a TreeMap that is expected to be large and
  * concurrently accessed.
  *
- *  <pre> {@code
+ * <pre> {@code
  * class RWDictionary {
- *   private final Map<String, Data> m = new TreeMap<String, Data>();
+ *   private final Map<String, Data> m = new TreeMap<>();
  *   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  *   private final Lock r = rwl.readLock();
  *   private final Lock w = rwl.writeLock();
@@ -263,17 +266,17 @@
         static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
         static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
 
-        /** Returns the number of shared holds represented in count  */
+        /** Returns the number of shared holds represented in count. */
         static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
-        /** Returns the number of exclusive holds represented in count  */
+        /** Returns the number of exclusive holds represented in count. */
         static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
 
         /**
          * A counter for per-thread read hold counts.
-         * Maintained as a ThreadLocal; cached in cachedHoldCounter
+         * Maintained as a ThreadLocal; cached in cachedHoldCounter.
          */
         static final class HoldCounter {
-            int count = 0;
+            int count;          // initially 0
             // Use id, not reference, to avoid garbage retention
             final long tid = getThreadId(Thread.currentThread());
         }
@@ -330,7 +333,7 @@
          * <p>This allows tracking of read holds for uncontended read
          * locks to be very cheap.
          */
-        private transient Thread firstReader = null;
+        private transient Thread firstReader;
         private transient int firstReaderHoldCount;
 
         Sync() {
@@ -703,7 +706,7 @@
         private final Sync sync;
 
         /**
-         * Constructor for use by subclasses
+         * Constructor for use by subclasses.
          *
          * @param lock the outer lock object
          * @throws NullPointerException if the lock is null
@@ -814,7 +817,7 @@
          * permit barging on a fair lock then combine the timed and
          * un-timed forms together:
          *
-         *  <pre> {@code
+         * <pre> {@code
          * if (lock.tryLock() ||
          *     lock.tryLock(timeout, unit)) {
          *   ...
@@ -874,7 +877,12 @@
          * Attempts to release this lock.
          *
          * <p>If the number of readers is now zero then the lock
-         * is made available for write lock attempts.
+         * is made available for write lock attempts. If the current
+         * thread does not hold this lock then {@link
+         * IllegalMonitorStateException} is thrown.
+         *
+         * @throws IllegalMonitorStateException if the current thread
+         * does not hold this lock
          */
         public void unlock() {
             sync.releaseShared(1);
@@ -912,7 +920,7 @@
         private final Sync sync;
 
         /**
-         * Constructor for use by subclasses
+         * Constructor for use by subclasses.
          *
          * @param lock the outer lock object
          * @throws NullPointerException if the lock is null
@@ -1026,7 +1034,7 @@
          * by the current thread, or the write lock was already held
          * by the current thread; and {@code false} otherwise.
          */
-        public boolean tryLock( ) {
+        public boolean tryLock() {
             return sync.tryWriteLock();
         }
 
@@ -1046,7 +1054,7 @@
          * that does permit barging on a fair lock then combine the
          * timed and un-timed forms together:
          *
-         *  <pre> {@code
+         * <pre> {@code
          * if (lock.tryLock() ||
          *     lock.tryLock(timeout, unit)) {
          *   ...
@@ -1161,7 +1169,7 @@
          * InterruptedException} will be thrown, and the thread's
          * interrupted status will be cleared.
          *
-         * <li> Waiting threads are signalled in FIFO order.
+         * <li>Waiting threads are signalled in FIFO order.
          *
          * <li>The ordering of lock reacquisition for threads returning
          * from waiting methods is the same as for threads initially
@@ -1369,7 +1377,7 @@
      * either the read or write lock.  The value is only an estimate
      * because the number of threads may change dynamically while this
      * method traverses internal data structures.  This method is
-     * designed for use in monitoring of the system state, not for
+     * designed for use in monitoring system state, not for
      * synchronization control.
      *
      * @return the estimated number of threads waiting for this lock
@@ -1489,19 +1497,17 @@
      * ways that do not preserve unique mappings.
      */
     static final long getThreadId(Thread thread) {
-        return UNSAFE.getLongVolatile(thread, TID_OFFSET);
+        return U.getLongVolatile(thread, TID);
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long TID_OFFSET;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final long TID;
     static {
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> tk = Thread.class;
-            TID_OFFSET = UNSAFE.objectFieldOffset
-                (tk.getDeclaredField("tid"));
-        } catch (Exception e) {
+            TID = U.objectFieldOffset
+                (Thread.class.getDeclaredField("tid"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,10 +36,6 @@
 package java.util.concurrent.locks;
 
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.LockSupport;
 
 /**
  * A capability-based lock with three modes for controlling read/write
@@ -58,12 +54,12 @@
  *   in method {@link #unlockWrite} to release the lock. Untimed and
  *   timed versions of {@code tryWriteLock} are also provided. When
  *   the lock is held in write mode, no read locks may be obtained,
- *   and all optimistic read validations will fail.  </li>
+ *   and all optimistic read validations will fail.
  *
  *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
  *   waiting for non-exclusive access, returning a stamp that can be
  *   used in method {@link #unlockRead} to release the lock. Untimed
- *   and timed versions of {@code tryReadLock} are also provided. </li>
+ *   and timed versions of {@code tryReadLock} are also provided.
  *
  *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
  *   returns a non-zero stamp only if the lock is not currently held
@@ -81,7 +77,7 @@
  *   invoke method {@code validate()}.  For example, such steps are
  *   typically required when first reading an object or array
  *   reference, and then accessing one of its fields, elements or
- *   methods. </li>
+ *   methods.
  *
  * </ul>
  *
@@ -132,7 +128,7 @@
  * not strictly needed here because no exceptions can occur in their
  * bodies.<br>
  *
- *  <pre>{@code
+ * <pre> {@code
  * class Point {
  *   private double x, y;
  *   private final StampedLock sl = new StampedLock();
@@ -542,7 +538,7 @@
         WNode h;
         if (state != stamp || (stamp & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
+        U.putLongVolatile(this, STATE, (stamp += WBIT) == 0L ? ORIGIN : stamp);
         if ((h = whead) != null && h.status != 0)
             release(h);
     }
@@ -589,7 +585,7 @@
             else if (m == WBIT) {
                 if (a != m)
                     break;
-                state = (s += WBIT) == 0L ? ORIGIN : s;
+                U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
                 if ((h = whead) != null && h.status != 0)
                     release(h);
                 return;
@@ -610,7 +606,7 @@
     }
 
     /**
-     * If the lock state matches the given stamp, performs one of
+     * If the lock state matches the given stamp, atomically performs one of
      * the following actions. If the stamp represents holding a write
      * lock, returns it.  Or, if a read lock, if the write lock is
      * available, releases the read lock and returns a write stamp.
@@ -647,7 +643,7 @@
     }
 
     /**
-     * If the lock state matches the given stamp, performs one of
+     * If the lock state matches the given stamp, atomically performs one of
      * the following actions. If the stamp represents holding a write
      * lock, releases it and obtains a read lock.  Or, if a read lock,
      * returns it. Or, if an optimistic read, acquires a read lock and
@@ -673,7 +669,7 @@
             else if (m == WBIT) {
                 if (a != m)
                     break;
-                state = next = s + (WBIT + RUNIT);
+                U.putLongVolatile(this, STATE, next = s + (WBIT + RUNIT));
                 if ((h = whead) != null && h.status != 0)
                     release(h);
                 return next;
@@ -687,7 +683,7 @@
     }
 
     /**
-     * If the lock state matches the given stamp then, if the stamp
+     * If the lock state matches the given stamp then, atomically, if the stamp
      * represents holding a lock, releases it and returns an
      * observation stamp.  Or, if an optimistic read, returns it if
      * validated. This method returns zero in all other cases, and so
@@ -710,7 +706,8 @@
             else if (m == WBIT) {
                 if (a != m)
                     break;
-                state = next = (s += WBIT) == 0L ? ORIGIN : s;
+                U.putLongVolatile(this, STATE,
+                                  next = (s += WBIT) == 0L ? ORIGIN : s);
                 if ((h = whead) != null && h.status != 0)
                     release(h);
                 return next;
@@ -740,7 +737,7 @@
     public boolean tryUnlockWrite() {
         long s; WNode h;
         if (((s = state) & WBIT) != 0L) {
-            state = (s += WBIT) == 0L ? ORIGIN : s;
+            U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
             if ((h = whead) != null && h.status != 0)
                 release(h);
             return true;
@@ -923,7 +920,7 @@
         WNode h; long s;
         if (((s = state) & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        state = (s += WBIT) == 0L ? ORIGIN : s;
+        U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
         if ((h = whead) != null && h.status != 0)
             release(h);
     }
@@ -948,7 +945,7 @@
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
-        state = ORIGIN; // reset to unlocked state
+        U.putLongVolatile(this, STATE, ORIGIN); // reset to unlocked state
     }
 
     // internals
@@ -966,7 +963,7 @@
         if ((s & ABITS) == RFULL) {
             if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
                 ++readerOverflow;
-                state = s;
+                U.putLongVolatile(this, STATE, s);
                 return s;
             }
         }
@@ -993,8 +990,8 @@
                 }
                 else
                     next = s - RUNIT;
-                 state = next;
-                 return next;
+                U.putLongVolatile(this, STATE, next);
+                return next;
             }
         }
         else if ((LockSupport.nextSecondarySeed() &
@@ -1062,6 +1059,7 @@
             }
         }
 
+        boolean wasInterrupted = false;
         for (int spins = -1;;) {
             WNode h, np, pp; int ps;
             if ((h = whead) == p) {
@@ -1076,6 +1074,8 @@
                                                  ns = s + WBIT)) {
                             whead = node;
                             node.prev = null;
+                            if (wasInterrupted)
+                                Thread.currentThread().interrupt();
                             return ns;
                         }
                     }
@@ -1119,8 +1119,11 @@
                         U.park(false, time);  // emulate LockSupport.park
                     node.thread = null;
                     U.putObject(wt, PARKBLOCKER, null);
-                    if (interruptible && Thread.interrupted())
-                        return cancelWaiter(node, node, true);
+                    if (Thread.interrupted()) {
+                        if (interruptible)
+                            return cancelWaiter(node, node, true);
+                        wasInterrupted = true;
+                    }
                 }
             }
         }
@@ -1136,6 +1139,7 @@
      * @return next state, or INTERRUPTED
      */
     private long acquireRead(boolean interruptible, long deadline) {
+        boolean wasInterrupted = false;
         WNode node = null, p;
         for (int spins = -1;;) {
             WNode h;
@@ -1143,8 +1147,11 @@
                 for (long m, s, ns;;) {
                     if ((m = (s = state) & ABITS) < RFULL ?
                         U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
-                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
+                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
+                        if (wasInterrupted)
+                            Thread.currentThread().interrupt();
                         return ns;
+                    }
                     else if (m >= WBIT) {
                         if (spins > 0) {
                             if (LockSupport.nextSecondarySeed() >= 0)
@@ -1193,8 +1200,11 @@
                                 U.compareAndSwapLong(this, STATE, s,
                                                      ns = s + RUNIT) :
                                 (m < WBIT &&
-                                 (ns = tryIncReaderOverflow(s)) != 0L))
+                                 (ns = tryIncReaderOverflow(s)) != 0L)) {
+                                if (wasInterrupted)
+                                    Thread.currentThread().interrupt();
                                 return ns;
+                            }
                         } while (m < WBIT);
                     }
                     if (whead == h && p.prev == pp) {
@@ -1205,8 +1215,11 @@
                         }
                         if (deadline == 0L)
                             time = 0L;
-                        else if ((time = deadline - System.nanoTime()) <= 0L)
+                        else if ((time = deadline - System.nanoTime()) <= 0L) {
+                            if (wasInterrupted)
+                                Thread.currentThread().interrupt();
                             return cancelWaiter(node, p, false);
+                        }
                         Thread wt = Thread.currentThread();
                         U.putObject(wt, PARKBLOCKER, this);
                         node.thread = wt;
@@ -1215,8 +1228,11 @@
                             U.park(false, time);
                         node.thread = null;
                         U.putObject(wt, PARKBLOCKER, null);
-                        if (interruptible && Thread.interrupted())
-                            return cancelWaiter(node, p, true);
+                        if (Thread.interrupted()) {
+                            if (interruptible)
+                                return cancelWaiter(node, p, true);
+                            wasInterrupted = true;
+                        }
                     }
                 }
             }
@@ -1243,6 +1259,8 @@
                                 (w = c.thread) != null)
                                 U.unpark(w);
                         }
+                        if (wasInterrupted)
+                            Thread.currentThread().interrupt();
                         return ns;
                     }
                     else if (m >= WBIT &&
@@ -1286,8 +1304,11 @@
                         U.park(false, time);
                     node.thread = null;
                     U.putObject(wt, PARKBLOCKER, null);
-                    if (interruptible && Thread.interrupted())
-                        return cancelWaiter(node, node, true);
+                    if (Thread.interrupted()) {
+                        if (interruptible)
+                            return cancelWaiter(node, node, true);
+                        wasInterrupted = true;
+                    }
                 }
             }
         }
@@ -1377,7 +1398,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U;
+    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long WHEAD;
     private static final long WTAIL;
@@ -1388,26 +1409,23 @@
 
     static {
         try {
-            U = sun.misc.Unsafe.getUnsafe();
-            Class<?> k = StampedLock.class;
-            Class<?> wk = WNode.class;
             STATE = U.objectFieldOffset
-                (k.getDeclaredField("state"));
+                (StampedLock.class.getDeclaredField("state"));
             WHEAD = U.objectFieldOffset
-                (k.getDeclaredField("whead"));
+                (StampedLock.class.getDeclaredField("whead"));
             WTAIL = U.objectFieldOffset
-                (k.getDeclaredField("wtail"));
+                (StampedLock.class.getDeclaredField("wtail"));
+
             WSTATUS = U.objectFieldOffset
-                (wk.getDeclaredField("status"));
+                (WNode.class.getDeclaredField("status"));
             WNEXT = U.objectFieldOffset
-                (wk.getDeclaredField("next"));
+                (WNode.class.getDeclaredField("next"));
             WCOWAIT = U.objectFieldOffset
-                (wk.getDeclaredField("cowait"));
-            Class<?> tk = Thread.class;
+                (WNode.class.getDeclaredField("cowait"));
+
             PARKBLOCKER = U.objectFieldOffset
-                (tk.getDeclaredField("parkBlocker"));
-
-        } catch (Exception e) {
+                (Thread.class.getDeclaredField("parkBlocker"));
+        } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Wed Jul 05 20:54:58 2017 +0200
@@ -226,8 +226,9 @@
  *
  * <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
  *
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
- * Chapter 17 of the Java Language Specification</a> defines the
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5">
+ * Chapter 17 of
+ * <cite>The Java&trade; Language Specification</cite></a> defines the
  * <i>happens-before</i> relation on memory operations such as reads and
  * writes of shared variables.  The results of a write by one thread are
  * guaranteed to be visible to a read by another thread only if the write
--- a/jdk/src/java.base/share/classes/java/util/zip/Deflater.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/Deflater.java	Wed Jul 05 20:54:58 2017 +0200
@@ -318,7 +318,9 @@
      * should be called in order to provide more input
      */
     public boolean needsInput() {
-        return len <= 0;
+        synchronized (zsRef) {
+            return len <= 0;
+        }
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/zip/ZStreamRef.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZStreamRef.java	Wed Jul 05 20:54:58 2017 +0200
@@ -31,7 +31,7 @@
 
 class ZStreamRef {
 
-    private long address;
+    private volatile long address;
     ZStreamRef (long address) {
         this.address = address;
     }
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Wed Jul 05 20:54:58 2017 +0200
@@ -60,7 +60,7 @@
  */
 public
 class ZipFile implements ZipConstants, Closeable {
-    private long jzfile;           // address of jzfile data
+    private long jzfile;  // address of jzfile data
     private final String name;     // zip file name
     private final int total;       // total number of entries
     private final boolean locsig;  // if zip file starts with LOCSIG (usually true)
@@ -691,7 +691,7 @@
      * (possibly compressed) zip file entry.
      */
    private class ZipFileInputStream extends InputStream {
-        private volatile boolean closeRequested = false;
+        private volatile boolean zfisCloseRequested = false;
         protected long jzentry; // address of jzentry data
         private   long pos;     // current position within entry data
         protected long rem;     // number of remaining bytes within entry
@@ -718,6 +718,7 @@
                     len = (int) rem;
                 }
 
+                // Check if ZipFile open
                 ensureOpenOrZipException();
                 len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b,
                                    off, len);
@@ -761,9 +762,9 @@
         }
 
         public void close() {
-            if (closeRequested)
+            if (zfisCloseRequested)
                 return;
-            closeRequested = true;
+            zfisCloseRequested = true;
 
             rem = 0;
             synchronized (ZipFile.this) {
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Wed Jul 05 20:54:58 2017 +0200
@@ -58,7 +58,7 @@
 
         try {
             substrate = ImageNativeSubstrate.openImage(imagePath, byteOrder);
-        } catch (UnsatisfiedLinkError ex) {
+        } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) {
             substrate = ImageJavaSubstrate.openImage(imagePath, byteOrder);
         }
 
--- a/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -37,14 +37,20 @@
 
     private BytecodeDescriptor() { }  // cannot instantiate
 
+    /**
+     * @param loader the class loader in which to look up the types (null means
+     *               bootstrap class loader)
+     */
     public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
         return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
     }
 
+    /**
+     * @param loader the class loader in which to look up the types (null means
+     *               bootstrap class loader)
+     */
     static List<Class<?>> parseMethod(String bytecodeSignature,
             int start, int end, ClassLoader loader) {
-        if (loader == null)
-            loader = ClassLoader.getSystemClassLoader();
         String str = bytecodeSignature;
         int[] i = {start};
         ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
@@ -71,6 +77,10 @@
         throw new IllegalArgumentException("bad signature: "+str+": "+msg);
     }
 
+    /**
+     * @param loader the class loader in which to look up the types (null means
+     *               bootstrap class loader)
+     */
     private static Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
         if (i[0] == end)  return null;
         char c = str.charAt(i[0]++);
@@ -80,7 +90,9 @@
             i[0] = endc+1;
             String name = str.substring(begc, endc).replace('/', '.');
             try {
-                return loader.loadClass(name);
+                return (loader == null)
+                    ? Class.forName(name, false, null)
+                    : loader.loadClass(name);
             } catch (ClassNotFoundException ex) {
                 throw new TypeNotPresentException(name, ex);
             }
--- a/jdk/src/java.base/share/classes/sun/misc/ConditionLock.java	Wed Jul 05 20:54:03 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 1994, 2005, 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 sun.misc;
-
-/**
- * ConditionLock is a Lock with a built in state variable.  This class
- * provides the ability to wait for the state variable to be set to a
- * desired value and then acquire the lock.<p>
- *
- * The lockWhen() and unlockWith() methods can be safely intermixed
- * with the lock() and unlock() methods. However if there is a thread
- * waiting for the state variable to become a particular value and you
- * simply call Unlock(), that thread will not be able to acquire the
- * lock until the state variable equals its desired value.
- *
- * @author      Peter King
- */
-public final
-class ConditionLock extends Lock {
-    private int state = 0;
-
-    /**
-     * Creates a ConditionLock.
-     */
-    public ConditionLock () {
-    }
-
-    /**
-     * Creates a ConditionLock in an initialState.
-     */
-    public ConditionLock (int initialState) {
-        state = initialState;
-    }
-
-    /**
-     * Acquires the lock when the state variable equals the desired state.
-     *
-     * @param desiredState the desired state
-     * @exception  java.lang.InterruptedException if any thread has
-     *               interrupted this thread.
-     */
-    public synchronized void lockWhen(int desiredState)
-        throws InterruptedException
-    {
-        while (state != desiredState) {
-            wait();
-        }
-        lock();
-    }
-
-    /**
-     * Releases the lock, and sets the state to a new value.
-     * @param newState the new state
-     */
-    public synchronized void unlockWith(int newState) {
-        state = newState;
-        unlock();
-    }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/Lock.java	Wed Jul 05 20:54:03 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 1994, 2005, 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 sun.misc;
-
-/**
- * The Lock class provides a simple, useful interface to a lock.
- * Unlike monitors which synchronize access to an object, locks
- * synchronize access to an arbitrary set of resources (objects,
- * methods, variables, etc.). <p>
- *
- * The programmer using locks must be responsible for clearly defining
- * the semantics of their use and should handle deadlock avoidance in
- * the face of exceptions. <p>
- *
- * For example, if you want to protect a set of method invocations with
- * a lock, and one of the methods may throw an exception, you must be
- * prepared to release the lock similarly to the following example:
- * <pre>
- *      class SomeClass {
- *          Lock myLock = new Lock();
-
- *          void someMethod() {
- *              myLock.lock();
- *              try {
- *                  StartOperation();
- *                  ContinueOperation();
- *                  EndOperation();
- *              } finally {
- *                  myLock.unlock();
- *              }
- *          }
- *      }
- * </pre>
- *
- * @author      Peter King
- */
-public
-class Lock {
-    private boolean locked = false;
-
-    /**
-     * Create a lock, which is initially not locked.
-     */
-    public Lock () {
-    }
-
-    /**
-     * Acquire the lock.  If someone else has the lock, wait until it
-     * has been freed, and then try to acquire it again.  This method
-     * will not return until the lock has been acquired.
-     *
-     * @exception  java.lang.InterruptedException if any thread has
-     *               interrupted this thread.
-     */
-    public final synchronized void lock() throws InterruptedException {
-        while (locked) {
-            wait();
-        }
-        locked = true;
-    }
-
-    /**
-     * Release the lock.  If someone else is waiting for the lock, the
-     * will be notitified so they can try to acquire the lock again.
-     */
-    public final synchronized void unlock() {
-        locked = false;
-        notifyAll();
-    }
-}
--- a/jdk/src/java.base/share/native/libfdlibm/s_cbrt.c	Wed Jul 05 20:54:03 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-
-/*
- * Copyright (c) 1998, 2001, 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.
- */
-
-#include "fdlibm.h"
-
-/* cbrt(x)
- * Return cube root of x
- */
-#ifdef __STDC__
-static const unsigned
-#else
-static unsigned
-#endif
-        B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
-        B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
-
-#ifdef __STDC__
-static const double
-#else
-static double
-#endif
-C =  5.42857142857142815906e-01, /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
-D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
-E =  1.41428571428571436819e+00, /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
-F =  1.60714285714285720630e+00, /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
-G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
-
-#ifdef __STDC__
-        double cbrt(double x)
-#else
-        double cbrt(x)
-        double x;
-#endif
-{
-        int     hx;
-        double r,s,t=0.0,w;
-        unsigned sign;
-
-
-        hx = __HI(x);           /* high word of x */
-        sign=hx&0x80000000;             /* sign= sign(x) */
-        hx  ^=sign;
-        if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
-        if((hx|__LO(x))==0)
-            return(x);          /* cbrt(0) is itself */
-
-        __HI(x) = hx;   /* x <- |x| */
-    /* rough cbrt to 5 bits */
-        if(hx<0x00100000)               /* subnormal number */
-          {__HI(t)=0x43500000;          /* set t= 2**54 */
-           t*=x; __HI(t)=__HI(t)/3+B2;
-          }
-        else
-          __HI(t)=hx/3+B1;
-
-
-    /* new cbrt to 23 bits, may be implemented in single precision */
-        r=t*t/x;
-        s=C+r*t;
-        t*=G+F/(s+E+D/s);
-
-    /* chopped to 20 bits and make it larger than cbrt(x) */
-        __LO(t)=0; __HI(t)+=0x00000001;
-
-
-    /* one step newton iteration to 53 bits with error less than 0.667 ulps */
-        s=t*t;          /* t*t is exact */
-        r=x/s;
-        w=t+t;
-        r=(r-t)/(w+r);  /* r-s is exact */
-        t=t+t*r;
-
-    /* retore the sign bit */
-        __HI(t) |= sign;
-        return(t);
-}
--- a/jdk/src/java.base/share/native/libjava/StrictMath.c	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/native/libjava/StrictMath.c	Wed Jul 05 20:54:58 2017 +0200
@@ -89,12 +89,6 @@
 }
 
 JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
-{
-    return (jdouble) jcbrt((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
 Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
 {
     return (jdouble) jatan2((double)d1, (double)d2);
--- a/jdk/src/java.base/share/native/libzip/zip_util.c	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.base/share/native/libzip/zip_util.c	Wed Jul 05 20:54:58 2017 +0200
@@ -1302,12 +1302,23 @@
 jint
 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
 {
-    jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
+    jlong entry_size;
     jlong start;
 
+    if (zip == 0) {
+        return -1;
+    }
+
     /* Clear previous zip error */
     zip->msg = NULL;
 
+    if (entry == 0) {
+        zip->msg = "ZIP_Read: jzentry is NULL";
+        return -1;
+    }
+
+    entry_size = (entry->csize != 0) ? entry->csize : entry->size;
+
     /* Check specified position */
     if (pos < 0 || pos > entry_size - 1) {
         zip->msg = "ZIP_Read: specified offset out of range";
@@ -1440,6 +1451,11 @@
     char *msg;
     char tmpbuf[1024];
 
+    if (entry == 0) {
+        jio_fprintf(stderr, "jzentry was invalid");
+        return JNI_FALSE;
+    }
+
     strcpy(entryname, entry->name);
     if (entry->csize == 0) {
         /* Entry is stored */
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed Jul 05 20:54:58 2017 +0200
@@ -32,8 +32,14 @@
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.util.concurrent.ConcurrentHashMap;
+import java.nio.file.Paths;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import jdk.internal.misc.JavaAWTAccess;
 import jdk.internal.misc.SharedSecrets;
 import sun.misc.ManagedLocalsThread;
@@ -57,37 +63,28 @@
  * <p>
  * At startup the LogManager class is located using the
  * java.util.logging.manager system property.
+ *
+ * <h3>LogManager Configuration</h3>
+ *
+ * A LogManager initializes the logging configuration via
+ * the {@link #readConfiguration()} method during LogManager initialization.
+ * By default, LogManager default configuration is used.
+ * The logging configuration read by LogManager must be in the
+ * {@linkplain Properties properties file} format.
  * <p>
  * The LogManager defines two optional system properties that allow control over
- * the initial configuration:
+ * the initial configuration, as specified in the {@link #readConfiguration()}
+ * method:
  * <ul>
  * <li>"java.util.logging.config.class"
  * <li>"java.util.logging.config.file"
  * </ul>
- * These two properties may be specified on the command line to the "java"
+ * <p>
+ * These two system properties may be specified on the command line to the "java"
  * command, or as system property definitions passed to JNI_CreateJavaVM.
  * <p>
- * If the "java.util.logging.config.class" property is set, then the
- * property value is treated as a class name.  The given class will be
- * loaded, an object will be instantiated, and that object's constructor
- * is responsible for reading in the initial configuration.  (That object
- * may use other system properties to control its configuration.)  The
- * alternate configuration class can use {@code readConfiguration(InputStream)}
- * to define properties in the LogManager.
- * <p>
- * If "java.util.logging.config.class" property is <b>not</b> set,
- * then the "java.util.logging.config.file" system property can be used
- * to specify a properties file (in java.util.Properties format). The
- * initial logging configuration will be read from this file.
- * <p>
- * If neither of these properties is defined then the LogManager uses its
- * default configuration. The default configuration is typically loaded from the
- * properties file "{@code conf/logging.properties}" in the Java installation
- * directory.
- * <p>
- * The properties for loggers and Handlers will have names starting
- * with the dot-separated name for the handler or logger.
- * <p>
+ * The {@linkplain Properties properties} for loggers and Handlers will have
+ * names starting with the dot-separated name for the handler or logger.<br>
  * The global logging properties may include:
  * <ul>
  * <li>A property "handlers".  This defines a whitespace or comma separated
@@ -788,7 +785,7 @@
             // instantiation of the handler is done in the LogManager.addLogger
             // implementation as a handler class may be only visible to LogManager
             // subclass for the custom log manager case
-            processParentHandlers(logger, name);
+            processParentHandlers(logger, name, VisitedLoggers.NEVER);
 
             // Find the new node and its parent.
             LogNode node = getNode(name);
@@ -836,7 +833,8 @@
 
         // If logger.getUseParentHandlers() returns 'true' and any of the logger's
         // parents have levels or handlers defined, make sure they are instantiated.
-        private void processParentHandlers(final Logger logger, final String name) {
+        private void processParentHandlers(final Logger logger, final String name,
+               Predicate<Logger> visited) {
             final LogManager owner = getOwner();
             AccessController.doPrivileged(new PrivilegedAction<Void>() {
                 @Override
@@ -862,7 +860,9 @@
                     owner.getProperty(pname + ".handlers") != null) {
                     // This pname has a level/handlers definition.
                     // Make sure it exists.
-                    demandLogger(pname, null, null);
+                    if (visited.test(demandLogger(pname, null, null))) {
+                        break;
+                    }
                 }
                 ix = ix2+1;
             }
@@ -942,48 +942,64 @@
     private void loadLoggerHandlers(final Logger logger, final String name,
                                     final String handlersPropertyName)
     {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
             @Override
-            public Object run() {
-                String names[] = parseClassNames(handlersPropertyName);
-                final boolean ensureCloseOnReset = names.length > 0
-                    && getBooleanProperty(handlersPropertyName + ".ensureCloseOnReset",true);
-
-                int count = 0;
-                for (String type : names) {
-                    try {
-                        Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
-                        Handler hdl = (Handler) clz.newInstance();
-                        // Check if there is a property defining the
-                        // this handler's level.
-                        String levs = getProperty(type + ".level");
-                        if (levs != null) {
-                            Level l = Level.findLevel(levs);
-                            if (l != null) {
-                                hdl.setLevel(l);
-                            } else {
-                                // Probably a bad level. Drop through.
-                                System.err.println("Can't set level for " + type);
-                            }
-                        }
-                        // Add this Handler to the logger
-                        logger.addHandler(hdl);
-                        if (++count == 1 && ensureCloseOnReset) {
-                            // add this logger to the closeOnResetLoggers list.
-                            closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
-                        }
-                    } catch (Exception ex) {
-                        System.err.println("Can't load log handler \"" + type + "\"");
-                        System.err.println("" + ex);
-                        ex.printStackTrace();
-                    }
-                }
-
+            public Void run() {
+                setLoggerHandlers(logger, name, handlersPropertyName,
+                    createLoggerHandlers(name, handlersPropertyName));
                 return null;
             }
         });
     }
 
+    private void setLoggerHandlers(final Logger logger, final String name,
+                                   final String handlersPropertyName,
+                                   List<Handler> handlers)
+    {
+        final boolean ensureCloseOnReset = ! handlers.isEmpty()
+                    && getBooleanProperty(handlersPropertyName + ".ensureCloseOnReset",true);
+        int count = 0;
+        for (Handler hdl : handlers) {
+            logger.addHandler(hdl);
+            if (++count == 1 && ensureCloseOnReset) {
+                // add this logger to the closeOnResetLoggers list.
+                closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
+            }
+        }
+    }
+
+    private List<Handler> createLoggerHandlers(final String name, final String handlersPropertyName)
+    {
+        String names[] = parseClassNames(handlersPropertyName);
+        List<Handler> handlers = new ArrayList<>(names.length);
+        for (String type : names) {
+            try {
+                Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
+                Handler hdl = (Handler) clz.newInstance();
+                // Check if there is a property defining the
+                // this handler's level.
+                String levs = getProperty(type + ".level");
+                if (levs != null) {
+                    Level l = Level.findLevel(levs);
+                    if (l != null) {
+                        hdl.setLevel(l);
+                    } else {
+                        // Probably a bad level. Drop through.
+                        System.err.println("Can't set level for " + type);
+                    }
+                }
+                // Add this Handler to the logger
+                handlers.add(hdl);
+            } catch (Exception ex) {
+                System.err.println("Can't load log handler \"" + type + "\"");
+                System.err.println("" + ex);
+                ex.printStackTrace();
+            }
+        }
+
+        return handlers;
+    }
+
 
     // loggerRefQueue holds LoggerWeakRef objects for Logger objects
     // that have been GC'ed.
@@ -1242,21 +1258,48 @@
     }
 
     /**
-     * Reinitialize the logging properties and reread the logging configuration.
+     * Reads and initializes the logging configuration.
+     * <p>
+     * If the "java.util.logging.config.class" system property is set, then the
+     * property value is treated as a class name.  The given class will be
+     * loaded, an object will be instantiated, and that object's constructor
+     * is responsible for reading in the initial configuration.  (That object
+     * may use other system properties to control its configuration.)  The
+     * alternate configuration class can use {@code readConfiguration(InputStream)}
+     * to define properties in the LogManager.
      * <p>
-     * The same rules are used for locating the configuration properties
-     * as are used at startup.  So normally the logging properties will
-     * be re-read from the same file that was used at startup.
-     * <P>
-     * Any log level definitions in the new configuration file will be
-     * applied using Logger.setLevel(), if the target Logger exists.
+     * If "java.util.logging.config.class" system property is <b>not</b> set,
+     * then this method will read the initial configuration from a properties
+     * file and calls the {@link #readConfiguration(InputStream)} method to initialize
+     * the configuration. The "java.util.logging.config.file" system property can be used
+     * to specify the properties file that will be read as the initial configuration;
+     * if not set, then the LogManager default configuration is used.
+     * The default configuration is typically loaded from the
+     * properties file "{@code conf/logging.properties}" in the Java installation
+     * directory.
+     *
      * <p>
      * Any {@linkplain #addConfigurationListener registered configuration
      * listener} will be invoked after the properties are read.
      *
-     * @exception  SecurityException  if a security manager exists and if
-     *             the caller does not have LoggingPermission("control").
-     * @exception  IOException if there are IO problems reading the configuration.
+     * @apiNote This {@code readConfiguration} method should only be used for
+     * initializing the configuration during LogManager initialization or
+     * used with the "java.util.logging.config.class" property.
+     * When this method is called after loggers have been created, and
+     * the "java.util.logging.config.class" system property is not set, all
+     * existing loggers will be {@linkplain #reset() reset}. Then any
+     * existing loggers that have a level property specified in the new
+     * configuration stream will be {@linkplain
+     * Logger#setLevel(java.util.logging.Level) set} to the specified log level.
+     * <p>
+     * To properly update the logging configuration, use the
+     * {@link #updateConfiguration(java.util.function.Function)} or
+     * {@link #updateConfiguration(java.io.InputStream, java.util.function.Function)}
+     * methods instead.
+     *
+     * @throws   SecurityException  if a security manager exists and if
+     *              the caller does not have LoggingPermission("control").
+     * @throws   IOException if there are IO problems reading the configuration.
      */
     public void readConfiguration() throws IOException, SecurityException {
         checkPermission();
@@ -1284,20 +1327,24 @@
             }
         }
 
+        String fname = getConfigurationFileName();
+        try (final InputStream in = new FileInputStream(fname)) {
+            final BufferedInputStream bin = new BufferedInputStream(in);
+            readConfiguration(bin);
+        }
+    }
+
+    String getConfigurationFileName() throws IOException {
         String fname = System.getProperty("java.util.logging.config.file");
         if (fname == null) {
             fname = System.getProperty("java.home");
             if (fname == null) {
                 throw new Error("Can't find java.home ??");
             }
-            File f = new File(fname, "conf");
-            f = new File(f, "logging.properties");
-            fname = f.getCanonicalPath();
+            fname = Paths.get(fname, "conf", "logging.properties")
+                    .toAbsolutePath().normalize().toString();
         }
-        try (final InputStream in = new FileInputStream(fname)) {
-            final BufferedInputStream bin = new BufferedInputStream(in);
-            readConfiguration(bin);
-        }
+        return fname;
     }
 
     /**
@@ -1305,9 +1352,17 @@
      * <p>
      * For all named loggers, the reset operation removes and closes
      * all Handlers and (except for the root logger) sets the level
-     * to null.  The root logger's level is set to Level.INFO.
+     * to {@code null}. The root logger's level is set to {@code Level.INFO}.
      *
-     * @exception  SecurityException  if a security manager exists and if
+     * @apiNote Calling this method also clears the LogManager {@linkplain
+     * #getProperty(java.lang.String) properties}. The {@link
+     * #updateConfiguration(java.util.function.Function)
+     * updateConfiguration(Function)} or
+     * {@link #updateConfiguration(java.io.InputStream, java.util.function.Function)
+     * updateConfiguration(InputStream, Function)} method can be used to
+     * properly update to a new configuration.
+     *
+     * @throws  SecurityException  if a security manager exists and if
      *             the caller does not have LoggingPermission("control").
      */
 
@@ -1421,18 +1476,32 @@
     }
 
     /**
-     * Reinitialize the logging properties and reread the logging configuration
-     * from the given stream, which should be in java.util.Properties format.
+     * Reads and initializes the logging configuration from the given input stream.
+     *
+     * <p>
      * Any {@linkplain #addConfigurationListener registered configuration
      * listener} will be invoked after the properties are read.
      * <p>
-     * Any log level definitions in the new configuration file will be
-     * applied using Logger.setLevel(), if the target Logger exists.
+     * @apiNote This {@code readConfiguration} method should only be used for
+     * initializing the configuration during LogManager initialization or
+     * used with the "java.util.logging.config.class" property.
+     * When this method is called after loggers have been created, all
+     * existing loggers will be {@linkplain #reset() reset}. Then any
+     * existing loggers that have a level property specified in the
+     * given input stream will be {@linkplain
+     * Logger#setLevel(java.util.logging.Level) set} to the specified log level.
+     * <p>
+     * To properly update the logging configuration, use the
+     * {@link #updateConfiguration(java.util.function.Function)} or
+     * {@link #updateConfiguration(java.io.InputStream, java.util.function.Function)}
+     * method instead.
      *
-     * @param ins       stream to read properties from
-     * @exception  SecurityException  if a security manager exists and if
+     * @param ins  stream to read properties from
+     * @throws  SecurityException  if a security manager exists and if
      *             the caller does not have LoggingPermission("control").
-     * @exception  IOException if there are problems reading from the stream.
+     * @throws  IOException if there are problems reading from the stream,
+     *             or the given stream is not in the
+     *             {@linkplain java.util.Properties properties file} format.
      */
     public void readConfiguration(InputStream ins) throws IOException, SecurityException {
         checkPermission();
@@ -1506,6 +1575,633 @@
         invokeConfigurationListeners();
     }
 
+    // This enum enumerate the configuration properties that will be
+    // updated on existing loggers when the configuration is updated
+    // with LogManager.updateConfiguration().
+    //
+    // Note that this works properly only for the global LogManager - as
+    // Handler and its subclasses get their configuration from
+    // LogManager.getLogManager().
+    //
+    static enum ConfigProperty {
+        LEVEL(".level"), HANDLERS(".handlers"), USEPARENT(".useParentHandlers");
+        final String suffix;
+        final int length;
+        private ConfigProperty(String suffix) {
+            this.suffix = Objects.requireNonNull(suffix);
+            length = suffix.length();
+        }
+
+        public boolean handleKey(String key) {
+            if (this == HANDLERS && suffix.substring(1).equals(key)) return true;
+            if (this == HANDLERS && suffix.equals(key)) return false;
+            return key.endsWith(suffix);
+        }
+        String key(String loggerName) {
+            if (this == HANDLERS && (loggerName == null || loggerName.isEmpty())) {
+                return suffix.substring(1);
+            }
+            return loggerName + suffix;
+        }
+        String loggerName(String key) {
+            assert key.equals(suffix.substring(1)) && this == HANDLERS || key.endsWith(suffix);
+            if (this == HANDLERS && suffix.substring(1).equals(key)) return "";
+            return key.substring(0, key.length() - length);
+        }
+
+        /**
+         * If the property is one that should be updated on existing loggers by
+         * updateConfiguration, returns the name of the logger for which the
+         * property is configured. Otherwise, returns null.
+         * @param property a property key in 'props'
+         * @return the name of the logger on which the property is to be set,
+         *         if the property is one that should be updated on existing
+         *         loggers, {@code null} otherwise.
+         */
+        static String getLoggerName(String property) {
+            for (ConfigProperty p : ConfigProperty.ALL) {
+                if (p.handleKey(property)) {
+                    return p.loggerName(property);
+                }
+            }
+            return null; // Not a property that should be updated.
+        }
+
+        /**
+         * Find the ConfigProperty corresponding to the given
+         * property key (may find none).
+         * @param property a property key in 'props'
+         * @return An optional containing a ConfigProperty object,
+         *         if the property is one that should be updated on existing
+         *         loggers, empty otherwise.
+         */
+        static Optional<ConfigProperty> find(String property) {
+            return ConfigProperty.ALL.stream()
+                    .filter(p -> p.handleKey(property))
+                    .findFirst();
+         }
+
+        /**
+         * Returns true if the given property is one that should be updated
+         * on existing loggers.
+         * Used to filter property name streams.
+         * @param property a property key from the configuration.
+         * @return true if this property is of interest for updateConfiguration.
+         */
+        static boolean matches(String property) {
+            return find(property).isPresent();
+        }
+
+        /**
+         * Returns true if the new property value is different from the old,
+         * and therefore needs to be updated on existing loggers.
+         * @param k a property key in the configuration
+         * @param previous the old configuration
+         * @param next the new configuration
+         * @return true if the property is changing value between the two
+         *         configurations.
+         */
+        static boolean needsUpdating(String k, Properties previous, Properties next) {
+            final String p = trim(previous.getProperty(k, null));
+            final String n = trim(next.getProperty(k, null));
+            return ! Objects.equals(p,n);
+        }
+
+        /**
+         * Applies the mapping function for the given key to the next
+         * configuration.
+         * If the mapping function is null then this method does nothing.
+         * Otherwise, it calls the mapping function to compute the value
+         * that should be associated with {@code key} in the resulting
+         * configuration, and applies it to {@code next}.
+         * If the mapping function returns {@code null} the key is removed
+         * from {@code next}.
+         *
+         * @param k a property key in the configuration
+         * @param previous the old configuration
+         * @param next the new configuration (modified by this function)
+         * @param remappingFunction the mapping function.
+         */
+        static void merge(String k, Properties previous, Properties next,
+                          BiFunction<String, String, String> mappingFunction) {
+            String p = trim(previous.getProperty(k, null));
+            String n = trim(next.getProperty(k, null));
+            String mapped = trim(mappingFunction.apply(p,n));
+            if (!Objects.equals(n, mapped)) {
+                if (mapped == null) {
+                    next.remove(k);
+                } else {
+                    next.setProperty(k, mapped);
+                }
+            }
+        }
+
+        private static final EnumSet<ConfigProperty> ALL =
+                EnumSet.allOf(ConfigProperty.class);
+    }
+
+    // trim the value if not null.
+    private static String trim(String value) {
+        return value == null ? null : value.trim();
+    }
+
+    /**
+     * An object that keep track of loggers we have already visited.
+     * Used when updating configuration, to avoid processing the same logger
+     * twice.
+     */
+    static final class VisitedLoggers implements Predicate<Logger> {
+        final IdentityHashMap<Logger,Boolean> visited;
+        private VisitedLoggers(IdentityHashMap<Logger,Boolean> visited) {
+            this.visited = visited;
+        }
+        VisitedLoggers() {
+            this(new IdentityHashMap<>());
+        }
+        @Override
+        public boolean test(Logger logger) {
+            return visited != null && visited.put(logger, Boolean.TRUE) != null;
+        }
+        public void clear() {
+            if (visited != null) visited.clear();
+        }
+
+        // An object that considers that no logger has ever been visited.
+        // This is used when processParentHandlers is called from
+        // LoggerContext.addLocalLogger
+        static final VisitedLoggers NEVER = new VisitedLoggers(null);
+    }
+
+
+    /**
+     * Type of the modification for a given property. One of SAME, ADDED, CHANGED,
+     * or REMOVED.
+     */
+    static enum ModType {
+        SAME,    // property had no value in the old and new conf, or had the
+                 // same value in both.
+        ADDED,   // property had no value in the old conf, but has one in the new.
+        CHANGED, // property has a different value in the old conf and the new conf.
+        REMOVED; // property has no value in the new conf, but had one in the old.
+        static ModType of(String previous, String next) {
+            if (previous == null && next != null) {
+                return ADDED;
+            }
+            if (next == null && previous != null) {
+                return REMOVED;
+            }
+            if (!Objects.equals(trim(previous), trim(next))) {
+                return CHANGED;
+            }
+            return SAME;
+        }
+    }
+
+    /**
+     * Updates the logging configuration.
+     * <p>
+     * If the "java.util.logging.config.file" system property is set,
+     * then the property value specifies the properties file to be read
+     * as the new configuration. Otherwise, the LogManager default
+     * configuration is used.
+     * <br>The default configuration is typically loaded from the
+     * properties file "{@code conf/logging.properties}" in the
+     * Java installation directory.
+     * <p>
+     * This method reads the new configuration and calls the {@link
+     * #updateConfiguration(java.io.InputStream, java.util.function.Function)
+     * updateConfiguration(ins, mapper)} method to
+     * update the configuration.
+     *
+     * @apiNote
+     * This method updates the logging configuration from reading
+     * a properties file and ignores the "java.util.logging.config.class"
+     * system property.  The "java.util.logging.config.class" property is
+     * only used by the {@link #readConfiguration()}  method to load a custom
+     * configuration class as an initial configuration.
+     *
+     * @param mapper a functional interface that takes a configuration
+     *   key <i>k</i> and returns a function <i>f(o,n)</i> whose returned
+     *   value will be applied to the resulting configuration. The
+     *   function <i>f</i> may return {@code null} to indicate that the property
+     *   <i>k</i> will not be added to the resulting configuration.
+     *   <br>
+     *   If {@code mapper} is {@code null} then {@code (k) -> ((o, n) -> n)} is
+     *   assumed.
+     *   <br>
+     *   For each <i>k</i>, the mapped function <i>f</i> will
+     *   be invoked with the value associated with <i>k</i> in the old
+     *   configuration (i.e <i>o</i>) and the value associated with
+     *   <i>k</i> in the new configuration (i.e. <i>n</i>).
+     *   <br>A {@code null} value for <i>o</i> or <i>n</i> indicates that no
+     *   value was present for <i>k</i> in the corresponding configuration.
+     *
+     * @throws  SecurityException  if a security manager exists and if
+     *          the caller does not have LoggingPermission("control"), or
+     *          does not have the permissions required to set up the
+     *          configuration (e.g. open file specified for FileHandlers
+     *          etc...)
+     *
+     * @throws  NullPointerException  if {@code mapper} returns a {@code null}
+     *         function when invoked.
+     *
+     * @throws  IOException if there are problems reading from the
+     *          logging configuration file.
+     *
+     * @see #updateConfiguration(java.io.InputStream, java.util.function.Function)
+     */
+    public void updateConfiguration(Function<String, BiFunction<String,String,String>> mapper)
+            throws IOException {
+        checkPermission();
+        ensureLogManagerInitialized();
+        drainLoggerRefQueueBounded();
+
+        String fname = getConfigurationFileName();
+        try (final InputStream in = new FileInputStream(fname)) {
+            final BufferedInputStream bin = new BufferedInputStream(in);
+            updateConfiguration(bin, mapper);
+        }
+    }
+
+    /**
+     * Updates the logging configuration.
+     * <p>
+     * For each configuration key in the {@linkplain
+     * #getProperty(java.lang.String) existing configuration} and
+     * the given input stream configuration, the given {@code mapper} function
+     * is invoked to map from the configuration key to a function,
+     * <i>f(o,n)</i>, that takes the old value and new value and returns
+     * the resulting value to be applied in the resulting configuration,
+     * as specified in the table below.
+     * <p>Let <i>k</i> be a configuration key in the old or new configuration,
+     * <i>o</i> be the old value (i.e. the value associated
+     * with <i>k</i> in the old configuration), <i>n</i> be the
+     * new value (i.e. the value associated with <i>k</i> in the new
+     * configuration), and <i>f</i> be the function returned
+     * by {@code mapper.apply(}<i>k</i>{@code )}: then <i>v = f(o,n)</i> is the
+     * resulting value. If <i>v</i> is not {@code null}, then a property
+     * <i>k</i> with value <i>v</i> will be added to the resulting configuration.
+     * Otherwise, it will be omitted.
+     * <br>A {@code null} value may be passed to function
+     * <i>f</i> to indicate that the corresponding configuration has no
+     * configuration key <i>k</i>.
+     * The function <i>f</i> may return {@code null} to indicate that
+     * there will be no value associated with <i>k</i> in the resulting
+     * configuration.
+     * <p>
+     * If {@code mapper} is {@code null}, then <i>v</i> will be set to
+     * <i>n</i>.
+     * <p>
+     * LogManager {@linkplain #getProperty(java.lang.String) properties} are
+     * updated with the resulting value in the resulting configuration.
+     * <p>
+     * The registered {@linkplain #addConfigurationListener configuration
+     * listeners} will be invoked after the configuration is successfully updated.
+     * <br><br>
+     * <table summary="Updating configuration properties">
+     * <tr>
+     * <th>Property</th>
+     * <th>Resulting Behavior</th>
+     * </tr>
+     * <tr>
+     * <td valign="top">{@code <logger>.level}</td>
+     * <td>
+     * <ul>
+     *   <li>If the resulting configuration defines a level for a logger and
+     *       if the resulting level is different than the level specified in the
+     *       the old configuration, or not specified in
+     *       the old configuration, then if the logger exists or if children for
+     *       that logger exist, the level for that logger will be updated,
+     *       and the change propagated to any existing logger children.
+     *       This may cause the logger to be created, if necessary.
+     *   </li>
+     *   <li>If the old configuration defined a level for a logger, and the
+     *       resulting configuration doesn't, then this change will not be
+     *       propagated to existing loggers, if any.
+     *       To completely replace a configuration - the caller should therefore
+     *       call {@link #reset() reset} to empty the current configuration,
+     *       before calling {@code updateConfiguration}.
+     *   </li>
+     * </ul>
+     * </td>
+     * <tr>
+     * <td valign="top">{@code <logger>.useParentHandlers}</td>
+     * <td>
+     * <ul>
+     *   <li>If either the resulting or the old value for the useParentHandlers
+     *       property is not null, then if the logger exists or if children for
+     *       that logger exist, that logger will be updated to the resulting
+     *       value.
+     *       The value of the useParentHandlers property is the value specified
+     *       in the configuration; if not specified, the default is true.
+     *   </li>
+     * </ul>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td valign="top">{@code <logger>.handlers}</td>
+     * <td>
+     * <ul>
+     *   <li>If the resulting configuration defines a list of handlers for a
+     *       logger, and if the resulting list is different than the list
+     *       specified in the old configuration for that logger (that could be
+     *       empty), then if the logger exists or its children exist, the
+     *       handlers associated with that logger are closed and removed and
+     *       the new handlers will be created per the resulting configuration
+     *       and added to that logger, creating that logger if necessary.
+     *   </li>
+     *   <li>If the old configuration defined some handlers for a logger, and
+     *       the resulting configuration doesn't, if that logger exists,
+     *       its handlers will be removed and closed.
+     *   </li>
+     *   <li>Changing the list of handlers on an existing logger will cause all
+     *       its previous handlers to be removed and closed, regardless of whether
+     *       they had been created from the configuration or programmatically.
+     *       The old handlers will be replaced by new handlers, if any.
+     *   </li>
+     * </ul>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td valign="top">{@code <handler-name>.*}</td>
+     * <td>
+     * <ul>
+     *   <li>Properties configured/changed on handler classes will only affect
+     *       newly created handlers. If a node is configured with the same list
+     *       of handlers in the old and the resulting configuration, then these
+     *       handlers will remain unchanged.
+     *   </li>
+     * </ul>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td valign="top">{@code config} and any other property</td>
+     * <td>
+     * <ul>
+     *   <li>The resulting value for these property will be stored in the
+     *   LogManager properties, but {@code updateConfiguration} will not parse
+     *   or process their values.
+     *   </li>
+     * </ul>
+     * </td>
+     * </tr>
+     * </table>
+     * <p>
+     * <em>Example mapper functions:</em>
+     * <br><br>
+     * <ul>
+     * <li>Replace all logging properties with the new configuration:
+     * <br><br>{@code     (k) -> ((o, n) -> n)}:
+     * <br><br>this is equivalent to passing a null {@code mapper} parameter.
+     * </li>
+     * <li>Merge the new configuration and old configuration and use the
+     * new value if <i>k</i> exists in the new configuration:
+     * <br><br>{@code     (k) -> ((o, n) -> n == null ? o : n)}:
+     * <br><br>as if merging two collections as follows:
+     * {@code result.putAll(oldc); result.putAll(newc)}.<br></li>
+     * <li>Merge the new configuration and old configuration and use the old
+     * value if <i>k</i> exists in the old configuration:
+     * <br><br>{@code     (k) -> ((o, n) -> o == null ? n : o)}:
+     * <br><br>as if merging two collections as follows:
+     * {@code result.putAll(newc); result.putAll(oldc)}.<br></li>
+     * <li>Replace all properties with the new configuration except the handler
+     * property to configure Logger's handler that is not root logger:
+     * <br>
+     * <pre>{@code (k) -> k.endsWith(".handlers")}
+     *      {@code     ? ((o, n) -> (o == null ? n : o))}
+     *      {@code     : ((o, n) -> n)}</pre>
+     * </li>
+     * </ul>
+     * <p>
+     * To completely reinitialize a configuration, an application can first call
+     * {@link #reset() reset} to fully remove the old configuration, followed by
+     * {@code updateConfiguration} to initialize the new configuration.
+     *
+     * @param ins    a stream to read properties from
+     * @param mapper a functional interface that takes a configuration
+     *   key <i>k</i> and returns a function <i>f(o,n)</i> whose returned
+     *   value will be applied to the resulting configuration. The
+     *   function <i>f</i> may return {@code null} to indicate that the property
+     *   <i>k</i> will not be added to the resulting configuration.
+     *   <br>
+     *   If {@code mapper} is {@code null} then {@code (k) -> ((o, n) -> n)} is
+     *   assumed.
+     *   <br>
+     *   For each <i>k</i>, the mapped function <i>f</i> will
+     *   be invoked with the value associated with <i>k</i> in the old
+     *   configuration (i.e <i>o</i>) and the value associated with
+     *   <i>k</i> in the new configuration (i.e. <i>n</i>).
+     *   <br>A {@code null} value for <i>o</i> or <i>n</i> indicates that no
+     *   value was present for <i>k</i> in the corresponding configuration.
+     *
+     * @throws  SecurityException if a security manager exists and if
+     *          the caller does not have LoggingPermission("control"), or
+     *          does not have the permissions required to set up the
+     *          configuration (e.g. open files specified for FileHandlers)
+     *
+     * @throws  NullPointerException if {@code ins} is null or if
+     *          {@code mapper} returns a null function when invoked.
+     *
+     * @throws  IOException if there are problems reading from the stream,
+     *          or the given stream is not in the
+     *          {@linkplain java.util.Properties properties file} format.
+     */
+    public void updateConfiguration(InputStream ins,
+            Function<String, BiFunction<String,String,String>> mapper)
+            throws IOException {
+        checkPermission();
+        ensureLogManagerInitialized();
+        drainLoggerRefQueueBounded();
+
+        final Properties previous;
+        final Set<String> updatePropertyNames;
+        List<LoggerContext> cxs = Collections.emptyList();
+        final VisitedLoggers visited = new VisitedLoggers();
+        final Properties next = new Properties();
+
+        try {
+            // Load the properties
+            next.load(ins);
+        } catch (IllegalArgumentException x) {
+            // props.load may throw an IllegalArgumentException if the stream
+            // contains malformed Unicode escape sequences.
+            // We wrap that in an IOException as updateConfiguration is
+            // specified to throw IOException if there are problems reading
+            // from the stream.
+            // Note: new IOException(x.getMessage(), x) allow us to get a more
+            // concise error message than new IOException(x);
+            throw new IOException(x.getMessage(), x);
+        }
+
+        if (globalHandlersState == STATE_SHUTDOWN) return;
+
+        // exclusive lock: readConfiguration/reset/updateConfiguration can't
+        //           run concurrently.
+        // configurationLock.writeLock().lock();
+        configurationLock.lock();
+        try {
+            if (globalHandlersState == STATE_SHUTDOWN) return;
+            previous = props;
+
+            // Builds a TreeSet of all (old and new) property names.
+            updatePropertyNames =
+                    Stream.concat(previous.stringPropertyNames().stream(),
+                                  next.stringPropertyNames().stream())
+                        .collect(Collectors.toCollection(TreeSet::new));
+
+            if (mapper != null) {
+                // mapper will potentially modify the content of
+                // 'next', so we need to call it before affecting props=next.
+                // give a chance to the mapper to control all
+                // properties - not just those we will reset.
+                updatePropertyNames.stream()
+                        .forEachOrdered(k -> ConfigProperty
+                                .merge(k, previous, next,
+                                       Objects.requireNonNull(mapper.apply(k))));
+            }
+
+            props = next;
+
+            // allKeys will contain all keys:
+            //    - which correspond to a configuration property we are interested in
+            //      (first filter)
+            //    - whose value needs to be updated (because it's new, removed, or
+            //      different) in the resulting configuration (second filter)
+            final Stream<String> allKeys = updatePropertyNames.stream()
+                    .filter(ConfigProperty::matches)
+                    .filter(k -> ConfigProperty.needsUpdating(k, previous, next));
+
+            // Group configuration properties by logger name
+            // We use a TreeMap so that parent loggers will be visited before
+            // child loggers.
+            final Map<String, TreeSet<String>> loggerConfigs =
+                    allKeys.collect(Collectors.groupingBy(ConfigProperty::getLoggerName,
+                                    TreeMap::new,
+                                    Collectors.toCollection(TreeSet::new)));
+
+            if (!loggerConfigs.isEmpty()) {
+                cxs = contexts();
+            }
+            final List<Logger> loggers = cxs.isEmpty()
+                    ? Collections.emptyList() : new ArrayList<>(cxs.size());
+            for (Map.Entry<String, TreeSet<String>> e : loggerConfigs.entrySet()) {
+                // This can be a logger name, or something else...
+                // The only thing we know is that we found a property
+                //    we are interested in.
+                // For instance, if we found x.y.z.level, then x.y.z could be
+                // a logger, but it could also be a handler class...
+                // Anyway...
+                final String name = e.getKey();
+                final Set<String> properties = e.getValue();
+                loggers.clear();
+                for (LoggerContext cx : cxs) {
+                    Logger l = cx.findLogger(name);
+                    if (l != null && !visited.test(l)) {
+                        loggers.add(l);
+                    }
+                }
+                if (loggers.isEmpty()) continue;
+                for (String pk : properties) {
+                    ConfigProperty cp = ConfigProperty.find(pk).get();
+                    String p = previous.getProperty(pk, null);
+                    String n = next.getProperty(pk, null);
+
+                    // Determines the type of modification.
+                    ModType mod = ModType.of(p, n);
+
+                    // mod == SAME means that the two values are equals, there
+                    // is nothing to do. Usually, this should not happen as such
+                    // properties should have been filtered above.
+                    // It could happen however if the properties had
+                    // trailing/leading whitespaces.
+                    if (mod == ModType.SAME) continue;
+
+                    switch (cp) {
+                        case LEVEL:
+                            if (mod == ModType.REMOVED) continue;
+                            Level level = Level.findLevel(trim(n));
+                            if (level != null) {
+                                if (name.isEmpty()) {
+                                    rootLogger.setLevel(level);
+                                }
+                                for (Logger l : loggers) {
+                                    if (!name.isEmpty() || l != rootLogger) {
+                                        l.setLevel(level);
+                                    }
+                                }
+                            }
+                            break;
+                        case USEPARENT:
+                            if (!name.isEmpty()) {
+                                boolean useParent = getBooleanProperty(pk, true);
+                                if (n != null || p != null) {
+                                    // reset the flag only if the previous value
+                                    // or the new value are not null.
+                                    for (Logger l : loggers) {
+                                        l.setUseParentHandlers(useParent);
+                                    }
+                                }
+                            }
+                            break;
+                        case HANDLERS:
+                            List<Handler> hdls = null;
+                            if (name.isEmpty()) {
+                                // special handling for the root logger.
+                                globalHandlersState = STATE_READING_CONFIG;
+                                try {
+                                    closeHandlers(rootLogger);
+                                    globalHandlersState = STATE_UNINITIALIZED;
+                                } catch (Throwable t) {
+                                    globalHandlersState = STATE_INITIALIZED;
+                                    throw t;
+                                }
+                            }
+                            for (Logger l : loggers) {
+                                if (l == rootLogger) continue;
+                                closeHandlers(l);
+                                if (mod == ModType.REMOVED) {
+                                    closeOnResetLoggers.removeIf(c -> c.logger == l);
+                                    continue;
+                                }
+                                if (hdls == null) {
+                                    hdls = name.isEmpty()
+                                            ? Arrays.asList(rootLogger.getHandlers())
+                                            : createLoggerHandlers(name, pk);
+                                }
+                                setLoggerHandlers(l, name, pk, hdls);
+                            }
+                            break;
+                        default: break;
+                    }
+                }
+            }
+        } finally {
+            configurationLock.unlock();
+            visited.clear();
+        }
+
+        // Now ensure that if an existing logger has acquired a new parent
+        // in the configuration, this new parent will be created - if needed,
+        // and added to the context of the existing child.
+        //
+        drainLoggerRefQueueBounded();
+        for (LoggerContext cx : cxs) {
+            for (Enumeration<String> names = cx.getLoggerNames() ; names.hasMoreElements();) {
+                String name = names.nextElement();
+                if (name.isEmpty()) continue;  // don't need to process parents on root.
+                Logger l = cx.findLogger(name);
+                if (l != null && !visited.test(l)) {
+                    // should pass visited here to cut the processing when
+                    // reaching a logger already visited.
+                    cx.processParentHandlers(l, name, visited);
+                }
+            }
+        }
+
+        // We changed the configuration: invoke configuration listeners
+        invokeConfigurationListeners();
+    }
+
     /**
      * Get the value of a logging property.
      * The method returns null if the property is not found.
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/TimeZoneNames_en_GB.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/TimeZoneNames_en_GB.java	Wed Jul 05 20:54:58 2017 +0200
@@ -47,7 +47,8 @@
     protected final Object[][] getContents() {
         return new Object[][] {
             {"Europe/London", new String[] {"Greenwich Mean Time", "GMT",
-                                            "British Summer Time", "BST"}},
+                                            "British Summer Time", "BST",
+                                            "British Time", "BT"}},
         };
     }
 }
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java	Wed Jul 05 20:54:58 2017 +0200
@@ -40,7 +40,8 @@
             {"Asia/Calcutta",
                 new String[] {
                     "\u092d\u093e\u0930\u0924\u0940\u092f \u0938\u092e\u092f", "IST",
-                    "\u092d\u093e\u0930\u0924\u0940\u092f \u0938\u092e\u092f", "IST"
+                    "\u092d\u093e\u0930\u0924\u0940\u092f \u0938\u092e\u092f", "IST",
+                    "\u092d\u093e\u0930\u0924\u0940\u092f \u0938\u092e\u092f", "IT"
                 }
             },
         };
--- a/jdk/test/java/lang/Math/CubeRootTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/Math/CubeRootTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main CubeRootTests
  * @bug 4347132 4939441 8078672
  * @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/HypotTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/Math/HypotTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main HypotTests
  * @bug 4851638 4939441 8078672
  * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/IeeeRecommendedTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main IeeeRecommendedTests
  * @bug 4860891 4826732 4780454 4939441 4826652 8078672
  * @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/Log1pTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/Math/Log1pTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @run main Log1pTests
  * @bug 4851638 4939441 8078672
  * @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/StrictMath/CubeRootTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/StrictMath/CubeRootTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,20 @@
 
 /*
  * @test
- * @bug 4347132
+ * @bug 4347132 8136799
+ * @key randomness
+ * @library /lib/testlibrary/
+ * @build jdk.testlibrary.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build CubeRootTests
+ * @run main CubeRootTests
  * @summary Tests specifically for StrictMath.cbrt
  * @author Joseph D. Darcy
  */
 
+import jdk.testlibrary.RandomFactory;
+
 /**
  * The tests in ../Math/CubeRootTests.java test properties that should
  * hold for any cube root implementation, including the FDLIBM-based
@@ -42,6 +51,19 @@
 public class CubeRootTests {
     private CubeRootTests(){}
 
+    public static void main(String [] argv) {
+        int failures = 0;
+
+        failures += testCubeRoot();
+        failures += testAgainstTranslit();
+
+        if (failures > 0) {
+            System.err.println("Testing the cube root incurred "
+                               + failures + " failures.");
+            throw new RuntimeException();
+        }
+    }
+
     static int testCubeRootCase(double input, double expected) {
         int failures=0;
 
@@ -458,16 +480,44 @@
         return failures;
     }
 
+    // Initialize shared random number generator
+    private static java.util.Random random = RandomFactory.getRandom();
 
-    public static void main(String [] argv) {
+    /**
+     * Test StrictMath.cbrt against transliteration port of cbrt.
+     */
+    private static int testAgainstTranslit() {
         int failures = 0;
+        double x;
 
-        failures += testCubeRoot();
+        // Test just above subnormal threshold...
+        x = Double.MIN_NORMAL;
+        failures += testRange(x, Math.ulp(x), 1000);
+
+        // ... and just below subnormal threshold ...
+        x =  Math.nextDown(Double.MIN_NORMAL);
+        failures += testRange(x, -Math.ulp(x), 1000);
 
-        if (failures > 0) {
-            System.err.println("Testing the cube root incurred "
-                               + failures + " failures.");
-            throw new RuntimeException();
+        // ... and near zero.
+        failures += testRange(0.0, Double.MIN_VALUE, 1000);
+
+        x = Tests.createRandomDouble(random);
+
+        // Make the increment twice the ulp value in case the random
+        // value is near an exponent threshold. Don't worry about test
+        // elements overflowing to infinity if the starting value is
+        // near Double.MAX_VALUE.
+        failures += testRange(x, 2.0 * Math.ulp(x), 1000);
+
+        return failures;
+    }
+
+    private static int testRange(double start, double increment, int count) {
+        int failures = 0;
+        double x = start;
+        for (int i = 0; i < count; i++, x += increment) {
+            failures += testCubeRootCase(x, FdlibmTranslit.Cbrt.compute(x));
         }
+        return failures;
     }
 }
--- a/jdk/test/java/lang/StrictMath/FdlibmTranslit.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/StrictMath/FdlibmTranslit.java	Wed Jul 05 20:54:58 2017 +0200
@@ -73,6 +73,67 @@
     }
 
     /**
+     * cbrt(x)
+     * Return cube root of x
+     */
+    public static class Cbrt {
+        // unsigned
+        private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+        private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+        private static final double C =  5.42857142857142815906e-01; /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
+        private static final double D = -7.05306122448979611050e-01; /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+        private static final double E =  1.41428571428571436819e+00; /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
+        private static final double F =  1.60714285714285720630e+00; /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
+        private static final double G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+        public static strictfp double compute(double x) {
+            int     hx;
+            double  r, s, t=0.0, w;
+            int sign; // unsigned
+
+            hx = __HI(x);           // high word of x
+            sign = hx & 0x80000000;             // sign= sign(x)
+            hx  ^= sign;
+            if (hx >= 0x7ff00000)
+                return (x+x); // cbrt(NaN,INF) is itself
+            if ((hx | __LO(x)) == 0)
+                return(x);          // cbrt(0) is itself
+
+            x = __HI(x, hx);   // x <- |x|
+            // rough cbrt to 5 bits
+            if (hx < 0x00100000) {               // subnormal number
+                t = __HI(t, 0x43500000);          // set t= 2**54
+                t *= x;
+                t = __HI(t, __HI(t)/3+B2);
+            } else {
+                t = __HI(t, hx/3+B1);
+            }
+
+            // new cbrt to 23 bits, may be implemented in single precision
+            r = t * t/x;
+            s = C + r*t;
+            t *= G + F/(s + E + D/s);
+
+            // chopped to 20 bits and make it larger than cbrt(x)
+            t = __LO(t, 0);
+            t = __HI(t, __HI(t)+0x00000001);
+
+
+            // one step newton iteration to 53 bits with error less than 0.667 ulps
+            s = t * t;          // t*t is exact
+            r = x / s;
+            w = t + t;
+            r= (r - t)/(w + r);  // r-s is exact
+            t= t + t*r;
+
+            // retore the sign bit
+            t = __HI(t, __HI(t) | sign);
+            return(t);
+        }
+    }
+
+    /**
      * hypot(x,y)
      *
      * Method :
--- a/jdk/test/java/lang/StrictMath/HypotTests.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/lang/StrictMath/HypotTests.java	Wed Jul 05 20:54:58 2017 +0200
@@ -27,7 +27,7 @@
  * @key randomness
  * @summary Tests for StrictMath.hypot
  * @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
  * @build Tests
  * @build FdlibmTranslit
  * @build HypotTests
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/rmi/registry/readTest/readTest.sh	Wed Jul 05 20:54:58 2017 +0200
@@ -27,6 +27,7 @@
 # @build TestLibrary
 # @summary remove java.rmi.server.codebase property parsing from registyimpl
 # @run shell readTest.sh
+# @key intermittent
 
 OS=`uname -s`
 VER=`uname -r`
--- a/jdk/test/java/util/AbstractList/CheckForComodification.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/AbstractList/CheckForComodification.java	Wed Jul 05 20:54:58 2017 +0200
@@ -42,7 +42,7 @@
             for (int i : list)
                 if (i == LENGTH - 2)
                     list.remove(i);
-        } catch(ConcurrentModificationException e) {
+        } catch (ConcurrentModificationException e) {
             return;
         }
         throw new RuntimeException("No ConcurrentModificationException");
--- a/jdk/test/java/util/AbstractList/FailFastIterator.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/AbstractList/FailFastIterator.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4189896
- * @summary AbstractList iterators previously checked for co-modificatin
+ * @summary AbstractList iterators previously checked for co-modification
  *          *after* the set/add/remove operations were performed.
  */
 
@@ -44,7 +44,7 @@
             copy.add(new Integer(99));
             i.remove();
             throw new Exception("remove: iterator didn't fail fast");
-        } catch(ConcurrentModificationException e) {
+        } catch (ConcurrentModificationException e) {
         }
         if (!copy.equals(orig))
             throw new Exception("remove: iterator didn't fail fast enough");
@@ -56,7 +56,7 @@
             copy.add(new Integer(99));
             i.set(new Integer(666));
             throw new Exception("set: iterator didn't fail fast");
-        } catch(ConcurrentModificationException e) {
+        } catch (ConcurrentModificationException e) {
         }
         if (!copy.equals(orig))
             throw new Exception("set: iterator didn't fail fast enough");
@@ -67,7 +67,7 @@
             copy.add(new Integer(99));
             i.add(new Integer(666));
             throw new Exception("add: iterator didn't fail fast");
-        } catch(ConcurrentModificationException e) {
+        } catch (ConcurrentModificationException e) {
         }
         if (!copy.equals(orig))
             throw new Exception("add: iterator didn't fail fast enough");
--- a/jdk/test/java/util/Collection/BiggernYours.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collection/BiggernYours.java	Wed Jul 05 20:54:58 2017 +0200
@@ -41,16 +41,16 @@
         Object[] c2Array = c2.toArray();
 
         check(c1Array.length == c2Array.length);
-        for(Object aC1 : c1Array) {
+        for (Object aC1 : c1Array) {
             boolean found = false;
-            for(Object aC2 : c2Array) {
-                if(Objects.equals(aC1, aC2)) {
+            for (Object aC2 : c2Array) {
+                if (Objects.equals(aC1, aC2)) {
                     found = true;
                     break;
                 }
             }
 
-            if(!found)
+            if (!found)
                 fail(aC1 + " not found in " + Arrays.toString(c2Array));
         }
     }
--- a/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 20:54:58 2017 +0200
@@ -101,7 +101,12 @@
 
         testMap(new HashMap<Integer,Integer>());
         testMap(new LinkedHashMap<Integer,Integer>());
-        testMap(new WeakHashMap<Integer,Integer>());
+
+        // TODO: Add reliable support for WeakHashMap.
+        // This test is subject to very rare failures because the GC
+        // may remove unreferenced-keys from the map at any time.
+        // testMap(new WeakHashMap<Integer,Integer>());
+
         testMap(new IdentityHashMap<Integer,Integer>());
         testMap(new TreeMap<Integer,Integer>());
         testMap(new Hashtable<Integer,Integer>());
@@ -343,6 +348,12 @@
         return true;
     }
 
+    // 6260652: (coll) Arrays.asList(x).toArray().getClass()
+    //          should be Object[].class
+    // Fixed in jdk9, but not jdk8 ...
+    static final boolean needToWorkAround6260652 =
+        Arrays.asList("").toArray().getClass() != Object[].class;
+
     private static void checkFunctionalInvariants(Collection<Integer> c) {
         try {
             checkContainsSelf(c);
@@ -356,7 +367,10 @@
             }
 
             check(c.toArray().length == c.size());
-            check(c.toArray().getClass() == Object[].class);
+            check(c.toArray().getClass() == Object[].class
+                  ||
+                  (needToWorkAround6260652 &&
+                   c.getClass().getName().equals("java.util.Arrays$ArrayList")));
             for (int size : new int[]{0,1,c.size(), c.size()+1}) {
                 Integer[] a = c.toArray(new Integer[size]);
                 check((size > c.size()) || a.length == c.size());
@@ -408,7 +422,6 @@
         catch (Throwable t) { unexpected(t); }
     }
 
-
     //----------------------------------------------------------------
     // If add("x") succeeds, contains("x") & remove("x") should succeed
     //----------------------------------------------------------------
@@ -1291,7 +1304,7 @@
 
         equalNext(descItr, expected[idx--]);
         descItr.remove();
-        while(idx >= 0 && descItr.hasNext()) {
+        while (idx >= 0 && descItr.hasNext()) {
             equalNext(descItr, expected[idx--]);
         }
         equal(descItr.hasNext(), false);
--- a/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java	Wed Jul 05 20:54:58 2017 +0200
@@ -113,7 +113,7 @@
         }
 
         Set<T> uniq = new HashSet<>();
-        while(iter.hasNext()) {
+        while (iter.hasNext()) {
             T each = iter.next();
             assertTrue(!uniq.contains(each));
             uniq.add(each);
@@ -209,7 +209,7 @@
             assertTrue(!pI.hasNext());
         }
 
-        while(mI.hasNext()) {
+        while (mI.hasNext()) {
             pI = mI.next().iterator();
             assertTrue(!pI.hasNext());
         }
--- a/jdk/test/java/util/Collections/BigBinarySearch.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/BigBinarySearch.java	Wed Jul 05 20:54:58 2017 +0200
@@ -61,13 +61,13 @@
         }
     }
 
-    /** Check that binarySearch finds an element where we got it */
+    /** Checks that binarySearch finds an element where we got it. */
     private static void checkBinarySearch(List<Integer> l, int i) {
         try { equal(i, Collections.binarySearch(l, l.get(i))); }
         catch (Throwable t) { unexpected(t); }
     }
 
-    /** Check that binarySearch finds an element where we got it */
+    /** Checks that binarySearch finds an element where we got it. */
     private static void checkBinarySearch(List<Integer> l, int i,
                                           Comparator<Integer> comparator) {
         try { equal(i, Collections.binarySearch(l, l.get(i), comparator)); }
--- a/jdk/test/java/util/Collections/BinarySearchNullComparator.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/BinarySearchNullComparator.java	Wed Jul 05 20:54:58 2017 +0200
@@ -27,11 +27,10 @@
  * @summary Test Collections.binarySearch() with a null comparator
  */
 
-
 import java.util.*;
 
 public class BinarySearchNullComparator {
-    public static void main (String args[]) throws Exception {
+    public static void main(String args[]) throws Exception {
         List list = Arrays.asList(new String[] {"I", "Love", "You"});
 
         int result = Collections.binarySearch(list, "You", null);
--- a/jdk/test/java/util/Collections/CheckedListBash.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/CheckedListBash.java	Wed Jul 05 20:54:58 2017 +0200
@@ -109,19 +109,19 @@
 
         List even = clone(s);
         Iterator it = even.iterator();
-        while(it.hasNext())
-            if(((Integer)it.next()).intValue() % 2 == 1)
+        while (it.hasNext())
+            if (((Integer)it.next()).intValue() % 2 == 1)
                 it.remove();
         it = even.iterator();
-        while(it.hasNext())
-            if(((Integer)it.next()).intValue() % 2 == 1)
+        while (it.hasNext())
+            if (((Integer)it.next()).intValue() % 2 == 1)
                 fail("Failed to remove all odd nubmers.");
 
         List odd = clone(s);
         for (int i=0; i<(listSize/2); i++)
             odd.remove(i);
         for (int i=0; i<(listSize/2); i++)
-            if(((Integer)odd.get(i)).intValue() % 2 != 1)
+            if (((Integer)odd.get(i)).intValue() % 2 != 1)
                 fail("Failed to remove all even nubmers.");
 
         List all = clone(odd);
@@ -145,8 +145,8 @@
         }
         itAll = all.listIterator();
         it = s.iterator();
-        while(it.hasNext())
-            if(it.next()==itAll.next())
+        while (it.hasNext())
+            if (it.next()==itAll.next())
                 fail("Iterator.set failed to change value.");
         if (!all.equals(s))
             fail("Failed to reconstruct ints with ListIterator.");
@@ -215,10 +215,10 @@
 
             int preSize = s.size();
             if (!s.add(e))
-                fail ("Add failed.");
+                fail("Add failed.");
             int postSize = s.size();
             if (postSize-preSize != 1)
-                fail ("Add didn't increase size by 1.");
+                fail("Add didn't increase size by 1.");
         }
     }
 
--- a/jdk/test/java/util/Collections/CheckedMapBash.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/CheckedMapBash.java	Wed Jul 05 20:54:58 2017 +0200
@@ -134,7 +134,7 @@
             fail("clear failed.");
 
         Iterator i = m.entrySet().iterator();
-        while(i.hasNext()) {
+        while (i.hasNext()) {
             i.next();
             i.remove();
         }
@@ -142,12 +142,11 @@
             fail("Iterator.remove() failed");
     }
 
-
     @DataProvider(name = "Bash.Supplier<Map<Integer,Integer>>", parallel = true)
     public static Iterator<Object[]> bashNavigableMapProvider() {
         ArrayList<Object[]> iters = new ArrayList<>(makeCheckedMaps());
         iters.ensureCapacity(numItr * iters.size());
-        for(int each=1; each < numItr; each++) {
+        for (int each=1; each < numItr; each++) {
             iters.addAll( makeCheckedMaps());
         }
         return iters.iterator();
--- a/jdk/test/java/util/Collections/CheckedSetBash.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/CheckedSetBash.java	Wed Jul 05 20:54:58 2017 +0200
@@ -130,14 +130,14 @@
             boolean prePresent = s.contains(e);
             boolean added = s.add(e);
             if (!s.contains(e))
-                fail ("Element not present after addition.");
+                fail("Element not present after addition.");
             if (added == prePresent)
-                fail ("added == alreadyPresent");
+                fail("added == alreadyPresent");
             int postSize = s.size();
             if (added && preSize == postSize)
-                fail ("Add returned true, but size didn't change.");
+                fail("Add returned true, but size didn't change.");
             if (!added && preSize != postSize)
-                fail ("Add returned false, but size changed.");
+                fail("Add returned false, but size changed.");
         }
     }
 
@@ -145,7 +145,7 @@
     public static Iterator<Object[]> navigableSetsProvider() {
         ArrayList<Object[]> iters = new ArrayList<>(makeCheckedSets());
         iters.ensureCapacity(numItr * iters.size());
-        for(int each=1; each < numItr; each++) {
+        for (int each=1; each < numItr; each++) {
             iters.addAll( makeCheckedSets());
         }
         return iters.iterator();
--- a/jdk/test/java/util/Collections/EmptyCollectionSerialization.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/EmptyCollectionSerialization.java	Wed Jul 05 20:54:58 2017 +0200
@@ -62,7 +62,7 @@
                 copy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(copy)) +
                 " is not the singleton " +
                 singleton.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(singleton)));
-        } catch(Exception all) {
+        } catch (Exception all) {
             fail(description + ": Unexpected Exception", all);
         }
     }
--- a/jdk/test/java/util/Collections/EmptyIterator.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/EmptyIterator.java	Wed Jul 05 20:54:58 2017 +0200
@@ -29,13 +29,14 @@
 
 import static java.util.Collections.*;
 import java.util.*;
+import java.util.concurrent.SynchronousQueue;
 
 public class EmptyIterator {
 
     void test(String[] args) throws Throwable {
         testEmptyCollection(emptyList());
         testEmptyCollection(emptySet());
-
+        testEmptyCollection(new SynchronousQueue<Object>());
         testEmptyMap(emptyMap());
 
         Hashtable<?,?> emptyTable = new Hashtable<>();
--- a/jdk/test/java/util/Collections/EmptyNavigableMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/EmptyNavigableMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -282,7 +282,7 @@
 
         // slightly smaller
         NavigableMap ns = subMap.subMap(first, false, last, false);
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.subMap(first, true, last, true);
         },
@@ -303,7 +303,7 @@
         // slightly smaller
         NavigableMap ns = subMap.headMap(BigInteger.ONE, false);
 
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.headMap(BigInteger.ONE, true);
         },
@@ -324,7 +324,7 @@
         // slightly smaller
         NavigableMap ns = subMap.tailMap(BigInteger.ONE, false);
 
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.tailMap(BigInteger.ONE, true);
         },
--- a/jdk/test/java/util/Collections/EmptyNavigableSet.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/EmptyNavigableSet.java	Wed Jul 05 20:54:58 2017 +0200
@@ -301,7 +301,7 @@
 
         // slightly smaller
         NavigableSet ns = subSet.subSet(first, false, last, false);
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.subSet(first, true, last, true);
         },
@@ -322,7 +322,7 @@
         // slightly smaller
         NavigableSet ns = subSet.headSet(BigInteger.ONE, false);
 
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.headSet(BigInteger.ONE, true);
         },
@@ -343,7 +343,7 @@
         // slightly smaller
         NavigableSet ns = subSet.tailSet(BigInteger.ONE, false);
 
-        // slight exapansion
+        // slight expansion
         assertThrows(() -> {
             ns.tailSet(BigInteger.ONE, true);
         },
--- a/jdk/test/java/util/Collections/RacingCollections.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/RacingCollections.java	Wed Jul 05 20:54:58 2017 +0200
@@ -62,14 +62,16 @@
             this.start();
         }
 
-        @SuppressWarnings("unchecked") void clear(Object o) {
+        @SuppressWarnings("unchecked")
+        void clear(Object o) {
             if (o instanceof Collection)
                 ((Collection<?>)o).clear();
             else
                 ((Map<?,?>)o).clear();
         }
 
-        @SuppressWarnings("unchecked") void realRun() {
+        @SuppressWarnings("unchecked")
+        void realRun() {
             // Mutate elLoco wildly forever, checking occasionally for "done"
             clear(elLoco);
             if (elLoco instanceof List) {
@@ -156,7 +158,7 @@
             quittingTime = System.nanoTime() + workTimeMillis * 1024 * 1024;
         }
         boolean keepGoing() {
-            return (i++ % 128 != 0) || (System.nanoTime() < quittingTime);
+            return (i++ % 128 != 0) || (System.nanoTime() - quittingTime < 0);
         }
     }
 
@@ -233,6 +235,7 @@
     private static List<Queue<Integer>> newConcurrentQueues() {
         List<Queue<Integer>> list =
             new ArrayList<Queue<Integer>>(newConcurrentDeques());
+        list.add(new ArrayBlockingQueue<Integer>(10));
         list.add(new LinkedBlockingQueue<Integer>(10));
         list.add(new LinkedTransferQueue<Integer>());
         list.add(new ConcurrentLinkedQueue<Integer>());
--- a/jdk/test/java/util/Collections/ReverseOrder.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/ReverseOrder.java	Wed Jul 05 20:54:58 2017 +0200
@@ -25,7 +25,7 @@
  * @test
  * @bug 4593209 8001667
  * @summary Reverse comparator was subtly broken
- * @author Josh bloch
+ * @author Josh Bloch
  */
 
 import java.util.*;
--- a/jdk/test/java/util/Collections/RotateEmpty.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/RotateEmpty.java	Wed Jul 05 20:54:58 2017 +0200
@@ -33,6 +33,6 @@
 
     public static void main(String[] args) throws Exception {
             List l = new ArrayList();
-            Collections.rotate (l, 1);
+            Collections.rotate(l, 1);
     }
 }
--- a/jdk/test/java/util/Collections/T6433170.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/T6433170.java	Wed Jul 05 20:54:58 2017 +0200
@@ -58,7 +58,6 @@
         checkEmpty(checked);
     }
 
-
     //--------------------- Infrastructure ---------------------------
     volatile int passed = 0, failed = 0;
     void pass() {passed++;}
--- a/jdk/test/java/util/Collections/WrappedNull.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Collections/WrappedNull.java	Wed Jul 05 20:54:58 2017 +0200
@@ -33,133 +33,133 @@
 public class WrappedNull {
       public static void main(String argv[]) throws Exception {
           boolean testSucceeded = false;
-          try{
+          try {
               List l = Arrays.asList(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("Arrays.asList");
 
           testSucceeded = false;
-          try{
+          try {
               Collection c = Collections.unmodifiableCollection(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableCollection");
 
           testSucceeded = false;
-          try{
+          try {
               Set c = Collections.unmodifiableSet(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableSet");
 
           testSucceeded = false;
-          try{
+          try {
               List c = Collections.unmodifiableList(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableList");
 
           testSucceeded = false;
-          try{
+          try {
               Map c = Collections.unmodifiableMap(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableMap");
 
           testSucceeded = false;
-          try{
+          try {
               SortedSet c = Collections.unmodifiableSortedSet(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableSortedSet");
 
           testSucceeded = false;
-          try{
+          try {
               SortedMap c = Collections.unmodifiableSortedMap(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("unmodifiableSortedMap");
 
           testSucceeded = false;
-          try{
+          try {
               Collection c = Collections.synchronizedCollection(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedCollection");
 
           testSucceeded = false;
-          try{
+          try {
               Set c = Collections.synchronizedSet(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedSet");
 
           testSucceeded = false;
-          try{
+          try {
               List c = Collections.synchronizedList(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedList");
 
           testSucceeded = false;
-          try{
+          try {
               Map c = Collections.synchronizedMap(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedMap");
 
           testSucceeded = false;
-          try{
+          try {
               SortedSet c = Collections.synchronizedSortedSet(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedSortedSet");
 
           testSucceeded = false;
-          try{
+          try {
               SortedMap c = Collections.synchronizedSortedMap(null);
           }
           catch (NullPointerException e) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("synchronizedSortedMap");
 
           // Make sure that non-null arguments don't throw exc.
--- a/jdk/test/java/util/Hashtable/IllegalLoadFactor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Hashtable/IllegalLoadFactor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -26,8 +26,6 @@
    @summary Test for an illegalargumentexception on loadFactor
 */
 
-
-
 import java.util.*;
 
 /**
@@ -38,92 +36,92 @@
 
       public static void main(String argv[]) throws Exception {
           boolean testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               Hashtable bad1 = new Hashtable(100, -3);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("Hashtable, negative load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               Hashtable bad1 = new Hashtable(100, Float.NaN);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("Hashtable, NaN load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               HashMap bad1 = new HashMap(100, -3);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("HashMap, negative load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               HashMap bad1 = new HashMap(100, Float.NaN);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("HashMap, NaN load factor");
 
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               HashSet bad1 = new HashSet(100, -3);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("HashSet, negative load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               HashSet bad1 = new HashSet(100, Float.NaN);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("HashSet, NaN load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               WeakHashMap bad1 = new WeakHashMap(100, -3);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("WeakHashMap, negative load factor");
 
           testSucceeded = false;
-          try{
+          try {
               // this should generate an IllegalArgumentException
               WeakHashMap bad1 = new WeakHashMap(100, Float.NaN);
           }
           catch (IllegalArgumentException e1) {
               testSucceeded = true;
           }
-          if(!testSucceeded)
+          if (!testSucceeded)
               throw new Exception("WeakHashMap, NaN load factor");
 
           // Make sure that legal creates don't throw exceptions
--- a/jdk/test/java/util/Hashtable/ReadObject.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Hashtable/ReadObject.java	Wed Jul 05 20:54:58 2017 +0200
@@ -57,13 +57,13 @@
     public Object get(Object key) {
         ValueWrapper valueWrapper = (ValueWrapper)super.get(key);
         Object value = valueWrapper.getValue();
-        if(value instanceof ValueWrapper)
+        if (value instanceof ValueWrapper)
             throw new RuntimeException("Hashtable.get bug");
         return value;
     }
 
     public Object put(Object key, Object value) {
-        if(value instanceof ValueWrapper)
+        if (value instanceof ValueWrapper)
             throw new RuntimeException(
                 "Hashtable.put bug: value is already wrapped");
         ValueWrapper valueWrapper = new ValueWrapper(value);
@@ -98,4 +98,4 @@
         ReadObject myHashtableCopy = (ReadObject)copyObject(myHashtable);
         String value = (String)myHashtableCopy.get("key");
     }
-};
+}
--- a/jdk/test/java/util/IdentityHashMap/ToString.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/IdentityHashMap/ToString.java	Wed Jul 05 20:54:58 2017 +0200
@@ -28,7 +28,6 @@
  * @author  Josh Bloch
  */
 
-
 import java.util.*;
 
 public class ToString {
--- a/jdk/test/java/util/LinkedHashMap/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/LinkedHashMap/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -83,12 +83,12 @@
         Map<Integer,Integer> m = new LinkedHashMap();
         for (int i=0; i<mapSize; i++)
             if (m.put(new Integer(i), new Integer(2*i)) != null)
-                throw new Exception("put returns non-null value erroenously.");
+                throw new Exception("put returns non-null value erroneously.");
         for (int i=0; i<2*mapSize; i++)
             if (m.containsValue(new Integer(i)) != (i%2==0))
                 throw new Exception("contains value "+i);
         if (m.put(nil, nil) == null)
-            throw new Exception("put returns a null value erroenously.");
+            throw new Exception("put returns a null value erroneously.");
         Map<Integer,Integer> m2 = new LinkedHashMap(); m2.putAll(m);
         if (!m.equals(m2))
             throw new Exception("Clone not equal to original. (1)");
@@ -129,7 +129,7 @@
             throw new Exception("clear failed.");
 
         Iterator it = m.entrySet().iterator();
-        while(it.hasNext()) {
+        while (it.hasNext()) {
             it.next();
             it.remove();
         }
@@ -240,8 +240,8 @@
 
         for (int i=0; i<mapSize; i++) {
             Integer x = (Integer) l2.get(i);
-            if(!x.equals(m.remove(x)))
-              throw new Exception("Missing key: "+i+", "+x);
+            if (!x.equals(m.remove(x)))
+                throw new Exception("Missing key: "+i+", "+x);
             if (!x.equals(m.computeIfAbsent(x, Integer::valueOf)))
                 throw new Exception("Wrong value: "+i+", "+m.get(x)+", "+x);
         }
@@ -292,7 +292,7 @@
             ObjectInputStream in = new ObjectInputStream(bis);
             result = (Map)in.readObject();
             in.close();
-        } catch(Exception e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
         return result;
--- a/jdk/test/java/util/LinkedHashMap/Cache.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/LinkedHashMap/Cache.java	Wed Jul 05 20:54:58 2017 +0200
@@ -33,7 +33,7 @@
     private static final int MAP_SIZE = 10;
     private static final int NUM_KEYS = 100;
 
-    public static void main(String[] args)  throws Exception {
+    public static void main(String[] args) throws Exception {
         Map m = new LinkedHashMap() {
             protected boolean removeEldestEntry(Map.Entry eldest) {
                 return size() > MAP_SIZE;
--- a/jdk/test/java/util/LinkedHashSet/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/LinkedHashSet/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -99,7 +99,7 @@
     static Set clone(Set s) throws Exception {
         Set clone;
         int method = rnd.nextInt(3);
-        clone = (method==0 ?  (Set) ((LinkedHashSet)s).clone() :
+        clone = (method==0 ? (Set) ((LinkedHashSet)s).clone() :
                  (method==1 ? new LinkedHashSet(Arrays.asList(s.toArray())) :
                   serClone(s)));
         if (!s.equals(clone))
@@ -126,7 +126,7 @@
             ObjectInputStream in = new ObjectInputStream(bis);
             result = (Set)in.readObject();
             in.close();
-        } catch(Exception e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
         return result;
--- a/jdk/test/java/util/LinkedList/Clone.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/LinkedList/Clone.java	Wed Jul 05 20:54:58 2017 +0200
@@ -74,7 +74,7 @@
             throw new RuntimeException("TreeMap.clone() is broken.");
     }
 
-    private static class LinkedList2 extends LinkedList {};
-    private static class TreeSet2    extends TreeSet {};
-    private static class TreeMap2    extends TreeMap {};
+    private static class LinkedList2 extends LinkedList {}
+    private static class TreeSet2    extends TreeSet {}
+    private static class TreeMap2    extends TreeMap {}
 }
--- a/jdk/test/java/util/LinkedList/ComodifiedRemove.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/LinkedList/ComodifiedRemove.java	Wed Jul 05 20:54:58 2017 +0200
@@ -41,10 +41,10 @@
         list.add(o1);
         ListIterator e = list.listIterator();
         e.next();
-        Object o2 = new Integer (2);
+        Object o2 = new Integer(2);
         list.add(o2);
 
-        try{
+        try {
             e.remove();
         } catch (ConcurrentModificationException cme) {
             return;
--- a/jdk/test/java/util/List/ListDefaults.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/List/ListDefaults.java	Wed Jul 05 20:54:58 2017 +0200
@@ -381,7 +381,7 @@
                 minBitCount = bitCount;
             }
 
-            // Resuse the supplier to store AtomicInteger instead of Integer
+            // Reuse the supplier to store AtomicInteger instead of Integer
             // Hence the use of raw type and cast
             List<AtomicInteger> incomparablesData = new ArrayList<>();
             for (int i = 0; i < test.expected.size(); i++) {
--- a/jdk/test/java/util/Map/Defaults.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Map/Defaults.java	Wed Jul 05 20:54:58 2017 +0200
@@ -464,7 +464,7 @@
     @Test(dataProvider = "MergeCases")
     private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
             // add and check initial conditions.
-            switch(oldValue) {
+            switch (oldValue) {
                 case ABSENT :
                     map.remove(EXTRA_KEY);
                     assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
@@ -490,7 +490,7 @@
 
             // check result
 
-            switch(result) {
+            switch (result) {
                 case NULL :
                     assertNull(returned, "wrong value");
                     break;
@@ -505,7 +505,7 @@
             }
 
             // check map
-            switch(put) {
+            switch (put) {
                 case ABSENT :
                     assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
                     break;
@@ -610,7 +610,6 @@
         return all;
     }
 
-
     private static Collection<Object[]> makeRWMapsNoNulls() {
         Collection<Object[]> all = new ArrayList<>();
 
@@ -656,8 +655,8 @@
 
         return all;
     }
+
     /**
-     *
      * @param nullKeys include null keys
      * @param nullValues include null values
      * @return
@@ -674,7 +673,6 @@
     }
 
     /**
-     *
      * @param nulls include null values
      * @return
      */
@@ -702,7 +700,6 @@
     }
 
     /**
-     *
      * @param nulls include nulls
      * @return
      */
@@ -712,8 +709,7 @@
         });
     }
 
-     /**
-     *
+    /**
      * @param supplier a supplier of mutable map instances.
      *
      * @param nullKeys   include null keys
@@ -774,15 +770,15 @@
     static Collection<Object[]> makeMergeTestCases() {
         Collection<Object[]> cases = new ArrayList<>();
 
-        for( Object[] mapParams : makeAllRWMaps() ) {
+        for (Object[] mapParams : makeAllRWMaps() ) {
             cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.ABSENT, Merging.Value.NEWVALUE, Merging.Merger.UNUSED, Merging.Value.NEWVALUE, Merging.Value.NEWVALUE });
         }
 
-        for( Object[] mapParams : makeAllRWMaps() ) {
+        for (Object[] mapParams : makeAllRWMaps() ) {
             cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.NULL, Merging.Value.ABSENT, Merging.Value.NULL });
         }
 
-        for( Object[] mapParams : makeAllRWMaps() ) {
+        for (Object[] mapParams : makeAllRWMaps() ) {
             cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.RESULT, Merging.Value.RESULT, Merging.Value.RESULT });
         }
 
@@ -813,7 +809,7 @@
     }
 
     public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
-        for(Thrower<T> thrower : throwers) {
+        for (Thrower<T> thrower : throwers) {
             assertThrows(thrower, throwable, message);
         }
     }
@@ -834,7 +830,7 @@
      * @param <K> Type of keys
      * @param <V> Type of values
      */
-    public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
+    public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K,V> {
 
         protected final M map;
 
@@ -842,8 +838,8 @@
 
         protected ExtendsAbstractMap(M map) { this.map = map; }
 
-        public Set<Map.Entry<K, V>> entrySet() {
-            return new AbstractSet<Map.Entry<K, V>>() {
+        public Set<Map.Entry<K,V>> entrySet() {
+            return new AbstractSet<Map.Entry<K,V>>() {
                 public int size() {
                     return map.size();
                 }
@@ -876,7 +872,7 @@
      * @param <K> Type of keys
      * @param <V> Type of values
      */
-    public static class ImplementsConcurrentMap<K, V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
+    public static class ImplementsConcurrentMap<K,V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
         public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
 
         // ConcurrentMap reabstracts these methods
--- a/jdk/test/java/util/Map/Get.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Map/Get.java	Wed Jul 05 20:54:58 2017 +0200
@@ -119,7 +119,7 @@
     static void check(boolean cond) { if (cond) pass(); else fail(); }
     static void check(String desc, boolean cond) { if (cond) pass(); else fail(desc); }
     static void equal(Object x, Object y) {
-        if(Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
+        if (Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
     }
 
     public static void main(String[] args) throws Throwable {
--- a/jdk/test/java/util/NavigableMap/LockStep.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/NavigableMap/LockStep.java	Wed Jul 05 20:54:58 2017 +0200
@@ -228,8 +228,8 @@
         if (maybe(4) && s instanceof Serializable) {
             try {
                 equal2(s, serialClone(s));
-            } catch(RuntimeException uhoh) {
-                if(!(uhoh.getCause() instanceof NotSerializableException)) {
+            } catch (RuntimeException uhoh) {
+                if (!(uhoh.getCause() instanceof NotSerializableException)) {
                     throw uhoh;
                 }
             }
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java	Wed Jul 05 20:54:58 2017 +0200
@@ -126,19 +126,19 @@
         }
 
         {
-            Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, 0);
+            Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, 0);
             assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
             assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
         }
 
         {
-            Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, Spliterator.CONCURRENT);
+            Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, Spliterator.CONCURRENT);
             assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
             assertCharacteristics(s, Spliterator.CONCURRENT);
         }
 
         {
-            Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator( ), 0);
+            Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator(), 0);
             assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
         }
 
--- a/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -214,7 +214,7 @@
 
         db.addMap(LinkedHashMap::new);
 
-        // This fails when run through jrteg but passes when run though
+        // This fails when run through jtreg but passes when run through
         // ant
 //        db.addMap(IdentityHashMap::new);
 
--- a/jdk/test/java/util/TimSort/Sorter.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/TimSort/Sorter.java	Wed Jul 05 20:54:58 2017 +0200
@@ -46,7 +46,7 @@
 
         for (int i=0; i < 10000; i++) {
             for (Sorter s : values()) {
-                Integer[] test= gold.clone();
+                Integer[] test = gold.clone();
                 s.sort(test);
             }
         }
--- a/jdk/test/java/util/TreeMap/ContainsValue.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/TreeMap/ContainsValue.java	Wed Jul 05 20:54:58 2017 +0200
@@ -30,7 +30,7 @@
 import java.util.*;
 
 public class ContainsValue {
-    public static void main (String[] args) {
+    public static void main(String[] args) {
         Map map = new TreeMap();
 
         if (map.containsValue ("gemutlichkeit"))
--- a/jdk/test/java/util/TreeMap/HeadTailTypeError.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/TreeMap/HeadTailTypeError.java	Wed Jul 05 20:54:58 2017 +0200
@@ -32,71 +32,70 @@
 
 public class HeadTailTypeError {
     public static void main(String argv[]) throws Exception {
-        try{
+        try {
             SortedMap m = new TreeMap();
             m.headMap(new Object());
             throw new Exception("headMap, natural ordering");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedMap m = new TreeMap();
             m.tailMap(new Object());
             throw new Exception("tailMap, natural ordering");
         } catch (ClassCastException e) {
         }
 
-
-        try{
+        try {
             SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
             m.headMap(new Integer(0));
             throw new Exception("headMap, explicit comparator");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
             m.tailMap(new Integer(0));
             throw new Exception("tailMap, explicit comparator");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet();
             m.headSet(new Object());
             throw new Exception("headSet, natural ordering");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet();
             m.tailSet(new Object());
             throw new Exception("tailSet, natural ordering");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
             m.headSet(new Integer(0));
             throw new Exception("headSet, explicit comparator");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
             m.tailSet(new Integer(0));
             throw new Exception("tailSet, explicit comparator");
         } catch (ClassCastException e) {
         }
 
-        try{
+        try {
             SortedMap m = new TreeMap();
             m.headMap(null);
             throw new Exception("(null endpoint)headMap, natural ordering");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedMap m = new TreeMap();
             m.tailMap(null);
             throw new Exception("(null endpoint)tailMap, natural ordering");
@@ -104,42 +103,42 @@
         }
 
 
-        try{
+        try {
             SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
             m.headMap(null);
             throw new Exception("(null endpoint)headMap, explicit comparator");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
             m.tailMap(null);
             throw new Exception("(null endpoint)tailMap, explicit comparator");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet();
             m.headSet(null);
             throw new Exception("(null endpoint)headSet, natural ordering");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet();
             m.tailSet(null);
             throw new Exception("(null endpoint)tailSet, natural ordering");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
             m.headSet(null);
             throw new Exception("(null endpoint)headSet, explicit comparator");
         } catch (NullPointerException e) {
         }
 
-        try{
+        try {
             SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
             m.tailSet(null);
             throw new Exception("(null endpoint)tailSet, explicit comparator");
--- a/jdk/test/java/util/TreeMap/SubMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/TreeMap/SubMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -40,7 +40,7 @@
         boolean exc = false;
         try {
             m2.firstKey();
-        } catch(NoSuchElementException e) {
+        } catch (NoSuchElementException e) {
             exc = true;
         }
         if (!exc)
@@ -49,7 +49,7 @@
         exc = false;
         try {
             m2.lastKey();
-        } catch(NoSuchElementException e) {
+        } catch (NoSuchElementException e) {
             exc = true;
         }
         if (!exc)
@@ -70,7 +70,7 @@
         exc = false;
         try {
             s2.first();
-        } catch(NoSuchElementException e) {
+        } catch (NoSuchElementException e) {
             exc = true;
         }
         if (!exc)
@@ -79,7 +79,7 @@
         exc = false;
         try {
             s2.last();
-        } catch(NoSuchElementException e) {
+        } catch (NoSuchElementException e) {
             exc = true;
         }
         if (!exc)
--- a/jdk/test/java/util/Vector/ComodifiedRemoveAllElements.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Vector/ComodifiedRemoveAllElements.java	Wed Jul 05 20:54:58 2017 +0200
@@ -25,7 +25,7 @@
  * @test
  * @bug 4298133
  * @summary Due to a bug in Vector's removeAllElements(),
- *          the modification counter  would not get incremented.
+ *          the modification counter would not get incremented.
  * @author Konstantin Kladko
  */
 
@@ -37,7 +37,7 @@
         v.addElement(null);
         Iterator it = v.iterator();
         v.removeAllElements();
-        try{
+        try {
             it.next();
         } catch (ConcurrentModificationException cme) {
             return;
--- a/jdk/test/java/util/Vector/IllegalConstructorArgs.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Vector/IllegalConstructorArgs.java	Wed Jul 05 20:54:58 2017 +0200
@@ -39,7 +39,7 @@
       public static void main(String argv[]) {
           int testSucceeded=0;
 
-        try{
+        try {
            // this should generate an IllegalArgumentException
            Vector bad1 = new Vector(-100, 10);
         }
@@ -50,8 +50,8 @@
             testSucceeded =0;
         }
 
-        if(testSucceeded == 0)
-             throw new RuntimeException("Wrong exception thrown.");
+        if (testSucceeded == 0)
+            throw new RuntimeException("Wrong exception thrown.");
 
      }
 
--- a/jdk/test/java/util/Vector/LastIndexOf.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Vector/LastIndexOf.java	Wed Jul 05 20:54:58 2017 +0200
@@ -34,7 +34,7 @@
     public static void main(String argv[]) throws Exception {
         Vector v = new Vector(10);
 
-        try{
+        try {
             int i = v.lastIndexOf(null, 5);
             throw new Exception("lastIndexOf(5/10) " + i);
         } catch (IndexOutOfBoundsException e) {
--- a/jdk/test/java/util/Vector/SyncLastIndexOf.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/Vector/SyncLastIndexOf.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,7 +36,7 @@
     static class RemovingThread extends Thread {
 
         public void run() {
-           synchronized(v) {
+           synchronized (v) {
                 try {
                 sleep(200);
                 } catch (InterruptedException e) {
--- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 6499848
- * @ignore until 6842353 is resolved
  * @summary Check that iterators work properly in the presence of
  *          concurrent finalization and removal of elements.
  * @key randomness
@@ -116,7 +115,7 @@
             it.next();          // protects first entry
             System.out.println(map.values());
             foos[first] = null;
-            tryWaitForFinalizersToRun()
+            tryWaitForFinalizersToRun();
             equal(map.size(), first+1);
             System.out.println(map.values());
             checkIterator(it, first-1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,755 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Random;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+
+/*
+ * @test
+ * @bug 7014263
+ * @summary White box testing of ArrayBlockingQueue iterators.
+ */
+
+/**
+ * Highly coupled to the implementation of ArrayBlockingQueue.
+ * Uses reflection to inspect queue and iterator state.
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class IteratorConsistency {
+    final Random rnd = new Random();
+    final int CAPACITY = 20;
+    Field itrsField;
+    Field itemsField;
+    Field takeIndexField;
+    Field headField;
+    Field nextField;
+    Field prevTakeIndexField;
+
+    void test(String[] args) throws Throwable {
+        itrsField = ArrayBlockingQueue.class.getDeclaredField("itrs");
+        itemsField = ArrayBlockingQueue.class.getDeclaredField("items");
+        takeIndexField = ArrayBlockingQueue.class.getDeclaredField("takeIndex");
+        headField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itrs").getDeclaredField("head");
+        nextField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itrs$Node").getDeclaredField("next");
+        prevTakeIndexField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itr").getDeclaredField("prevTakeIndex");
+        itrsField.setAccessible(true);
+        itemsField.setAccessible(true);
+        takeIndexField.setAccessible(true);
+        headField.setAccessible(true);
+        nextField.setAccessible(true);
+        prevTakeIndexField.setAccessible(true);
+        test(CAPACITY, true);
+        test(CAPACITY, false);
+    }
+
+    Object itrs(ArrayBlockingQueue q) {
+        try {
+            return itrsField.get(q);
+        } catch (Throwable t) { throw new Error(); }
+    }
+
+    int takeIndex(ArrayBlockingQueue q) {
+        try {
+            return takeIndexField.getInt(q);
+        } catch (Throwable t) { throw new Error(); }
+    }
+
+    List<Iterator> trackedIterators(Object itrs) {
+        try {
+            List<Iterator> its = new ArrayList<Iterator>();
+            if (itrs != null)
+                for (Object p = headField.get(itrs); p != null; p = nextField.get(p))
+                    its.add(((WeakReference<Iterator>)(p)).get());
+            Collections.reverse(its);
+            return its;
+        } catch (Throwable t) { throw new Error(); }
+    }
+
+    List<Iterator> trackedIterators(ArrayBlockingQueue q) {
+        return trackedIterators(itrs(q));
+    }
+
+    List<Iterator> attachedIterators(Object itrs) {
+        try {
+            List<Iterator> its = new ArrayList<Iterator>();
+            if (itrs != null)
+                for (Object p = headField.get(itrs); p != null; p = nextField.get(p)) {
+                    Iterator it = ((WeakReference<Iterator>)(p)).get();
+                    if (it != null && !isDetached(it))
+                        its.add(it);
+                }
+            Collections.reverse(its);
+            return its;
+        } catch (Throwable t) { unexpected(t); return null; }
+    }
+
+    List<Iterator> attachedIterators(ArrayBlockingQueue q) {
+        return attachedIterators(itrs(q));
+    }
+
+    Object[] internalArray(ArrayBlockingQueue q) {
+        try {
+            return (Object[]) itemsField.get(q);
+        } catch (Throwable t) { throw new Error(t); }
+    }
+
+    void printInternalArray(ArrayBlockingQueue q) {
+        System.err.println(Arrays.toString(internalArray(q)));
+    }
+
+    void checkExhausted(Iterator it) {
+        if (rnd.nextBoolean()) {
+            check(!it.hasNext());
+            check(isDetached(it));
+        }
+        if (rnd.nextBoolean())
+            try { it.next(); fail("should throw"); }
+            catch (NoSuchElementException success) {}
+    }
+
+    boolean isDetached(Iterator it) {
+        try {
+            return prevTakeIndexField.getInt(it) < 0;
+        } catch (IllegalAccessException t) { unexpected(t); return false; }
+    }
+
+    void checkDetached(Iterator it) {
+        check(isDetached(it));
+    }
+
+    void removeUsingIterator(ArrayBlockingQueue q, Object element) {
+        Iterator it = q.iterator();
+        while (it.hasNext()) {
+            Object x = it.next();
+            if (element.equals(x))
+                it.remove();
+            checkRemoveThrowsISE(it);
+        }
+    }
+
+    void checkRemoveThrowsISE(Iterator it) {
+        if (rnd.nextBoolean())
+            return;
+        try { it.remove(); fail("should throw"); }
+        catch (IllegalStateException success) {}
+    }
+
+    void checkRemoveHasNoEffect(Iterator it, Collection c) {
+        if (rnd.nextBoolean())
+            return;
+        int size = c.size();
+        it.remove(); // no effect
+        equal(c.size(), size);
+        checkRemoveThrowsISE(it);
+    }
+
+    void checkIterationSanity(Queue q) {
+        if (rnd.nextBoolean())
+            return;
+        int size = q.size();
+        Object[] a = q.toArray();
+        Object[] b = new Object[size+2];
+        Arrays.fill(b, Boolean.TRUE);
+        Object[] c = q.toArray(b);
+        equal(a.length, size);
+        check(b == c);
+        check(b[size] == null);
+        check(b[size+1] == Boolean.TRUE);
+        equal(q.toString(), Arrays.toString(a));
+        Integer[] xx = null, yy = null;
+        if (size > 0) {
+            xx = new Integer[size - 1];
+            Arrays.fill(xx, 42);
+            yy = ((Queue<Integer>)q).toArray(xx);
+            for (Integer zz : xx)
+                equal(42, zz);
+        }
+        Iterator it = q.iterator();
+        for (int i = 0; i < size; i++) {
+            check(it.hasNext());
+            Object x = it.next();
+            check(x == a[i]);
+            check(x == b[i]);
+            if (xx != null) check(x == yy[i]);
+        }
+        check(!it.hasNext());
+    }
+
+    private static void waitForFinalizersToRun() {
+        for (int i = 0; i < 2; i++)
+            tryWaitForFinalizersToRun();
+    }
+
+    private static void tryWaitForFinalizersToRun() {
+        System.gc();
+        final CountDownLatch fin = new CountDownLatch(1);
+        new Object() { protected void finalize() { fin.countDown(); }};
+        System.gc();
+        try { fin.await(); }
+        catch (InterruptedException ie) { throw new Error(ie); }
+    }
+
+    void test(int capacity, boolean fair) {
+        //----------------------------------------------------------------
+        // q.clear will clear out itrs.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                check(q.add(i));
+            check(itrs(q) == null);
+            for (int i = 0; i < capacity; i++) {
+                its.add(q.iterator());
+                equal(trackedIterators(q), its);
+                q.poll();
+                q.add(capacity+i);
+            }
+            q.clear();
+            check(itrs(q) == null);
+            int j = 0;
+            for (Iterator it : its) {
+                if (rnd.nextBoolean())
+                    check(it.hasNext());
+                equal(it.next(), j++);
+                checkExhausted(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // q emptying will clear out itrs.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            check(itrs(q) == null);
+            for (int i = 0; i < capacity; i++) {
+                its.add(q.iterator());
+                equal(trackedIterators(q), its);
+                q.poll();
+                q.add(capacity+i);
+            }
+            for (int i = 0; i < capacity; i++)
+                q.poll();
+            check(itrs(q) == null);
+            int j = 0;
+            for (Iterator it : its) {
+                if (rnd.nextBoolean())
+                    check(it.hasNext());
+                equal(it.next(), j++);
+                checkExhausted(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Advancing 2 cycles will remove iterators.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            check(itrs(q) == null);
+            for (int i = capacity; i < 3 * capacity; i++) {
+                its.add(q.iterator());
+                equal(trackedIterators(q), its);
+                q.poll();
+                q.add(i);
+            }
+            for (int i = 3 * capacity; i < 4 * capacity; i++) {
+                equal(trackedIterators(q), its.subList(capacity,2*capacity));
+                q.poll();
+                q.add(i);
+            }
+            check(itrs(q) == null);
+            int j = 0;
+            for (Iterator it : its) {
+                if (rnd.nextBoolean())
+                    check(it.hasNext());
+                equal(it.next(), j++);
+                checkExhausted(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Interior removal of elements used by an iterator will cause
+        // it to be untracked.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            q.add(0);
+            for (int i = 1; i < 2 * capacity; i++) {
+                q.add(i);
+                Integer[] elts = { -1, -2, -3 };
+                for (Integer elt : elts) q.add(elt);
+                equal(q.remove(), i - 1);
+                Iterator it = q.iterator();
+                equal(it.next(), i);
+                equal(it.next(), elts[0]);
+                Collections.shuffle(Arrays.asList(elts));
+                check(q.remove(elts[0]));
+                check(q.remove(elts[1]));
+                equal(trackedIterators(q), Collections.singletonList(it));
+                check(q.remove(elts[2]));
+                check(itrs(q) == null);
+                equal(it.next(), -2);
+                if (rnd.nextBoolean()) checkExhausted(it);
+                if (rnd.nextBoolean()) checkDetached(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check iterators on an empty q
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            for (int i = 0; i < 4; i++) {
+                Iterator it = q.iterator();
+                check(itrs(q) == null);
+                if (rnd.nextBoolean()) checkExhausted(it);
+                if (rnd.nextBoolean()) checkDetached(it);
+                checkRemoveThrowsISE(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check "interior" removal of iterator's last element
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                for (int j = 0; j < i; j++)
+                    equal(j, it.next());
+                equal(attachedIterators(q), its);
+            }
+            q.remove(capacity - 1);
+            equal(attachedIterators(q), its);
+            for (int i = 1; i < capacity - 1; i++) {
+                q.remove(capacity - i - 1);
+                Iterator it = its.get(capacity - i);
+                checkDetached(it);
+                equal(attachedIterators(q), its.subList(0, capacity - i));
+                if (rnd.nextBoolean()) check(it.hasNext());
+                equal(it.next(), capacity - i);
+                checkExhausted(it);
+            }
+            equal(attachedIterators(q), its.subList(0, 2));
+            q.remove(0);
+            check(q.isEmpty());
+            check(itrs(q) == null);
+            Iterator it = its.get(0);
+            equal(it.next(), 0);
+            checkRemoveHasNoEffect(it, q);
+            checkExhausted(it);
+            checkDetached(it);
+            checkRemoveHasNoEffect(its.get(1), q);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check "interior" removal of alternating elements, straddling 2 cycles
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            // Move takeIndex to middle
+            for (int i = 0; i < capacity/2; i++) {
+                check(q.add(i));
+                equal(q.poll(), i);
+            }
+            check(takeIndex(q) == capacity/2);
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                for (int j = 0; j < i; j++)
+                    equal(j, it.next());
+                equal(attachedIterators(q), its);
+            }
+            // Remove all even elements, in either direction using
+            // q.remove(), or iterator.remove()
+            switch (rnd.nextInt(3)) {
+            case 0:
+                for (int i = 0; i < capacity; i+=2) {
+                    check(q.remove(i));
+                    equal(attachedIterators(q), its);
+                }
+                break;
+            case 1:
+                for (int i = capacity - 2; i >= 0; i-=2) {
+                    check(q.remove(i));
+                    equal(attachedIterators(q), its);
+                }
+                break;
+            case 2:
+                Iterator it = q.iterator();
+                while (it.hasNext()) {
+                    int i = (Integer) it.next();
+                    if ((i & 1) == 0)
+                        it.remove();
+                }
+                equal(attachedIterators(q), its);
+                break;
+            default: throw new Error();
+            }
+
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = its.get(i);
+                boolean even = ((i & 1) == 0);
+                if (even) {
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    equal(i, it.next());
+                    for (int j = i+1; j < capacity; j += 2)
+                        equal(j, it.next());
+                    check(!isDetached(it));
+                    check(!it.hasNext());
+                    check(isDetached(it));
+                } else { /* odd */
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    checkRemoveHasNoEffect(it, q);
+                    equal(i, it.next());
+                    for (int j = i+2; j < capacity; j += 2)
+                        equal(j, it.next());
+                    check(!isDetached(it));
+                    check(!it.hasNext());
+                    check(isDetached(it));
+                }
+            }
+            equal(trackedIterators(q), Collections.emptyList());
+            check(itrs(q) == null);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check garbage collection of discarded iterators
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < capacity; i++) {
+                its.add(q.iterator());
+                equal(attachedIterators(q), its);
+            }
+            its = null;
+            waitForFinalizersToRun();
+            List<Iterator> trackedIterators = trackedIterators(q);
+            equal(trackedIterators.size(), capacity);
+            for (Iterator x : trackedIterators)
+                check(x == null);
+            Iterator it = q.iterator();
+            equal(trackedIterators(q), Collections.singletonList(it));
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check garbage collection of discarded iterators,
+        // with a randomly retained subset.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            List<Iterator> retained = new ArrayList<Iterator>();
+            final int size = 1 + rnd.nextInt(capacity);
+            for (int i = 0; i < size; i++)
+                q.add(i);
+            for (int i = 0; i < size; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                equal(attachedIterators(q), its);
+            }
+            // Leave sufficient gaps in retained
+            for (int i = 0; i < size; i+= 2+rnd.nextInt(3))
+                retained.add(its.get(i));
+            its = null;
+            waitForFinalizersToRun();
+            List<Iterator> trackedIterators = trackedIterators(q);
+            equal(trackedIterators.size(), size);
+            for (Iterator it : trackedIterators)
+                check((it == null) ^ retained.contains(it));
+            Iterator it = q.iterator(); // trigger another sweep
+            retained.add(it);
+            equal(trackedIterators(q), retained);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check incremental sweeping of discarded iterators.
+        // Excessively white box?!
+        //----------------------------------------------------------------
+        try {
+            final int SHORT_SWEEP_PROBES = 4;
+            final int LONG_SWEEP_PROBES = 16;
+            final int PROBE_HOP = LONG_SWEEP_PROBES + 6 * SHORT_SWEEP_PROBES;
+            final int PROBE_HOP_COUNT = 10;
+            // Expect around 8 sweeps per PROBE_HOP
+            final int SWEEPS_PER_PROBE_HOP = 8;
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < PROBE_HOP_COUNT * PROBE_HOP; i++) {
+                its.add(q.iterator());
+                equal(attachedIterators(q), its);
+            }
+            // make some garbage, separated by PROBE_HOP
+            for (int i = 0; i < its.size(); i += PROBE_HOP)
+                its.set(i, null);
+            waitForFinalizersToRun();
+            int retries;
+            for (retries = 0;
+                 trackedIterators(q).contains(null) && retries < 1000;
+                 retries++)
+                // one round of sweeping
+                its.add(q.iterator());
+            check(retries >= PROBE_HOP_COUNT * (SWEEPS_PER_PROBE_HOP - 2));
+            check(retries <= PROBE_HOP_COUNT * (SWEEPS_PER_PROBE_HOP + 2));
+            Iterator itsit = its.iterator();
+            while (itsit.hasNext())
+                if (itsit.next() == null)
+                    itsit.remove();
+            equal(trackedIterators(q), its);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check safety of iterator.remove while in detached mode.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity/2; i++) {
+                q.add(i);
+                q.remove();
+            }
+            check(takeIndex(q) == capacity/2);
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                for (int j = 0; j < i; j++)
+                    equal(j, it.next());
+                equal(attachedIterators(q), its);
+            }
+            for (int i = capacity - 1; i >= 0; i--) {
+                Iterator it = its.get(i);
+                equal(i, it.next()); // last element
+                check(!isDetached(it));
+                check(!it.hasNext()); // first hasNext failure
+                check(isDetached(it));
+                int size = q.size();
+                check(q.contains(i));
+                switch (rnd.nextInt(3)) {
+                case 0:
+                    it.remove();
+                    check(!q.contains(i));
+                    equal(q.size(), size - 1);
+                    break;
+                case 1:
+                    // replace i with impostor
+                    if (q.remainingCapacity() == 0) {
+                        check(q.remove(i));
+                        check(q.add(-1));
+                    } else {
+                        check(q.add(-1));
+                        check(q.remove(i));
+                    }
+                    it.remove(); // should have no effect
+                    equal(size, q.size());
+                    check(q.contains(-1));
+                    check(q.remove(-1));
+                    break;
+                case 2:
+                    // replace i with true impostor
+                    if (i != 0) {
+                        check(q.remove(i));
+                        check(q.add(i));
+                    }
+                    it.remove();
+                    check(!q.contains(i));
+                    equal(q.size(), size - 1);
+                    break;
+                default: throw new Error();
+                }
+                checkRemoveThrowsISE(it);
+                check(isDetached(it));
+                check(!trackedIterators(q).contains(it));
+            }
+            check(q.isEmpty());
+            check(itrs(q) == null);
+            for (Iterator it : its)
+                checkExhausted(it);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check dequeues bypassing iterators' current positions.
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            Queue<Iterator> its0
+                = new ArrayDeque<Iterator>();
+            Queue<Iterator> itsMid
+                = new ArrayDeque<Iterator>();
+            List<Iterator> its = new ArrayList<Iterator>();
+            for (int i = 0; i < capacity; i++)
+                q.add(i);
+            for (int i = 0; i < 2 * capacity + 1; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                its0.add(it);
+            }
+            for (int i = 0; i < 2 * capacity + 1; i++) {
+                Iterator it = q.iterator();
+                for (int j = 0; j < capacity/2; j++)
+                    equal(j, it.next());
+                its.add(it);
+                itsMid.add(it);
+            }
+            for (int i = capacity; i < 3 * capacity; i++) {
+                Iterator it;
+
+                it = its0.remove();
+                checkRemoveThrowsISE(it);
+                if (rnd.nextBoolean()) check(it.hasNext());
+                equal(0, it.next());
+                int victim = i - capacity;
+                for (int j = victim + (victim == 0 ? 1 : 0); j < i; j++) {
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    equal(j, it.next());
+                }
+                checkExhausted(it);
+
+                it = itsMid.remove();
+                if (victim >= capacity/2)
+                    checkRemoveHasNoEffect(it, q);
+                equal(capacity/2, it.next());
+                if (victim > capacity/2)
+                    checkRemoveHasNoEffect(it, q);
+                for (int j = Math.max(victim, capacity/2 + 1); j < i; j++) {
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    equal(j, it.next());
+                }
+                checkExhausted(it);
+
+                if (rnd.nextBoolean()) {
+                    equal(victim, q.remove());
+                } else {
+                    ArrayList list = new ArrayList(1);
+                    q.drainTo(list, 1);
+                    equal(list.size(), 1);
+                    equal(victim, list.get(0));
+                }
+                check(q.add(i));
+            }
+            // takeIndex has wrapped twice.
+            Iterator it0 = its0.remove();
+            Iterator itMid = itsMid.remove();
+            check(isDetached(it0));
+            check(isDetached(itMid));
+            if (rnd.nextBoolean()) check(it0.hasNext());
+            if (rnd.nextBoolean()) check(itMid.hasNext());
+            checkRemoveThrowsISE(it0);
+            checkRemoveHasNoEffect(itMid, q);
+            if (rnd.nextBoolean()) equal(0, it0.next());
+            if (rnd.nextBoolean()) equal(capacity/2, itMid.next());
+            check(isDetached(it0));
+            check(isDetached(itMid));
+            equal(capacity, q.size());
+            equal(0, q.remainingCapacity());
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check collective sanity of iteration, toArray() and toString()
+        //----------------------------------------------------------------
+        try {
+            ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+            for (int i = 0; i < capacity; i++) {
+                checkIterationSanity(q);
+                equal(capacity, q.size() + q.remainingCapacity());
+                q.add(i);
+            }
+            for (int i = 0; i < (capacity + (capacity >> 1)); i++) {
+                checkIterationSanity(q);
+                equal(capacity, q.size() + q.remainingCapacity());
+                equal(i, q.peek());
+                equal(i, q.poll());
+                checkIterationSanity(q);
+                equal(capacity, q.size() + q.remainingCapacity());
+                q.add(capacity + i);
+            }
+            for (int i = 0; i < capacity; i++) {
+                checkIterationSanity(q);
+                equal(capacity, q.size() + q.remainingCapacity());
+                int expected = i + capacity + (capacity >> 1);
+                equal(expected, q.peek());
+                equal(expected, q.poll());
+            }
+            checkIterationSanity(q);
+        } catch (Throwable t) { unexpected(t); }
+
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new IteratorConsistency().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.err.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/BlockingQueue/DrainToFails.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Test drainTo failing due to c.add throwing
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class DrainToFails {
+    final int CAPACITY = 10;
+    final int SMALL = 2;
+
+    void test(String[] args) throws Throwable {
+        testDelayQueue(new DelayQueue());
+        testDelayQueue(new ScheduledThreadPoolExecutor(1).getQueue());
+
+        testUnbounded(new LinkedBlockingQueue());
+        testUnbounded(new LinkedBlockingDeque());
+        testUnbounded(new PriorityBlockingQueue());
+
+        testBounded(new LinkedBlockingQueue(CAPACITY));
+        testBounded(new LinkedBlockingDeque(CAPACITY));
+        testBounded(new ArrayBlockingQueue(CAPACITY));
+    }
+
+    static class PDelay
+        extends FutureTask<Void>
+        implements Delayed, RunnableScheduledFuture<Void> {
+        int pseudodelay;
+        PDelay(int i) {
+            super(new Runnable() { public void run() {}}, null);
+            pseudodelay = i;
+        }
+        public int compareTo(PDelay other) {
+            int a = this.pseudodelay;
+            int b = other.pseudodelay;
+            return (a < b) ? -1 : (a > b) ? 1 : 0;
+        }
+        public int compareTo(Delayed y) {
+            return compareTo((PDelay)y);
+        }
+        public boolean equals(Object other) {
+            return (other instanceof PDelay) &&
+                this.pseudodelay == ((PDelay)other).pseudodelay;
+        }
+        public long getDelay(TimeUnit ignore) {
+            return Integer.MIN_VALUE + pseudodelay;
+        }
+        public String toString() {
+            return String.valueOf(pseudodelay);
+        }
+        public boolean isPeriodic() { return false; }
+    }
+
+    void testDelayQueue(final BlockingQueue q) throws Throwable {
+        System.err.println(q.getClass().getSimpleName());
+        for (int i = 0; i < CAPACITY; i++)
+            q.add(new PDelay(i));
+        ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+        try {
+            q.drainTo(q2, SMALL + 3);
+            fail("should throw");
+        } catch (IllegalStateException success) {
+            equal(SMALL, q2.size());
+            equal(new PDelay(0), q2.poll());
+            equal(new PDelay(1), q2.poll());
+            check(q2.isEmpty());
+            for (int i = SMALL; i < CAPACITY; i++)
+                equal(new PDelay(i), q.poll());
+            equal(0, q.size());
+        }
+    }
+
+    void testUnbounded(final BlockingQueue q) throws Throwable {
+        System.err.println(q.getClass().getSimpleName());
+        for (int i = 0; i < CAPACITY; i++)
+            q.add(i);
+        ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+        try {
+            q.drainTo(q2, 7);
+            fail("should throw");
+        } catch (IllegalStateException success) {
+            assertContentsInOrder(q2, 0, 1);
+            q2.clear();
+            equal(q.size(), CAPACITY - SMALL);
+            equal(SMALL, q.peek());
+        }
+
+        try {
+            q.drainTo(q2);
+            fail("should throw");
+        } catch (IllegalStateException success) {
+            assertContentsInOrder(q2, 2, 3);
+            equal(q.size(), CAPACITY - 2 * SMALL);
+            for (int i = 2 * SMALL; i < CAPACITY; i++)
+                equal(i, q.poll());
+            equal(0, q.size());
+        }
+    }
+
+    void testBounded(final BlockingQueue q) throws Throwable {
+        System.err.println(q.getClass().getSimpleName());
+        for (int i = 0; i < CAPACITY; i++)
+            q.add(i);
+        List<Thread> putters = new ArrayList<Thread>();
+        for (int i = 0; i < 4; i++) {
+            Thread putter = new Thread(putter(q, 42 + i));
+            putters.add(putter);
+            putter.setDaemon(true);
+            putter.start();
+        }
+        ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+        try {
+            q.drainTo(q2, 7);
+            fail("should throw");
+        } catch (IllegalStateException success) {
+            while (q.size() < CAPACITY)
+                Thread.yield();
+            assertContentsInOrder(q2, 0, 1);
+            q2.clear();
+        }
+
+        try {
+            q.drainTo(q2);
+            fail("should throw");
+        } catch (IllegalStateException success) {
+            for (Thread putter : putters) {
+                putter.join(2000L);
+                check(! putter.isAlive());
+            }
+            assertContentsInOrder(q2, 2, 3);
+            for (int i = 2 * SMALL; i < CAPACITY; i++)
+                equal(i, q.poll());
+            equal(4, q.size());
+            check(q.contains(42));
+            check(q.contains(43));
+            check(q.contains(44));
+            check(q.contains(45));
+        }
+    }
+
+    Runnable putter(final BlockingQueue q, final int elt) {
+        return new Runnable() {
+            public void run() {
+                try { q.put(elt); }
+                catch (Throwable t) { unexpected(t); }}};
+    }
+
+    void assertContentsInOrder(Iterable it, Object... contents) {
+        int i = 0;
+        for (Object e : it)
+            equal(contents[i++], e);
+        equal(contents.length, i);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new DrainToFails().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java	Wed Jul 05 20:54:58 2017 +0200
@@ -48,7 +48,8 @@
         }
     }
 
-    static void checkInterrupted(Iterable<Fun> fs) {
+    static void checkInterrupted(Iterable<Fun> fs)
+            throws InterruptedException {
         final Executor immediateExecutor = new Executor() {
                 public void execute(Runnable r) {
                     r.run(); }};
@@ -60,6 +61,7 @@
         checkInterrupted0(fs, immediateExecutor);
         checkInterrupted0(fs, delayedExecutor);
         stpe.shutdown();
+        check(stpe.awaitTermination(10, SECONDS));
     }
 
     static void testQueue(final BlockingQueue<Object> q) {
@@ -96,8 +98,10 @@
             }
             checkInterrupted(fs);
         } catch (Throwable t) {
-          System.out.printf("Failed: %s%n", q.getClass().getSimpleName());
-          unexpected(t);
+            System.out.printf("Failed: %s%n", q.getClass().getSimpleName());
+            unexpected(t);
+        } finally {
+            Thread.interrupted();       // clear interrupts, just in case
         }
     }
 
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -53,7 +53,6 @@
 import static java.util.concurrent.ForkJoinPool.*;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
 public class Basic {
 
     static void checkCompletedNormally(CompletableFuture<?> cf, Object value) {
@@ -66,6 +65,7 @@
         try { equalAnyOf(cf.get(), values); } catch (Throwable x) { unexpected(x); }
         try { equalAnyOf(cf.get(0L, SECONDS), values); } catch (Throwable x) { unexpected(x); }
         check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+        check(!cf.isCompletedExceptionally(), "Expected isCompletedExceptionally to return false");
         check(!cf.isCancelled(), "Expected isCancelled to be false");
         check(!cf.cancel(true), "Expected cancel to return false");
         check(cf.toString().contains("[Completed normally]"));
@@ -97,6 +97,7 @@
         catch (CancellationException x) { if (cancelled) pass(); else fail(); }
         catch (ExecutionException x) { if (cancelled) check(x.getCause() instanceof CancellationException); else pass(); }
         check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+        check(cf.isCompletedExceptionally(), "Expected isCompletedExceptionally");
         check(cf.isCancelled() == cancelled, "Expected isCancelled: " + cancelled + ", got:"  + cf.isCancelled());
         check(cf.cancel(true) == cancelled, "Expected cancel: " + cancelled + ", got:"  + cf.cancel(true));
         check(cf.toString().contains("[Completed exceptionally]"));  // ## TODO: 'E'xceptionally
@@ -805,6 +806,49 @@
             cf2 = cf1.handle((x,t) -> { check(t.getCause() == ex); return 2;});
             checkCompletedExceptionally(cf1);
             checkCompletedNormally(cf2, 2);
+
+            cf1 = supplyAsync(() -> 1);
+            cf2 = cf1.handleAsync((x,t) -> x+1);
+            checkCompletedNormally(cf1, 1);
+            checkCompletedNormally(cf2, 2);
+
+            cf1 = supplyAsync(() -> { throw ex; });
+            cf2 = cf1.handleAsync((x,t) -> { check(t.getCause() == ex); return 2;});
+            checkCompletedExceptionally(cf1);
+            checkCompletedNormally(cf2, 2);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // whenComplete tests
+        //----------------------------------------------------------------
+        try {
+            AtomicInteger count = new AtomicInteger();
+            CompletableFuture<Integer> cf2;
+            CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
+            cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+            checkCompletedNormally(cf1, 1);
+            checkCompletedNormally(cf2, 1);
+            check(count.get() == 1, "action count should be incremented");
+
+            final RuntimeException ex = new RuntimeException();
+            cf1 = supplyAsync(() -> { throw ex; });
+            cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+            checkCompletedExceptionally(cf1);
+            checkCompletedExceptionally(cf2);
+            check(count.get() == 2, "action count should be incremented");
+
+            cf1 = supplyAsync(() -> 1);
+            cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+            checkCompletedNormally(cf1, 1);
+            checkCompletedNormally(cf2, 1);
+            check(count.get() == 3, "action count should be incremented");
+
+            cf1 = supplyAsync(() -> { throw ex; });
+            cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+            checkCompletedExceptionally(cf1);
+            checkCompletedExceptionally(cf2);
+            check(count.get() == 4, "action count should be incremented");
+
         } catch (Throwable t) { unexpected(t); }
 
     }
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -27,7 +27,6 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 
-
 /**
  * @test
  * @bug 8029164
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -33,7 +33,6 @@
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
-
 /**
  * @test
  * @bug 8068432 8072030
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -23,14 +23,18 @@
 
 import org.testng.annotations.Test;
 
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
@@ -39,48 +43,52 @@
 /**
  * @test
  * @bug 8028564
- * @run testng ConcurrentAssociateTest
+ * @run testng/timeout=1200 ConcurrentAssociateTest
  * @summary Test that association operations, such as put and compute,
  * place entries in the map
  */
 @Test
 public class ConcurrentAssociateTest {
 
-    // The number of entries for each thread to place in a map
+    /** Maximum time (in seconds) to wait for a test method to complete. */
+    private static final int TIMEOUT = Integer.getInteger("timeout", 200);
+
+    /** The number of entries for each thread to place in a map. */
     private static final int N = Integer.getInteger("n", 128);
-    // The number of iterations of the test
-    private static final int I = Integer.getInteger("i", 256);
 
-    // Object to be placed in the concurrent map
+    /** The number of iterations of the test. */
+    private static final int I = Integer.getInteger("i", 64);
+
+    /** Objects to be placed in the concurrent map. */
     static class X {
         // Limit the hash code to trigger collisions
-        int hc = ThreadLocalRandom.current().nextInt(1, 9);
+        final int hc = ThreadLocalRandom.current().nextInt(1, 9);
 
         public int hashCode() { return hc; }
     }
 
     @Test
-    public void testPut() {
+    public void testPut() throws Throwable {
         test("CHM.put", (m, o) -> m.put(o, o));
     }
 
     @Test
-    public void testCompute() {
+    public void testCompute() throws Throwable {
         test("CHM.compute", (m, o) -> m.compute(o, (k, v) -> o));
     }
 
     @Test
-    public void testComputeIfAbsent() {
+    public void testComputeIfAbsent() throws Throwable {
         test("CHM.computeIfAbsent", (m, o) -> m.computeIfAbsent(o, (k) -> o));
     }
 
     @Test
-    public void testMerge() {
+    public void testMerge() throws Throwable {
         test("CHM.merge", (m, o) -> m.merge(o, o, (v1, v2) -> v1));
     }
 
     @Test
-    public void testPutAll() {
+    public void testPutAll() throws Throwable {
         test("CHM.putAll", (m, o) -> {
             Map<Object, Object> hm = new HashMap<>();
             hm.put(o, o);
@@ -88,7 +96,7 @@
         });
     }
 
-    private static void test(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) {
+    private static void test(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) throws Throwable {
         for (int i = 0; i < I; i++) {
             testOnce(desc, associator);
         }
@@ -100,13 +108,16 @@
         }
     }
 
-    private static void testOnce(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) {
+    private static void testOnce(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) throws Throwable {
         ConcurrentHashMap<Object, Object> m = new ConcurrentHashMap<>();
         CountDownLatch s = new CountDownLatch(1);
 
         Supplier<Runnable> sr = () -> () -> {
             try {
-                s.await();
+                if (!s.await(TIMEOUT, TimeUnit.SECONDS)) {
+                    dumpTestThreads();
+                    throw new AssertionError("timed out");
+                }
             }
             catch (InterruptedException e) {
             }
@@ -121,7 +132,7 @@
         };
 
         // Bound concurrency to avoid degenerate performance
-        int ps = Math.min(Runtime.getRuntime().availableProcessors(), 32);
+        int ps = Math.min(Runtime.getRuntime().availableProcessors(), 8);
         Stream<CompletableFuture> runners = IntStream.range(0, ps)
                 .mapToObj(i -> sr.get())
                 .map(CompletableFuture::runAsync);
@@ -131,16 +142,41 @@
 
         // Trigger the runners to start associating
         s.countDown();
+
         try {
-            all.join();
-        } catch (CompletionException e) {
-            Throwable t = e.getCause();
-            if (t instanceof AssociationFailure) {
-                throw (AssociationFailure) t;
+            all.get(TIMEOUT, TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            dumpTestThreads();
+            throw e;
+        } catch (Throwable e) {
+            dumpTestThreads();
+            Throwable cause = e.getCause();
+            if (cause instanceof AssociationFailure) {
+                throw cause;
             }
-            else {
-                throw e;
-            }
+            throw e;
         }
     }
+
+    /**
+     * A debugging tool to print stack traces of most threads, as jstack does.
+     * Uninteresting threads are filtered out.
+     */
+    static void dumpTestThreads() {
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+        System.err.println("------ stacktrace dump start ------");
+        for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
+            String name = info.getThreadName();
+            if ("Signal Dispatcher".equals(name))
+                continue;
+            if ("Reference Handler".equals(name)
+                && info.getLockName().startsWith("java.lang.ref.Reference$Lock"))
+                continue;
+            if ("Finalizer".equals(name)
+                && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock"))
+                continue;
+            System.err.print(info);
+        }
+        System.err.println("------ stacktrace dump end ------");
+    }
 }
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentContainsKeyTest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentContainsKeyTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -80,7 +80,6 @@
         test(content, m);
     }
 
-
     private static void test(X[] content, ConcurrentHashMap<Object, Object> m) {
         for (int i = 0; i < I; i++) {
             testOnce(content, m);
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java	Wed Jul 05 20:54:58 2017 +0200
@@ -68,7 +68,6 @@
             }
         }
 
-
         if (args.length > 1)
             numTests = Integer.parseInt(args[1]);
 
@@ -92,7 +91,6 @@
 
         TestTimer.printStats();
 
-
         if (doSerializeTest)
             stest(newMap(mapClass), size);
     }
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -175,7 +175,7 @@
         int position;
         int total;
 
-        Runner(Map<Integer,Integer> map, Integer[] key,  CyclicBarrier barrier) {
+        Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
             this.map = map;
             this.key = key;
             this.barrier = barrier;
@@ -183,7 +183,7 @@
         }
 
         int step() {
-            // random-walk around key positions,  bunching accesses
+            // random-walk around key positions, bunching accesses
             int r = rng.next();
             position += (r & 7) - 3;
             while (position >= key.length) position -= key.length;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8054446 8137184 8137185
+ * @summary Regression test for memory leak in remove(Object)
+ * @run main/othervm -Xmx2200k RemoveLeak
+ */
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class RemoveLeak {
+    public static void main(String[] args) {
+        int i = 0;
+        // Without bug fix, OutOfMemoryError was observed at iteration 65120
+        int iterations = 10 * 65120;
+        try {
+            ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<>();
+            queue.add(0L);
+            while (i++ < iterations) {
+                queue.add(1L);
+                queue.remove(1L);
+            }
+        } catch (Error t) {
+            System.err.printf("failed at iteration %d/%d%n", i, iterations);
+            throw t;
+        }
+    }
+}
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -47,10 +47,10 @@
     AtomicInteger totalItems;
     boolean print;
 
-    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    // Suitable for benchmarking.  Overridden by args[0] for testing.
     int maxStages = 20;
 
-    // Suitable for benchmarking.  Overriden by args[1] for testing.
+    // Suitable for benchmarking.  Overridden by args[1] for testing.
     int items = 1024 * 1024;
 
     Collection<Queue<Integer>> concurrentQueues() {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Wed Jul 05 20:54:58 2017 +0200
@@ -56,7 +56,7 @@
 import java.util.Map;
 
 public class GCRetention {
-    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    // Suitable for benchmarking.  Overridden by args[0] for testing.
     int count = 1024 * 1024;
 
     final Map<String,String> results = new ConcurrentHashMap<String,String>();
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Wed Jul 05 20:54:58 2017 +0200
@@ -42,6 +42,7 @@
 
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class IteratorWeakConsistency {
+    final Random rnd = new Random();
 
     void test(String[] args) throws Throwable {
         test(new LinkedBlockingQueue());
@@ -51,14 +52,46 @@
         test(new ConcurrentLinkedDeque());
         test(new ConcurrentLinkedQueue());
         test(new LinkedTransferQueue());
-        // Other concurrent queues (e.g. ArrayBlockingQueue) do not
-        // currently have weakly consistent iterators.
-        // As of 2010-09, ArrayBlockingQueue passes this test, but
-        // does not fully implement weak consistency.
         test(new ArrayBlockingQueue(20));
     }
 
+    void checkExhausted(Iterator it) {
+        if (rnd.nextBoolean()) {
+            check(!it.hasNext());
+        }
+        if (rnd.nextBoolean())
+            try { it.next(); fail("should throw"); }
+            catch (NoSuchElementException success) {}
+    }
+
+    void checkRemoveThrowsISE(Iterator it) {
+        if (rnd.nextBoolean()) {
+            try { it.remove(); fail("should throw"); }
+            catch (IllegalStateException success) {}
+        }
+    }
+
+    void checkRemoveHasNoEffect(Iterator it, Collection c) {
+        if (rnd.nextBoolean()) {
+            int size = c.size();
+            it.remove(); // no effect
+            equal(c.size(), size);
+            checkRemoveThrowsISE(it);
+        }
+    }
+
     void test(Queue q) {
+        //----------------------------------------------------------------
+        // Check iterators on an empty q
+        //----------------------------------------------------------------
+        try {
+            for (int i = 0; i < 4; i++) {
+                Iterator it = q.iterator();
+                if (rnd.nextBoolean()) checkExhausted(it);
+                checkRemoveThrowsISE(it);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
         // TODO: make this more general
         try {
             for (int i = 0; i < 10; i++)
@@ -73,7 +106,7 @@
                 list.add(it.next());
             equal(list, Arrays.asList(0, 3, 4, 5, 6, 8, 9));
             check(! list.contains(null));
-            System.out.printf("%s: %s%n",
+            System.err.printf("%s: %s%n",
                               q.getClass().getSimpleName(),
                               list);
         } catch (Throwable t) { unexpected(t); }
@@ -96,6 +129,118 @@
             check(found4);
         } catch (Throwable t) { unexpected(t); }
 
+        try {
+            q.clear();
+            Object x = new Object();
+            for (int i = 0; i < 20; i++)
+                q.add(x);
+            equal(20, q.size());
+            Iterator it1 = q.iterator();
+            Iterator it2 = q.iterator();
+            try { it1.remove(); fail(); }
+            catch (IllegalStateException success) {}
+            try { it2.remove(); fail(); }
+            catch (IllegalStateException success) {}
+
+            check(it1.next() == x);
+            check(it2.hasNext());
+            check(it2.next() == x);
+            it1.remove();
+            it2.remove();
+            equal(19, q.size());
+            try { it1.remove(); fail(); }
+            catch (IllegalStateException success) {}
+            try { it2.remove(); fail(); }
+            catch (IllegalStateException success) {}
+            equal(19, q.size());
+
+            it1.next();
+            check(it2.hasNext());
+            it2.next();
+            it2.remove();
+            it1.remove();
+            equal(18, q.size());
+
+            it1.next();
+            it2.next();
+            check(q.remove() == x);
+            equal(17, q.size());
+            it1.remove();
+            it2.remove();
+            equal(17, q.size());
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Check "interior" removal of alternating elements
+        //----------------------------------------------------------------
+        try {
+            q.clear();
+            final int remainingCapacity = (q instanceof BlockingQueue) ?
+                ((BlockingQueue)q).remainingCapacity() :
+                Integer.MAX_VALUE;
+            final int capacity = Math.min(20, remainingCapacity);
+            List<Iterator> its = new ArrayList<Iterator>();
+            // Move to "middle"
+            for (int i = 0; i < capacity/2; i++) {
+                check(q.add(i));
+                equal(q.poll(), i);
+            }
+            for (int i = 0; i < capacity; i++)
+                check(q.add(i));
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = q.iterator();
+                its.add(it);
+                for (int j = 0; j < i; j++)
+                    equal(j, it.next());
+            }
+
+            // Remove all even elements, in either direction using
+            // q.remove(), or iterator.remove()
+            switch (rnd.nextInt(3)) {
+            case 0:
+                for (int i = 0; i < capacity; i+=2)
+                    check(q.remove(i));
+                break;
+            case 1:
+                for (int i = capacity - 2; i >= 0; i-=2)
+                    check(q.remove(i));
+                break;
+            case 2:
+                Iterator it = q.iterator();
+                while (it.hasNext()) {
+                    int i = (Integer) it.next();
+                    if ((i & 1) == 0)
+                        it.remove();
+                }
+                break;
+            default: throw new Error();
+            }
+
+            for (int i = 0; i < capacity; i++) {
+                Iterator it = its.get(i);
+                boolean even = ((i & 1) == 0);
+                if (even) {
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    equal(i, it.next());
+                    for (int j = i+1; j < capacity; j += 2)
+                        equal(j, it.next());
+                    check(!it.hasNext());
+                } else { /* odd */
+                    if (rnd.nextBoolean()) check(it.hasNext());
+                    checkRemoveHasNoEffect(it, q);
+                    equal(i, it.next());
+                    for (int j = i+2; j < capacity; j += 2)
+                        equal(j, it.next());
+                    check(!it.hasNext());
+                }
+            }
+
+            // q only contains odd elements
+            for (int i = 0; i < capacity; i++)
+                check(q.contains(i) ^ ((i & 1) == 0));
+
+        } catch (Throwable t) { unexpected(t); }
+
     }
 
     //--------------------- Infrastructure ---------------------------
@@ -112,6 +257,6 @@
         new IteratorWeakConsistency().instanceMain(args);}
     public void instanceMain(String[] args) throws Throwable {
         try {test(args);} catch (Throwable t) {unexpected(t);}
-        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        System.err.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new AssertionError("Some tests failed");}
 }
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -32,6 +32,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
+import static java.util.concurrent.TimeUnit.*;
 
 @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
 public class OfferRemoveLoops {
@@ -65,15 +66,16 @@
     }
 
     void testQueue(final Queue q) throws Throwable {
-        System.out.println(q.getClass().getSimpleName());
+        System.err.println(q.getClass().getSimpleName());
         final long testDurationNanos = testDurationMillis * 1000L * 1000L;
         final long quittingTimeNanos = System.nanoTime() + testDurationNanos;
         final long timeoutMillis = 10L * 1000L;
         final int maxChunkSize = 1042;
         final int maxQueueSize = 10 * maxChunkSize;
+        final CountDownLatch done = new CountDownLatch(3);
 
-        /** Poor man's bounded buffer. */
-        final AtomicLong approximateCount = new AtomicLong(0L);
+        /** Poor man's bounded buffer; prevents unbounded queue expansion. */
+        final Semaphore offers = new Semaphore(maxQueueSize);
 
         abstract class CheckedThread extends Thread {
             CheckedThread(String name) {
@@ -89,42 +91,44 @@
             protected boolean quittingTime(long i) {
                 return (i % 1024) == 0 && quittingTime();
             }
-            protected abstract void realRun();
+            protected abstract void realRun() throws Exception;
             public void run() {
                 try { realRun(); } catch (Throwable t) { unexpected(t); }
             }
         }
 
         Thread offerer = new CheckedThread("offerer") {
-            protected void realRun() {
-                final long chunkSize = getRandom().nextInt(maxChunkSize) + 2;
+            protected void realRun() throws InterruptedException {
+                final int chunkSize = getRandom().nextInt(maxChunkSize) + 20;
                 long c = 0;
-                for (long i = 0; ! quittingTime(i); i++) {
+                while (! quittingTime()) {
                     if (q.offer(Long.valueOf(c))) {
                         if ((++c % chunkSize) == 0) {
-                            approximateCount.getAndAdd(chunkSize);
-                            while (approximateCount.get() > maxQueueSize)
-                                Thread.yield();
+                            offers.acquire(chunkSize);
                         }
                     } else {
                         Thread.yield();
-                    }}}};
+                    }
+                }
+                done.countDown();
+            }};
 
         Thread remover = new CheckedThread("remover") {
             protected void realRun() {
-                final long chunkSize = getRandom().nextInt(maxChunkSize) + 2;
+                final int chunkSize = getRandom().nextInt(maxChunkSize) + 20;
                 long c = 0;
-                for (long i = 0; ! quittingTime(i); i++) {
+                while (! quittingTime()) {
                     if (q.remove(Long.valueOf(c))) {
                         if ((++c % chunkSize) == 0) {
-                            approximateCount.getAndAdd(-chunkSize);
+                            offers.release(chunkSize);
                         }
                     } else {
                         Thread.yield();
                     }
                 }
                 q.clear();
-                approximateCount.set(0); // Releases waiting offerer thread
+                offers.release(1<<30);  // Releases waiting offerer thread
+                done.countDown();
             }};
 
         Thread scanner = new CheckedThread("scanner") {
@@ -139,18 +143,19 @@
                         break;
                     }
                     Thread.yield();
-                }}};
+                }
+                done.countDown();
+            }};
 
-        for (Thread thread : new Thread[] { offerer, remover, scanner }) {
-            thread.join(timeoutMillis + testDurationMillis);
-            if (thread.isAlive()) {
-                System.err.printf("Hung thread: %s%n", thread.getName());
-                failed++;
-                for (StackTraceElement e : thread.getStackTrace())
-                    System.err.println(e);
-                // Kludge alert
-                thread.stop();
-                thread.join(timeoutMillis);
+        if (! done.await(timeoutMillis + testDurationMillis, MILLISECONDS)) {
+            for (Thread thread : new Thread[] { offerer, remover, scanner }) {
+                if (thread.isAlive()) {
+                    System.err.printf("Hung thread: %s%n", thread.getName());
+                    failed++;
+                    for (StackTraceElement e : thread.getStackTrace())
+                        System.err.println(e);
+                    thread.interrupt();
+                }
             }
         }
     }
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,7 +36,7 @@
  * @bug 6785442
  * @summary Checks race between poll and remove(Object), while
  * occasionally moonlighting as a microbenchmark.
- * @run main RemovePollRace 12345
+ * @run main RemovePollRace 1234
  */
 
 import java.util.concurrent.ArrayBlockingQueue;
@@ -56,7 +56,7 @@
 import java.util.Map;
 
 public class RemovePollRace {
-    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    // Suitable for benchmarking.  Overridden by args[0] for testing.
     int count = 1024 * 1024;
 
     final Map<String,String> results = new ConcurrentHashMap<String,String>();
@@ -100,6 +100,7 @@
     void test(String[] args) throws Throwable {
         if (args.length > 0)
             count = Integer.valueOf(args[0]);
+
         // Warmup
         for (Queue<Boolean> queue : concurrentQueues())
             test(queue);
--- a/jdk/test/java/util/concurrent/CopyOnWriteArrayList/COWSubList.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/CopyOnWriteArrayList/COWSubList.java	Wed Jul 05 20:54:58 2017 +0200
@@ -51,8 +51,7 @@
             r.run();
             throw new RuntimeException("Failed: expected IOOBE to be thrown");
         } catch (IndexOutOfBoundsException x) {
-            // ok, excpeted
+            // ok, expected
         }
     }
 }
-
--- a/jdk/test/java/util/concurrent/CountDownLatch/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/CountDownLatch/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -120,7 +120,7 @@
     //----------------------------------------------------------------
     // One thread interrupted
     //----------------------------------------------------------------
-    public static void threadInterrupted() throws Throwable{
+    public static void threadInterrupted() throws Throwable {
         int count = 0;
         Basic test = new Basic();
         CountDownLatch latch = new CountDownLatch(3);
--- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -49,7 +49,6 @@
         Int(int i) { value = i; }
     }
 
-
     public static void main(String[] args) throws Exception {
         int maxStages = 5;
         int iters = 10000;
--- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -111,8 +111,6 @@
 
         if (r == 0) // avoid overoptimization
             System.out.println("useless result: " + r);
-
-
     }
 
 }
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java	Wed Jul 05 20:54:58 2017 +0200
@@ -24,55 +24,71 @@
 /*
  * @test
  * @bug 6399443
- * @run main/othervm AutoShutdown
+ * @run main/othervm/timeout=1000 AutoShutdown
  * @summary Check for auto-shutdown and gc of singleThreadExecutors
  * @author Martin Buchholz
  */
 
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-import static java.util.concurrent.Executors.*;
-import java.util.concurrent.Phaser;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import static java.util.concurrent.Executors.defaultThreadFactory;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
 
 public class AutoShutdown {
-    private static void waitForFinalizersToRun() {
-        for (int i = 0; i < 2; i++)
-            tryWaitForFinalizersToRun();
-    }
 
-    private static void tryWaitForFinalizersToRun() {
-        System.gc();
-        final CountDownLatch fin = new CountDownLatch(1);
-        new Object() { protected void finalize() { fin.countDown(); }};
-        System.gc();
-        try { fin.await(); }
-        catch (InterruptedException ie) { throw new Error(ie); }
+    static void await(CountDownLatch latch) throws InterruptedException {
+        if (!latch.await(100L, TimeUnit.SECONDS))
+            throw new AssertionError("timed out waiting for latch");
     }
 
     private static void realMain(String[] args) throws Throwable {
-        final Phaser phaser = new Phaser(3);
-        Runnable trivialRunnable = new Runnable() {
-            public void run() {
-                phaser.arriveAndAwaitAdvance();
-            }
+        final Executor[] executors = {
+            newSingleThreadExecutor(),
+            newSingleThreadExecutor(defaultThreadFactory()),
+            // TODO: should these executors also auto-shutdown?
+            //newFixedThreadPool(1),
+            //newSingleThreadScheduledExecutor(),
+            //newSingleThreadScheduledExecutor(defaultThreadFactory()),
         };
-        int count0 = Thread.activeCount();
-        Executor e1 = newSingleThreadExecutor();
-        Executor e2 = newSingleThreadExecutor(defaultThreadFactory());
-        e1.execute(trivialRunnable);
-        e2.execute(trivialRunnable);
-        phaser.arriveAndAwaitAdvance();
-        equal(Thread.activeCount(), count0 + 2);
-        e1 = e2 = null;
-        for (int i = 0; i < 10 && Thread.activeCount() > count0; i++)
-            tryWaitForFinalizersToRun();
-        for (int i = 0; i < 10; ++i) { // give JVM a chance to settle.
-            if (Thread.activeCount() == count0)
-                return;
-            Thread.sleep(1000);
+        final ConcurrentLinkedQueue<WeakReference<Thread>> poolThreads
+            = new ConcurrentLinkedQueue<>();
+        final CountDownLatch threadStarted
+            = new CountDownLatch(executors.length);
+        final CountDownLatch pleaseProceed
+            = new CountDownLatch(1);
+        Runnable task = new Runnable() { public void run() {
+            try {
+                poolThreads.add(new WeakReference<>(Thread.currentThread()));
+                threadStarted.countDown();
+                await(pleaseProceed);
+            } catch (Throwable t) { unexpected(t); }
+        }};
+        for (Executor executor : executors)
+            executor.execute(task);
+        await(threadStarted);
+        pleaseProceed.countDown();
+        Arrays.fill(executors, null);   // make executors unreachable
+        boolean done = false;
+        for (long timeout = 1L; !done && timeout <= 128L; timeout *= 2) {
+            System.gc();
+            done = true;
+            for (WeakReference<Thread> ref : poolThreads) {
+                Thread thread = ref.get();
+                if (thread != null) {
+                    TimeUnit.SECONDS.timedJoin(thread, timeout);
+                    if (thread.isAlive())
+                        done = false;
+                }
+            }
         }
-        equal(Thread.activeCount(), count0);
+        if (!done)
+            throw new AssertionError("pool threads did not terminate");
     }
 
     //--------------------- Infrastructure ---------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8073704
+ * @summary Checks that once isDone() returns true,
+ * get() never throws InterruptedException or TimeoutException
+ */
+
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class DoneMeansDone {
+    public static void main(String[] args) throws Throwable {
+        final int iters = 1000;
+        final int nThreads = 2;
+        final AtomicBoolean done = new AtomicBoolean(false);
+        final AtomicReference<FutureTask<Boolean>> a = new AtomicReference<>();
+        final CountDownLatch threadsStarted = new CountDownLatch(nThreads);
+        final Callable<Boolean> alwaysTrue = new Callable<Boolean>() {
+            public Boolean call() {
+                return true;
+            }};
+
+        final Runnable observer = new Runnable() { public void run() {
+            threadsStarted.countDown();
+            final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+            try {
+                for (FutureTask<Boolean> f; !done.get();) {
+                    f = a.get();
+                    if (f != null) {
+                        do {} while (!f.isDone());
+                        Thread.currentThread().interrupt();
+                        if (!(rnd.nextBoolean()
+                              ? f.get()
+                              : f.get(-1L, TimeUnit.DAYS)))
+                            throw new AssertionError();
+                    }
+                }
+            } catch (Exception t) { throw new AssertionError(t); }
+        }};
+
+        final ArrayList<Future<?>> futures = new ArrayList<>(nThreads);
+        final ExecutorService pool = Executors.newCachedThreadPool();
+        for (int i = 0; i < nThreads; i++)
+            futures.add(pool.submit(observer));
+        threadsStarted.await();
+        for (int i = 0; i < iters; i++) {
+            FutureTask<Boolean> f = new FutureTask<>(alwaysTrue);
+            a.set(f);
+            f.run();
+        }
+        done.set(true);
+        pool.shutdown();
+        if (!pool.awaitTermination(10L, TimeUnit.SECONDS))
+            throw new AssertionError();
+        for (Future<?> future : futures)
+            future.get();
+    }
+}
--- a/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2012, 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
@@ -22,6 +21,11 @@
  */
 
 /*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
  * Written by Martin Buchholz with assistance from members of JCP JSR-166
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
--- a/jdk/test/java/util/concurrent/FutureTask/ExplicitSet.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/FutureTask/ExplicitSet.java	Wed Jul 05 20:54:58 2017 +0200
@@ -58,7 +58,7 @@
         SettableTask() {
             super(new Callable<Boolean>() {
                     public Boolean call() {
-                        fail ("The task should never be run!");
+                        fail("The task should never be run!");
                         return null;
                     };
                 });
--- a/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java	Wed Jul 05 20:54:58 2017 +0200
@@ -44,4 +44,3 @@
         } catch (TimeoutException success) {}
     }
 }
-
--- a/jdk/test/java/util/concurrent/Phaser/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -97,7 +97,8 @@
             equal(phase, atTheStartingGate.arrive());
             int awaitPhase = atTheStartingGate.awaitAdvanceInterruptibly
                 (phase, 30, SECONDS);
-            if (expectNextPhase) check(awaitPhase == (phase + 1));
+            if (expectNextPhase) check(awaitPhase == phase + 1);
+            else check(awaitPhase == phase || awaitPhase == phase + 1);
 
             pass();
         } catch (Throwable t) {
@@ -249,13 +250,11 @@
             Phaser phaser = new Phaser(3);
             Iterator<Arriver> arrivers = arriverIterator(phaser);
             int phase = phaser.getPhase();
-            for (int i = 0; i < 4; i++) {
+            for (int i = 0; i < 10; i++) {
                 check(phaser.getPhase() == phase);
                 Awaiter a1 = awaiter(phaser, 30, SECONDS); a1.start();
                 Arriver a2 = arrivers.next(); a2.start();
                 toTheStartingGate();
-                // allow a1 to block in awaitAdvanceInterruptibly
-                Thread.sleep(2000);
                 a1.interrupt();
                 a1.join();
                 phaser.arriveAndAwaitAdvance();
@@ -273,7 +272,7 @@
         // Phaser is terminated while threads are waiting
         //----------------------------------------------------------------
         try {
-            for (int i = 0; i < 4; i++) {
+            for (int i = 0; i < 10; i++) {
                 Phaser phaser = new Phaser(3);
                 Iterator<Awaiter> awaiters = awaiterIterator(phaser);
                 Arriver a1 = awaiters.next(); a1.start();
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Wed Jul 05 20:54:58 2017 +0200
@@ -88,7 +88,7 @@
     /**
      * Attempts to test exhaustively and deterministically, all 20
      * possible ways that one task can be scheduled in the maximal
-     * distant future, while at the same time an existing tasks's time
+     * distant future, while at the same time an existing task's time
      * has already expired.
      */
     void test(String[] args) throws Throwable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from members of
+ * JCP JSR-166 Expert Group and released to the public domain, as explained
+ * at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Ensure that waiting pool threads don't retain refs to tasks.
+ */
+
+import java.lang.ref.*;
+import java.util.concurrent.*;
+
+public class GCRetention {
+    /**
+     * A custom thread pool with a custom RunnableScheduledFuture, for the
+     * sole purpose of ensuring that the task retains a strong reference to
+     * the Runnable even after cancellation.
+     */
+    static class CustomPool extends ScheduledThreadPoolExecutor {
+        CustomPool(int n) { super(n); }
+        protected <V> RunnableScheduledFuture<V> decorateTask(
+            final Runnable r,
+            final RunnableScheduledFuture<V> task) {
+            return new RunnableScheduledFuture<V>() {
+                public void run() { System.err.println(r); task.run(); }
+                public boolean isPeriodic() { return task.isPeriodic(); }
+                public V get()
+                    throws InterruptedException,ExecutionException
+                    { return task.get(); }
+                public V get(long x, TimeUnit y)
+                    throws InterruptedException,ExecutionException,TimeoutException
+                    { return task.get(x, y); }
+                public boolean isDone() { return task.isDone(); }
+                public boolean isCancelled() { return task.isCancelled(); }
+                public boolean cancel(boolean x) { return task.cancel(x); }
+                public long getDelay(TimeUnit x) { return task.getDelay(x); }
+                public int compareTo(Delayed x) { return task.compareTo(x); }
+            };
+        }
+    }
+
+    int countRefsCleared(WeakReference<?>[] refs) {
+        int count = 0;
+        for (WeakReference<?> ref : refs)
+            if (ref.get() == null)
+                count++;
+        return count;
+    }
+
+    void test(String[] args) throws Throwable {
+        CustomPool pool = new CustomPool(10);
+        final int size = 100;
+        WeakReference<?>[] refs = new WeakReference<?>[size];
+        Future<?>[] futures = new Future<?>[size];
+        for (int i = 0; i < size; i++) {
+            final Object x = new Object();
+            refs[i] = new WeakReference<Object>(x);
+            // Create a Runnable with a strong ref to x.
+            Runnable r = new Runnable() {
+                    public void run() { System.out.println(x); }
+                };
+            // Schedule a custom task with a strong reference to r.
+            // Later tasks have earlier expiration, to ensure multiple
+            // residents of queue head.
+            futures[i] = pool.schedule(r, size*2-i, TimeUnit.MINUTES);
+        }
+        Thread.sleep(10);
+        for (int i = 0; i < size; i++) {
+            if (futures[i] != null) {
+                futures[i].cancel(false);
+                futures[i] = null;
+            }
+        }
+        pool.purge();
+        int cleared = 0;
+        for (int i = 0;
+             i < 10 && (cleared = countRefsCleared(refs)) < size;
+             i++) {
+            System.gc();
+            System.runFinalization();
+            Thread.sleep(10);
+        }
+        pool.shutdown();
+        pool.awaitTermination(10, TimeUnit.SECONDS);
+        if (cleared < size)
+            throw new Error(String.format
+                            ("references to %d/%d tasks retained (\"leaked\")",
+                             size - cleared, size));
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new GCRetention().instanceMain(args);}
+    void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8022642 8065320 8129861
+ * @summary Ensure relative sanity when zero core threads
+ */
+
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.*;
+import java.util.concurrent.locks.*;
+import java.lang.reflect.*;
+
+public class ZeroCoreThreads {
+    static boolean hasWaiters(ReentrantLock lock, Condition condition) {
+        lock.lock();
+        try {
+            return lock.hasWaiters(condition);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    static <T> T getField(Object x, String fieldName) {
+        try {
+            Field field = x.getClass().getDeclaredField(fieldName);
+            field.setAccessible(true);
+            return (T) field.get(x);
+        } catch (ReflectiveOperationException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    void test(String[] args) throws Throwable {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(0);
+        try {
+            test(p);
+        } finally {
+            p.shutdownNow();
+            check(p.awaitTermination(10L, SECONDS));
+        }
+    }
+
+    void test(ScheduledThreadPoolExecutor p) throws Throwable {
+        Runnable dummy = new Runnable() { public void run() {
+            throw new AssertionError("shouldn't get here"); }};
+        BlockingQueue q = p.getQueue();
+        ReentrantLock lock = getField(q, "lock");
+        Condition available = getField(q, "available");
+
+        equal(0, p.getPoolSize());
+        equal(0, p.getLargestPoolSize());
+        equal(0L, p.getTaskCount());
+        equal(0L, p.getCompletedTaskCount());
+        p.schedule(dummy, 1L, HOURS);
+        // Ensure one pool thread actually waits in timed queue poll
+        long t0 = System.nanoTime();
+        while (!hasWaiters(lock, available)) {
+            if (System.nanoTime() - t0 > SECONDS.toNanos(10L))
+                throw new AssertionError
+                    ("timed out waiting for a waiter to show up");
+            Thread.yield();
+        }
+        equal(1, p.getPoolSize());
+        equal(1, p.getLargestPoolSize());
+        equal(1L, p.getTaskCount());
+        equal(0L, p.getCompletedTaskCount());
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new ZeroCoreThreads().instanceMain(args);}
+    void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java	Wed Jul 05 20:54:58 2017 +0200
@@ -55,7 +55,7 @@
         return count;
     }
 
-    long millisElapsedSince(long t0) {
+    static long millisElapsedSince(long t0) {
         return (System.nanoTime() - t0) / (1000L * 1000L);
     }
 
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java	Wed Jul 05 20:54:58 2017 +0200
@@ -41,7 +41,6 @@
         if (x == null ? y == null : x.equals(y)) pass();
         else {System.out.println(x + " not equal to " + y); fail(); }}
 
-
     private static class CustomTask<V> extends FutureTask<V> {
         public static final AtomicInteger births = new AtomicInteger(0);
         CustomTask(Callable<V> c) { super(c); births.getAndIncrement(); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz and Doug Lea with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Should be able to shutdown a pool when worker creation failed.
+ */
+
+import java.util.concurrent.*;
+
+public class FlakyThreadFactory {
+    void test(String[] args) throws Throwable {
+        test(NullPointerException.class,
+             new ThreadFactory() {
+                public Thread newThread(Runnable r) {
+                    throw new NullPointerException();
+                }});
+        test(OutOfMemoryError.class,
+             new ThreadFactory() {
+                public Thread newThread(Runnable r) {
+                    new Thread(null, r, "a natural OOME", 1L << 60);
+                    // """On some platforms, the value of the stackSize
+                    // parameter may have no effect whatsoever."""
+                    throw new OutOfMemoryError("artificial OOME");
+                }});
+        test(null,
+             new ThreadFactory() {
+                public Thread newThread(Runnable r) {
+                    return null;
+                }});
+    }
+
+    void test(final Class<?> exceptionClass,
+              final ThreadFactory failingThreadFactory)
+            throws Throwable {
+        ThreadFactory flakyThreadFactory = new ThreadFactory() {
+            int seq = 0;
+            public Thread newThread(Runnable r) {
+                if (seq++ < 4)
+                    return new Thread(r);
+                else
+                    return failingThreadFactory.newThread(r);
+            }};
+        ThreadPoolExecutor pool =
+            new ThreadPoolExecutor(10, 10,
+                                   0L, TimeUnit.SECONDS,
+                                   new LinkedBlockingQueue(),
+                                   flakyThreadFactory);
+        try {
+            for (int i = 0; i < 8; i++)
+                pool.submit(new Runnable() { public void run() {} });
+            check(exceptionClass == null);
+        } catch (Throwable t) {
+            /* t.printStackTrace(); */
+            check(exceptionClass.isInstance(t));
+        }
+        pool.shutdown();
+        check(pool.awaitTermination(10L, TimeUnit.SECONDS));
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new FlakyThreadFactory().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz and Jason Mehrens with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Only one thread should be created when a thread needs to
+ * be kept alive to service a delayed task waiting in the queue.
+ */
+
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.*;
+import java.util.concurrent.atomic.*;
+
+public class ThreadRestarts {
+    public static void main(String[] args) throws Exception {
+        test(false);
+        test(true);
+    }
+
+    private static void test(boolean allowTimeout) throws Exception {
+        CountingThreadFactory ctf = new CountingThreadFactory();
+        ScheduledThreadPoolExecutor stpe
+            = new ScheduledThreadPoolExecutor(10, ctf);
+        try {
+            Runnable nop = new Runnable() { public void run() {}};
+            stpe.schedule(nop, 10*1000L, MILLISECONDS);
+            stpe.setKeepAliveTime(1L, MILLISECONDS);
+            stpe.allowCoreThreadTimeOut(allowTimeout);
+            MILLISECONDS.sleep(100L);
+        } finally {
+            stpe.shutdownNow();
+            stpe.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
+        }
+        if (ctf.count.get() > 1)
+            throw new AssertionError(
+                String.format("%d threads created, 1 expected",
+                              ctf.count.get()));
+    }
+
+    static class CountingThreadFactory implements ThreadFactory {
+        final AtomicLong count = new AtomicLong(0L);
+
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(r);
+            count.getAndIncrement();
+            return t;
+        }
+    }
+}
--- a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java	Wed Jul 05 20:54:58 2017 +0200
@@ -36,11 +36,12 @@
  * @author Doug Lea
  * @bug 8004138
  * @summary Check if ForkJoinPool table leaks thrown exceptions.
- * @run main/othervm -Xmx32m FJExceptionTableLeak
+ * @run main/othervm/timeout=1200 -Xmx32m FJExceptionTableLeak
  */
 import java.util.concurrent.*;
 
 public class FJExceptionTableLeak {
+    // TODO: make this test use less time!
 
     // Run with TASKS_PER_STEP * 40 < Xmx < STEPS * TASKS_PER_STEP * 40
     // These work for Xmx32m:
--- a/jdk/test/java/util/concurrent/forkjoin/Integrate.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/forkjoin/Integrate.java	Wed Jul 05 20:54:58 2017 +0200
@@ -59,14 +59,15 @@
     static final int DYNAMIC = 0;
     static final int FORK = 1;
 
-    // the function to integrate
-    static double computeFunction(double x)  {
+    /** the function to integrate */
+    static double computeFunction(double x) {
         return (x * x + 1.0) * x;
     }
 
     static final double start = 0.0;
     static final double end = 1536.0;
-    /*
+
+    /**
      * The number of recursive calls for
      * integrate from start to end.
      * (Empirically determined)
@@ -127,7 +128,6 @@
         g.shutdown();
     }
 
-
     // Sequential version
     static final class SQuad extends RecursiveAction {
         static double computeArea(ForkJoinPool pool, double l, double r) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,412 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 4486658
+ * @run main/timeout=7200 CheckedLockLoops
+ * @summary basic safety and liveness of ReentrantLocks, and other locks based on them
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+public final class CheckedLockLoops {
+    static final ExecutorService pool = Executors.newCachedThreadPool();
+    static final LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom();
+    static boolean print = false;
+    static boolean doBuiltin = false;
+
+    public static void main(String[] args) throws Exception {
+        int maxThreads = 5;
+        int iters = 100000;
+
+        if (args.length > 0)
+            maxThreads = Integer.parseInt(args[0]);
+
+        rng.setSeed(3122688L);
+
+        print = false;
+        System.out.println("Warmup...");
+        oneTest(3, 10000);
+        Thread.sleep(1000);
+        oneTest(2, 10000);
+        Thread.sleep(100);
+        oneTest(1, 100000);
+        Thread.sleep(100);
+        oneTest(1, 100000);
+        Thread.sleep(1000);
+        print = true;
+
+        for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) {
+            System.out.println("Threads:" + i);
+            oneTest(i, iters / i);
+            Thread.sleep(100);
+        }
+        pool.shutdown();
+        if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
+            throw new Error();
+    }
+
+    static void oneTest(int nthreads, int iters) throws Exception {
+        int v = rng.next();
+        if (doBuiltin) {
+            if (print)
+                System.out.print("builtin lock          ");
+            new BuiltinLockLoop().test(v, nthreads, iters);
+            Thread.sleep(10);
+        }
+
+        if (print)
+            System.out.print("ReentrantLock         ");
+        new ReentrantLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("Mutex                 ");
+        new MutexLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("ReentrantWriteLock    ");
+        new ReentrantWriteLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("ReentrantReadWriteLock");
+        new ReentrantReadWriteLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("Semaphore             ");
+        new SemaphoreLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("fair Semaphore        ");
+        new FairSemaphoreLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("FairReentrantLock     ");
+        new FairReentrantLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("FairRWriteLock         ");
+        new FairReentrantWriteLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+
+        if (print)
+            System.out.print("FairRReadWriteLock     ");
+        new FairReentrantReadWriteLockLoop().test(v, nthreads, iters);
+        Thread.sleep(10);
+    }
+
+    abstract static class LockLoop implements Runnable {
+        int value;
+        int checkValue;
+        int iters;
+        volatile int result;
+        final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
+        CyclicBarrier barrier;
+
+        final int setValue(int v) {
+            checkValue = v ^ 0x55555555;
+            value = v;
+            return v;
+        }
+
+        final int getValue() {
+            int v = value;
+            if (checkValue != ~(v ^ 0xAAAAAAAA))
+                throw new Error("lock protection failure");
+            return v;
+        }
+
+        final void test(int initialValue, int nthreads, int iters) throws Exception {
+            setValue(initialValue);
+            this.iters = iters;
+            barrier = new CyclicBarrier(nthreads+1, timer);
+            for (int i = 0; i < nthreads; ++i)
+                pool.execute(this);
+            barrier.await();
+            barrier.await();
+            long time = timer.getTime();
+            if (print) {
+                long tpi = time / (iters * nthreads);
+                System.out.print("\t" + LoopHelpers.rightJustify(tpi) + " ns per update");
+                //                double secs = (double)(time) / 1000000000.0;
+                //                System.out.print("\t " + secs + "s run time");
+                System.out.println();
+            }
+
+            if (result == 0) // avoid overoptimization
+                System.out.println("useless result: " + result);
+        }
+        abstract int loop(int n);
+        public final void run() {
+            try {
+                barrier.await();
+                result += loop(iters);
+                barrier.await();
+            }
+            catch (Exception ie) {
+                return;
+            }
+        }
+
+    }
+
+    private static class BuiltinLockLoop extends LockLoop {
+        final int loop(int n) {
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                synchronized (this) {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class ReentrantLockLoop extends LockLoop {
+        private final ReentrantLock lock = new ReentrantLock();
+        final int loop(int n) {
+            final ReentrantLock lock = this.lock;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                lock.lock();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    lock.unlock();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class MutexLoop extends LockLoop {
+        private final Mutex lock = new Mutex();
+        final int loop(int n) {
+            final Mutex lock = this.lock;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                lock.lock();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    lock.unlock();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class FairReentrantLockLoop extends LockLoop {
+        private final ReentrantLock lock = new ReentrantLock(true);
+        final int loop(int n) {
+            final ReentrantLock lock = this.lock;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                lock.lock();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    lock.unlock();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class ReentrantWriteLockLoop extends LockLoop {
+        private final Lock lock = new ReentrantReadWriteLock().writeLock();
+        final int loop(int n) {
+            final Lock lock = this.lock;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                lock.lock();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    lock.unlock();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class FairReentrantWriteLockLoop extends LockLoop {
+        final Lock lock = new ReentrantReadWriteLock(true).writeLock();
+        final int loop(int n) {
+            final Lock lock = this.lock;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                lock.lock();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    lock.unlock();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class SemaphoreLoop extends LockLoop {
+        private final Semaphore sem = new Semaphore(1, false);
+        final int loop(int n) {
+            final Semaphore sem = this.sem;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                sem.acquireUninterruptibly();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    sem.release();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+    private static class FairSemaphoreLoop extends LockLoop {
+        private final Semaphore sem = new Semaphore(1, true);
+        final int loop(int n) {
+            final Semaphore sem = this.sem;
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                sem.acquireUninterruptibly();
+                try {
+                    x = setValue(LoopHelpers.compute1(getValue()));
+                }
+                finally {
+                    sem.release();
+                }
+                sum += LoopHelpers.compute2(x);
+            }
+            return sum;
+        }
+    }
+
+    private static class ReentrantReadWriteLockLoop extends LockLoop {
+        private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+        final int loop(int n) {
+            final Lock rlock = lock.readLock();
+            final Lock wlock = lock.writeLock();
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                if ((n & 16) != 0) {
+                    rlock.lock();
+                    try {
+                        x = LoopHelpers.compute1(getValue());
+                        x = LoopHelpers.compute2(x);
+                    }
+                    finally {
+                        rlock.unlock();
+                    }
+                }
+                else {
+                    wlock.lock();
+                    try {
+                        setValue(x);
+                    }
+                    finally {
+                        wlock.unlock();
+                    }
+                    sum += LoopHelpers.compute2(x);
+                }
+            }
+            return sum;
+        }
+
+    }
+
+    private static class FairReentrantReadWriteLockLoop extends LockLoop {
+        private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+        final int loop(int n) {
+            final Lock rlock = lock.readLock();
+            final Lock wlock = lock.writeLock();
+            int sum = 0;
+            int x = 0;
+            while (n-- > 0) {
+                if ((n & 16) != 0) {
+                    rlock.lock();
+                    try {
+                        x = LoopHelpers.compute1(getValue());
+                        x = LoopHelpers.compute2(x);
+                    }
+                    finally {
+                        rlock.unlock();
+                    }
+                }
+                else {
+                    wlock.lock();
+                    try {
+                        setValue(x);
+                    }
+                    finally {
+                        wlock.unlock();
+                    }
+                    sum += LoopHelpers.compute2(x);
+                }
+            }
+            return sum;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Misc utilities in JSR166 performance tests
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+class LoopHelpers {
+
+    // Some mindless computation to do between synchronizations...
+
+    /**
+     * generates 32 bit pseudo-random numbers.
+     * Adapted from http://www.snippets.org
+     */
+    public static int compute1(int x) {
+        int lo = 16807 * (x & 0xFFFF);
+        int hi = 16807 * (x >>> 16);
+        lo += (hi & 0x7FFF) << 16;
+        if ((lo & 0x80000000) != 0) {
+            lo &= 0x7fffffff;
+            ++lo;
+        }
+        lo += hi >>> 15;
+        if (lo == 0 || (lo & 0x80000000) != 0) {
+            lo &= 0x7fffffff;
+            ++lo;
+        }
+        return lo;
+    }
+
+    /**
+     *  Computes a linear congruential random number a random number
+     *  of times.
+     */
+    public static int compute2(int x) {
+        int loops = (x >>> 4) & 7;
+        while (loops-- > 0) {
+            x = (x * 2147483647) % 16807;
+        }
+        return x;
+    }
+
+    /**
+     * An actually useful random number generator, but unsynchronized.
+     * Basically same as java.util.Random.
+     */
+    public static class SimpleRandom {
+        private static final long multiplier = 0x5DEECE66DL;
+        private static final long addend = 0xBL;
+        private static final long mask = (1L << 48) - 1;
+        static final AtomicLong seq = new AtomicLong(1);
+        private long seed = System.nanoTime() + seq.getAndIncrement();
+
+        public void setSeed(long s) {
+            seed = s;
+        }
+
+        public int next() {
+            long nextseed = (seed * multiplier + addend) & mask;
+            seed = nextseed;
+            return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
+        }
+    }
+
+    public static class BarrierTimer implements Runnable {
+        public volatile long startTime;
+        public volatile long endTime;
+        public void run() {
+            long t = System.nanoTime();
+            if (startTime == 0)
+                startTime = t;
+            else
+                endTime = t;
+        }
+        public void clear() {
+            startTime = 0;
+            endTime = 0;
+        }
+        public long getTime() {
+            return endTime - startTime;
+        }
+    }
+
+    public static String rightJustify(long n) {
+        // There's probably a better way to do this...
+        String field = "         ";
+        String num = Long.toString(n);
+        if (num.length() >= field.length())
+            return num;
+        StringBuffer b = new StringBuffer(field);
+        b.replace(b.length()-num.length(), b.length(), num);
+        return b.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/Mutex.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.io.*;
+
+/**
+ * A sample user extension of AbstractQueuedSynchronizer.
+ */
+public class Mutex implements Lock, java.io.Serializable {
+    private static class Sync extends AbstractQueuedSynchronizer {
+        public boolean isHeldExclusively() { return getState() == 1; }
+
+        public boolean tryAcquire(int acquires) {
+            assert acquires == 1; // Does not use multiple acquires
+            return compareAndSetState(0, 1);
+        }
+
+        public boolean tryRelease(int releases) {
+            setState(0);
+            return true;
+        }
+
+        Condition newCondition() { return new ConditionObject(); }
+
+        private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
+            s.defaultReadObject();
+            setState(0); // reset to unlocked state
+        }
+    }
+
+    private final Sync sync = new Sync();
+    public void lock() {
+        sync.acquire(1);
+    }
+    public boolean tryLock() {
+        return sync.tryAcquire(1);
+    }
+    public void lockInterruptibly() throws InterruptedException {
+        sync.acquireInterruptibly(1);
+    }
+    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+    }
+    public void unlock() { sync.release(1); }
+    public Condition newCondition() { return sync.newCondition(); }
+    public boolean isLocked() { return sync.isHeldExclusively(); }
+    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+}
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java	Wed Jul 05 20:54:58 2017 +0200
@@ -28,14 +28,32 @@
  * @author Martin Buchholz
  */
 
-// Note: this file is now out of sync with the jsr166 CVS repository due to the fix for 7092140
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
-import java.util.*;
-import java.util.regex.*;
-import java.util.concurrent.*;
-import java.util.concurrent.locks.*;
-import static java.util.concurrent.TimeUnit.*;
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.lang.ref.WeakReference;
+import java.util.Random;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class TimedAcquireLeak {
     static String javahome() {
@@ -96,18 +114,34 @@
                                   Callable<T> callable) throws Throwable {
         p.getInputStream().read();
         T result = callable.call();
-        OutputStream os = p.getOutputStream();
-        os.write((byte)'\n'); os.flush();
+        sendByte(p.getOutputStream());
         return result;
     }
 
+    /** No guarantees, but effective in practice. */
+    private static void forceFullGc() {
+        CountDownLatch finalizeDone = new CountDownLatch(1);
+        WeakReference<?> ref = new WeakReference<Object>(new Object() {
+            protected void finalize() { finalizeDone.countDown(); }});
+        try {
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+                    System.runFinalization(); // try to pick up stragglers
+                    return;
+                }
+            }
+        } catch (InterruptedException unexpected) {
+            throw new AssertionError("unexpected InterruptedException");
+        }
+        throw new AssertionError("failed to do a \"full\" gc");
+    }
+
     // To be called exactly twice by the child process
     public static void rendezvousChild() {
         try {
-            for (int i = 0; i < 100; i++) {
-                System.gc(); System.runFinalization(); Thread.sleep(50);
-            }
-            System.out.write((byte)'\n'); System.out.flush();
+            forceFullGc();
+            sendByte(System.out);
             System.in.read();
         } catch (Throwable t) { throw new Error(t); }
     }
@@ -118,6 +152,12 @@
         return matcher.group(group);
     }
 
+    /** It's all about sending a message! */
+    static void sendByte(OutputStream s) throws IOException {
+        s.write('!');
+        s.flush();
+    }
+
     static int objectsInUse(final Process child,
                             final String childPid,
                             final String className) {
@@ -155,6 +195,9 @@
             childClassName, uniqueID
         };
         final Process p = new ProcessBuilder(jobCmd).start();
+        // Ensure subprocess jvm has started, so that jps can find it
+        p.getInputStream().read();
+        sendByte(p.getOutputStream());
 
         final String childPid =
             match(commandOutputOf(jps, "-m"),
@@ -167,10 +210,19 @@
         failed += p.exitValue();
 
         // Check that no objects were leaked.
+        //
+        // TODO: This test is very brittle, depending on current JDK
+        // implementation, and needing occasional adjustment.
         System.out.printf("%d -> %d%n", n0, n1);
-        check(Math.abs(n1 - n0) < 2); // Almost always n0 == n1
-        check(n1 < 20);
+        // Almost always n0 == n1
+        // Maximum jitter observed in practice is 10 -> 17
+        check(Math.abs(n1 - n0) < 10);
+        check(n1 < 25);
         drainers.shutdown();
+        if (!drainers.awaitTermination(10L, SECONDS)) {
+            drainers.shutdownNow(); // last resort
+            throw new AssertionError("thread pool did not terminate");
+        }
     }
 
     //----------------------------------------------------------------
@@ -187,6 +239,10 @@
         }
 
         public static void main(String[] args) throws Throwable {
+            // Synchronize with parent process, so that jps can find us
+            sendByte(System.out);
+            System.in.read();
+
             final ReentrantLock lock = new ReentrantLock();
             lock.lock();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8074773
+ * @summary Stress test looks for lost unparks
+ * @run main/timeout=1200 ParkLoops
+ */
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+import java.util.concurrent.locks.LockSupport;
+
+public final class ParkLoops {
+    static final int THREADS = 4; // must be power of two
+    // static final int ITERS = 2_000_000;
+    // static final int TIMEOUT = 3500;  // in seconds
+    static final int ITERS = 100_000;
+    static final int TIMEOUT = 1000;  // in seconds
+
+    static class Parker implements Runnable {
+        static {
+            // Reduce the risk of rare disastrous classloading in first call to
+            // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+            Class<?> ensureLoaded = LockSupport.class;
+        }
+
+        private final AtomicReferenceArray<Thread> threads;
+        private final CountDownLatch done;
+
+        Parker(AtomicReferenceArray<Thread> threads, CountDownLatch done) {
+            this.threads = threads;
+            this.done = done;
+        }
+
+        public void run() {
+            final SimpleRandom rng = new SimpleRandom();
+            final Thread current = Thread.currentThread();
+            for (int k = ITERS, j; k > 0; k--) {
+                do {
+                    j = rng.next() & (THREADS - 1);
+                } while (!threads.compareAndSet(j, null, current));
+                do {                    // handle spurious wakeups
+                    LockSupport.park();
+                } while (threads.get(j) == current);
+            }
+            done.countDown();
+        }
+    }
+
+    static class Unparker implements Runnable {
+        static {
+            // Reduce the risk of rare disastrous classloading in first call to
+            // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+            Class<?> ensureLoaded = LockSupport.class;
+        }
+
+        private final AtomicReferenceArray<Thread> threads;
+        private final CountDownLatch done;
+
+        Unparker(AtomicReferenceArray<Thread> threads, CountDownLatch done) {
+            this.threads = threads;
+            this.done = done;
+        }
+
+        public void run() {
+            final SimpleRandom rng = new SimpleRandom();
+            for (int n = 0; (n++ & 0xff) != 0 || done.getCount() > 0;) {
+                int j = rng.next() & (THREADS - 1);
+                Thread parker = threads.get(j);
+                if (parker != null &&
+                    threads.compareAndSet(j, parker, null)) {
+                    LockSupport.unpark(parker);
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        final ExecutorService pool = Executors.newCachedThreadPool();
+        final AtomicReferenceArray<Thread> threads
+            = new AtomicReferenceArray<>(THREADS);
+        final CountDownLatch done = new CountDownLatch(THREADS);
+        final Runnable parker = new Parker(threads, done);
+        final Runnable unparker = new Unparker(threads, done);
+        for (int i = 0; i < THREADS; i++) {
+            pool.submit(parker);
+            pool.submit(unparker);
+        }
+        try {
+          if (!done.await(TIMEOUT, SECONDS)) {
+            dumpAllStacks();
+            throw new AssertionError("lost unpark");
+          }
+        } finally {
+          pool.shutdown();
+          pool.awaitTermination(10L, SECONDS);
+        }
+    }
+
+    static void dumpAllStacks() {
+        ThreadInfo[] threadInfos =
+            ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
+        for (ThreadInfo threadInfo : threadInfos) {
+            System.err.print(threadInfo);
+        }
+    }
+
+    /**
+     * An actually useful random number generator, but unsynchronized.
+     * Basically same as java.util.Random.
+     */
+    public static class SimpleRandom {
+        private static final long multiplier = 0x5DEECE66DL;
+        private static final long addend = 0xBL;
+        private static final long mask = (1L << 48) - 1;
+        static final AtomicLong seq = new AtomicLong(1);
+        private long seed = System.nanoTime() + seq.getAndIncrement();
+
+        public int next() {
+            long nextseed = (seed * multiplier + addend) & mask;
+            seed = nextseed;
+            return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
+        }
+    }
+}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,10 +35,10 @@
  * @test
  * @bug 4486658
  * @run main/timeout=2800 CancelledLockLoops
- * @summary tests lockInterruptibly.
- * Checks for responsiveness of locks to interrupts. Runs under that
- * assumption that ITERS_VALUE computations require more than TIMEOUT
- * msecs to complete.
+ * @summary tests ReentrantLock.lockInterruptibly.
+ * Checks for responsiveness of locks to interrupts.  Runs under the
+ * assumption that ITERS computations require more than TIMEOUT msecs
+ * to complete.
  */
 
 import java.util.concurrent.*;
@@ -48,11 +48,12 @@
 public final class CancelledLockLoops {
     static final Random rng = new Random();
     static boolean print = false;
-    static final int ITERS = 5000000;
+    static final int ITERS = 1000000;
     static final long TIMEOUT = 100;
 
     public static void main(String[] args) throws Exception {
         int maxThreads = (args.length > 0) ? Integer.parseInt(args[0]) : 5;
+
         print = true;
 
         for (int i = 2; i <= maxThreads; i += (i+1) >>> 1) {
@@ -112,7 +113,7 @@
                 lock.unlock();
             }
             if (c != 2)
-                throw new Error("Completed != 2");
+                throw new Error("Completed == " + c + "; expected 2");
             int r = result;
             if (r == 0) // avoid overoptimization
                 System.out.println("useless result: " + r);
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -57,7 +57,6 @@
         if (args.length > 0)
             maxThreads = Integer.parseInt(args[0]);
 
-
         print = true;
 
         for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) {
@@ -140,6 +139,4 @@
             }
         }
     }
-
-
 }
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java	Wed Jul 05 20:54:58 2017 +0200
@@ -134,7 +134,7 @@
         int position;
         int total;
 
-        Runner(Map<Integer,Integer> map, Integer[] key,  CyclicBarrier barrier) {
+        Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
             this.map = map;
             this.key = key;
             this.barrier = barrier;
@@ -142,7 +142,7 @@
         }
 
         int step() {
-            // random-walk around key positions,  bunching accesses
+            // random-walk around key positions, bunching accesses
             int r = rng.next();
             position += (r & 7) - 3;
             while (position >= key.length) position -= key.length;
@@ -156,7 +156,7 @@
                     throw new Error("bad mapping: " + x + " to " + k);
 
                 if (r < removesPerMaxRandom) {
-                    // get awy from this position
+                    // get away from this position
                     position = r % key.length;
                     map.remove(k);
                     return 2;
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -35,13 +35,11 @@
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
 
-
 /**
  * This is an incomplete implementation of a wrapper class
  * that places read-write locks around unsynchronized Maps.
  * Exists as a sample input for MapLoops test.
  */
-
 public class RWMap implements Map {
     private final Map m;
     private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
@@ -86,7 +84,6 @@
         finally { rwl.readLock().unlock(); }
     }
 
-
     public Set keySet() { // Not implemented
         return null;
     }
--- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java	Wed Jul 05 20:54:58 2017 +0200
@@ -78,7 +78,7 @@
     abstract static class Locker extends Thread {
         static AtomicInteger count = new AtomicInteger(1);
         private volatile Throwable thrown;
-        private volatile long stamp;;
+        private volatile long stamp;
         protected void thrown(Throwable thrown) { this.thrown = thrown; }
         public Throwable thrown() { return thrown; }
         protected void stamp(long stamp) { this.stamp = stamp; }
@@ -371,7 +371,7 @@
                 check(!sl.tryUnlockRead());
                 check(!sl.tryUnlockWrite());
                 check(sl.tryOptimisticRead() != 0L);
-                Locker[] wThreads = new Locker[100];;
+                Locker[] wThreads = new Locker[100];
                 for (int j=0; j<100; j++)
                     wThreads[j] = writers.next();
                 for (int j=0; j<100; j++)
@@ -401,7 +401,7 @@
                 check(!sl.tryUnlockRead());
                 check(!sl.tryUnlockWrite());
                 check(sl.tryOptimisticRead() != 0L);
-                Locker[] rThreads = new Locker[100];;
+                Locker[] rThreads = new Locker[100];
                 for (int j=0; j<100; j++)
                     rThreads[j] = readers.next();
                 for (int j=0; j<100; j++)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/HandlersOnComplexResetUpdate.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) 2015, 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.logging.FileHandler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+
+/**
+ * @test
+ * @bug 8033661
+ * @summary tests that FileHandlers configured on abstract nodes in logging.properties
+ *          will be closed on reset and reopened on updateConfiguration().
+ *          Test a complex reconfiguration where a logger with handlers
+ *          suddenly appears in the hierarchy between a child logger and the
+ *          root logger.
+ * @run main/othervm HandlersOnComplexResetUpdate UNSECURE
+ * @run main/othervm HandlersOnComplexResetUpdate SECURE
+ * @author danielfuchs
+ */
+public class HandlersOnComplexResetUpdate {
+
+    /**
+     * We will test the handling of abstract logger nodes with file handlers in
+     * two configurations:
+     * UNSECURE: No security manager.
+     * SECURE: With the security manager present - and the required
+     *         permissions granted.
+     */
+    public static enum TestCase {
+        UNSECURE, SECURE;
+        public void run(List<Properties> properties) throws Exception {
+            System.out.println("Running test case: " + name());
+            Configure.setUp(this, properties.get(0));
+            test(this.name(), properties);
+        }
+    }
+
+
+    private static final String PREFIX =
+            "FileHandler-" + UUID.randomUUID() + ".log";
+    private static final String userDir = System.getProperty("user.dir", ".");
+    private static final boolean userDirWritable = Files.isWritable(Paths.get(userDir));
+
+    private static final List<Properties> properties;
+    static {
+        // The test will call reset() and updateConfiguration() with each of these
+        // properties in sequence. The child logger is not released between each
+        // configuration. What is interesting here is mostly what happens between
+        // props4 and props5:
+        //
+        // In step 4 (props4) the configuration defines a handler for the
+        // logger com.foo (the direct parent of com.foo.child - which is the
+        // logger we hold on to).
+        //
+        // In step 5 (props5) the configuration has nothing concerning
+        // 'com.foo', but the handler has been migrated to 'com'.
+        // Since there doesn't exist any logger for 'com' (the previous
+        // configuration didn't have any configuration for 'com'), then
+        // 'com' will not be found when we process the existing loggers named
+        // in the configuration.
+        //
+        // So if we didn't also process the existing loggers not named in the
+        // configuration (such as com.foo.child) then no logger for 'com'
+        // would be created, which means that com.foo.child would not be
+        // able to inherit its configuration for 'com' until someone explicitely
+        // creates a logger for 'com'.
+        //
+        // This test check that a logger for 'com' will be created because
+        // 'com.foo.child' still exists when updateConfiguration() is called.
+
+        Properties props1 = new Properties();
+        props1.setProperty("test.name", "parent logger with handler");
+        props1.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props1.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props1.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props1.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props1.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props1.setProperty("test.checkHandlersOnParent", "true");
+        props1.setProperty("test.checkHandlersOn", "com.foo");
+        props1.setProperty("com.bar.level", "FINEST");
+
+        Properties props2 = new Properties();
+        props2.setProperty("java.util.logging.LogManager.reconfigureHandlers", "true");
+        props2.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props2.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props2.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props2.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props2.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props2.setProperty("test.checkHandlersOnParent", "true");
+        props2.setProperty("test.checkHandlersOn", "com.foo");
+        props2.setProperty("com.bar.level", "FINEST");
+
+        Properties props3 = new Properties();
+        props3.setProperty("test.name", "parent logger with handler");
+        props3.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props3.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props3.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props3.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props3.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props3.setProperty("test.checkHandlersOnParent", "true");
+        props3.setProperty("test.checkHandlersOn", "com.foo");
+        props3.setProperty("com.bar.level", "FINEST");
+
+        Properties props4 = new Properties();
+        props4.setProperty("java.util.logging.LogManager.reconfigureHandlers", "true");
+        props4.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props4.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props4.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props4.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props4.setProperty("test.checkHandlersOnParent", "true");
+        props4.setProperty("test.checkHandlersOn", "com.foo");
+        props4.setProperty("com.foo.handlers", FileHandler.class.getName());
+
+        Properties props5 = new Properties();
+        props5.setProperty("test.name", "parent logger with handler");
+        props5.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props5.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props5.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props5.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props5.setProperty("test.checkHandlersOnParent", "false");
+        props5.setProperty("test.checkHandlersOn", "com");
+        props5.setProperty("com.handlers", FileHandler.class.getName());
+
+        properties = Collections.unmodifiableList(Arrays.asList(
+                    props1, props2, props3, props4, props5));
+    }
+
+    /**
+     * This is the main test method. The rest is infrastructure.
+     * Creates a child of the 'com.foo' logger (com.foo.child) and holds on to
+     * it.
+     * <p>
+     * Then applies all given configurations in sequence and verifies assumptions
+     * about the handlers that com.foo should have, or not have.
+     * In the last configuration (props5) it also verifies that the
+     * logger 'com' has been created and has now the expected handler.
+     * <p>
+     * Finally releases the child logger after all configurations have been
+     * applied.
+     *
+     * @param name
+     * @param properties
+     * @throws Exception
+     */
+    static void test(String name, List<Properties> properties)
+            throws Exception {
+
+        System.out.println("\nTesting: " + name);
+        if (!userDirWritable) {
+            throw new RuntimeException("Not writable: "+userDir);
+        }
+
+        // Then create a child of the com.foo logger.
+        Logger fooChild = Logger.getLogger("com.foo.child");
+        fooChild.info("hello world");
+        Logger barChild = Logger.getLogger("com.bar.child");
+        barChild.info("hello world");
+
+        ReferenceQueue<Logger> queue = new ReferenceQueue();
+        WeakReference<Logger> fooRef = new WeakReference<>(Logger.getLogger("com.foo"), queue);
+        if (fooRef.get() != fooChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + fooChild.getParent() +"\n\texpected: " + fooRef.get());
+        }
+        WeakReference<Logger> barRef = new WeakReference<>(Logger.getLogger("com.bar"), queue);
+        if (barRef.get() != barChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + barChild.getParent() +"\n\texpected: " + barRef.get());
+        }
+        Reference<? extends Logger> ref2;
+        int max = 3;
+        barChild = null;
+        while ((ref2 = queue.poll()) == null) {
+            System.gc();
+            Thread.sleep(100);
+            if (--max == 0) break;
+        }
+
+        Throwable failed = null;
+        try {
+            if (ref2 != null) {
+                String refName = ref2 == fooRef ? "fooRef" : ref2 == barRef ? "barRef" : "unknown";
+                if (ref2 != barRef) {
+                    throw new RuntimeException("Unexpected logger reference cleared: " + refName);
+                } else {
+                    System.out.println("Reference " + refName + " cleared as expected");
+                }
+            } else if (ref2 == null) {
+                throw new RuntimeException("Expected 'barRef' to be cleared");
+            }
+            // Now lets try to reset, check that ref2 has no handlers, and
+            // attempt to configure again.
+            Properties previousProps  = properties.get(0);
+            int expectedHandlersCount = 1;
+            boolean checkHandlersOnParent = Boolean.parseBoolean(
+                    previousProps.getProperty("test.checkHandlersOnParent", "true"));
+            String checkHandlersOn = previousProps.getProperty("test.checkHandlersOn", null);
+            for (int i=1; i<properties.size(); i++) {
+                System.out.println("\n*** Reconfiguration with properties["+i+"]\n");
+                Properties nextProps = properties.get(i);
+                boolean reconfigureHandlers = true;
+
+                if (checkHandlersOnParent) {
+                    assertEquals(expectedHandlersCount,
+                            fooChild.getParent().getHandlers().length,
+                            "fooChild.getParent().getHandlers().length");
+                }
+                if (checkHandlersOn != null) {
+                    Logger loggerWithHandlers = LogManager.getLogManager().getLogger(checkHandlersOn);
+                    if (loggerWithHandlers == null) {
+                        throw new RuntimeException("Logger with handlers not found: " + checkHandlersOn);
+                    }
+                    assertEquals(expectedHandlersCount,
+                            loggerWithHandlers.getHandlers().length,
+                            checkHandlersOn + ".getHandlers().length");
+                }
+
+                // Reset
+                Configure.doPrivileged(() -> LogManager.getLogManager().reset());
+                assertEquals(0, fooChild.getParent().getHandlers().length, "fooChild.getParent().getHandlers().length");
+                if (checkHandlersOn != null) {
+                    Logger loggerWithHandlers = LogManager.getLogManager().getLogger(checkHandlersOn);
+                    if (loggerWithHandlers == null) {
+                        throw new RuntimeException("Logger with handlers not found: " + checkHandlersOn);
+                    }
+                    assertEquals(0, loggerWithHandlers.getHandlers().length,
+                            checkHandlersOn + ".getHandlers().length");
+                }
+
+                if (i == 4) {
+                    System.out.println("Last configuration...");
+                }
+                // Read configuration
+                Configure.doPrivileged(() -> Configure.updateConfigurationWith(nextProps, false));
+
+                expectedHandlersCount = reconfigureHandlers ? 1 : 0;
+                checkHandlersOnParent = Boolean.parseBoolean(
+                    nextProps.getProperty("test.checkHandlersOnParent", "true"));
+                checkHandlersOn = nextProps.getProperty("test.checkHandlersOn", null);
+
+                if (checkHandlersOnParent) {
+                    assertEquals(expectedHandlersCount,
+                        fooChild.getParent().getHandlers().length,
+                        "fooChild.getParent().getHandlers().length");
+                } else {
+                    assertEquals(0,
+                        fooChild.getParent().getHandlers().length,
+                        "fooChild.getParent().getHandlers().length");
+                }
+                if (checkHandlersOn != null) {
+                    Logger loggerWithHandlers = LogManager.getLogManager().getLogger(checkHandlersOn);
+                    if (loggerWithHandlers == null) {
+                        throw new RuntimeException("Logger with handlers not found: " + checkHandlersOn);
+                    }
+                    assertEquals(expectedHandlersCount,
+                            loggerWithHandlers.getHandlers().length,
+                            checkHandlersOn + ".getHandlers().length");
+                }
+            }
+        } catch (Throwable t) {
+            failed = t;
+        } finally {
+            final Throwable suppressed = failed;
+            Configure.doPrivileged(() -> LogManager.getLogManager().reset());
+            Configure.doPrivileged(() -> {
+                try {
+                    StringBuilder builder = new StringBuilder();
+                    Files.list(Paths.get(userDir))
+                        .filter((f) -> f.toString().contains(PREFIX))
+                        .filter((f) -> f.toString().endsWith(".lck"))
+                        .forEach((f) -> {
+                                builder.append(f.toString()).append('\n');
+                        });
+                    if (!builder.toString().isEmpty()) {
+                        throw new RuntimeException("Lock files not cleaned:\n"
+                                + builder.toString());
+                    }
+                } catch(RuntimeException | Error x) {
+                    if (suppressed != null) x.addSuppressed(suppressed);
+                    throw x;
+                } catch(Exception x) {
+                    if (suppressed != null) x.addSuppressed(suppressed);
+                    throw new RuntimeException(x);
+                }
+            });
+            fooChild = null;
+            System.out.println("Setting fooChild to: " + fooChild);
+            while ((ref2 = queue.poll()) == null) {
+                System.gc();
+                Thread.sleep(1000);
+            }
+            if (ref2 != fooRef) {
+                throw new RuntimeException("Unexpected reference: "
+                        + ref2 +"\n\texpected: " + fooRef);
+            }
+            if (ref2.get() != null) {
+                throw new RuntimeException("Referent not cleared: " + ref2.get());
+            }
+            System.out.println("Got fooRef after reset(), fooChild is " + fooChild);
+
+        }
+        if (failed != null) {
+            // should rarely happen...
+            throw new RuntimeException(failed);
+        }
+
+    }
+
+    public static void main(String... args) throws Exception {
+
+
+        if (args == null || args.length == 0) {
+            args = new String[] {
+                TestCase.UNSECURE.name(),
+                TestCase.SECURE.name(),
+            };
+        }
+
+        try {
+            for (String testName : args) {
+                TestCase test = TestCase.valueOf(testName);
+                test.run(properties);
+            }
+        } finally {
+            if (userDirWritable) {
+                Configure.doPrivileged(() -> {
+                    // cleanup - delete files that have been created
+                    try {
+                        Files.list(Paths.get(userDir))
+                            .filter((f) -> f.toString().contains(PREFIX))
+                            .forEach((f) -> {
+                                try {
+                                    System.out.println("deleting " + f);
+                                    Files.delete(f);
+                                } catch(Throwable t) {
+                                    System.err.println("Failed to delete " + f + ": " + t);
+                                }
+                            });
+                    } catch(Throwable t) {
+                        System.err.println("Cleanup failed to list files: " + t);
+                        t.printStackTrace();
+                    }
+                });
+            }
+        }
+    }
+
+    static class Configure {
+        static Policy policy = null;
+        static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return  new AtomicBoolean(false);
+            }
+        };
+        static void setUp(TestCase test, Properties propertyFile) {
+            switch (test) {
+                case SECURE:
+                    if (policy == null && System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    } else if (policy == null) {
+                        policy = new SimplePolicy(TestCase.SECURE, allowAll);
+                        Policy.setPolicy(policy);
+                        System.setSecurityManager(new SecurityManager());
+                    }
+                    if (System.getSecurityManager() == null) {
+                        throw new IllegalStateException("No SecurityManager.");
+                    }
+                    if (policy == null) {
+                        throw new IllegalStateException("policy not configured");
+                    }
+                    break;
+                case UNSECURE:
+                    if (System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    }
+                    break;
+                default:
+                    new InternalError("No such testcase: " + test);
+            }
+            doPrivileged(() -> {
+                updateConfigurationWith(propertyFile, false);
+            });
+        }
+
+        static void updateConfigurationWith(Properties propertyFile, boolean append) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                Function<String, BiFunction<String,String,String>> remapper =
+                        append ? (x) -> ((o, n) -> n == null ? o : n)
+                               : (x) -> ((o, n) -> n);
+                LogManager.getLogManager().updateConfiguration(bais, remapper);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void doPrivileged(Runnable run) {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                run.run();
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+        static <T> T callPrivileged(Callable<T> call) throws Exception {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                return call.call();
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+    }
+
+    @FunctionalInterface
+    public static interface FileHandlerSupplier {
+        public FileHandler test() throws Exception;
+    }
+
+    static final class TestAssertException extends RuntimeException {
+        TestAssertException(String msg) {
+            super(msg);
+        }
+    }
+
+    private static void assertEquals(long expected, long received, String msg) {
+        if (expected != received) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    final static class PermissionsBuilder {
+        final Permissions perms;
+        public PermissionsBuilder() {
+            this(new Permissions());
+        }
+        public PermissionsBuilder(Permissions perms) {
+            this.perms = perms;
+        }
+        public PermissionsBuilder add(Permission p) {
+            perms.add(p);
+            return this;
+        }
+        public PermissionsBuilder addAll(PermissionCollection col) {
+            if (col != null) {
+                for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+                    perms.add(e.nextElement());
+                }
+            }
+            return this;
+        }
+        public Permissions toPermissions() {
+            final PermissionsBuilder builder = new PermissionsBuilder();
+            builder.addAll(perms);
+            return builder.perms;
+        }
+    }
+
+    public static class SimplePolicy extends Policy {
+
+        final Permissions permissions;
+        final Permissions allPermissions;
+        final ThreadLocal<AtomicBoolean> allowAll; // actually: this should be in a thread locale
+        public SimplePolicy(TestCase test, ThreadLocal<AtomicBoolean> allowAll) {
+            this.allowAll = allowAll;
+            permissions = new Permissions();
+            permissions.add(new LoggingPermission("control", null));
+            permissions.add(new FilePermission(PREFIX+".lck", "read,write,delete"));
+            permissions.add(new FilePermission(PREFIX, "read,write"));
+
+            // these are used for configuring the test itself...
+            allPermissions = new Permissions();
+            allPermissions.add(new java.security.AllPermission());
+
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain domain, Permission permission) {
+            if (allowAll.get().get()) return allPermissions.implies(permission);
+            return permissions.implies(permission);
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/HandlersOnComplexUpdate.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2015, 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.logging.FileHandler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+
+/**
+ * @test
+ * @bug 8033661
+ * @summary tests that FileHandlers configured on abstract nodes in logging.properties
+ *          will be properly closed and reopened on updateConfiguration().
+ *          Test a complex reconfiguration where a logger with handlers
+ *          suddenly appears in the hierarchy between a child logger and the
+ *          root logger.
+ * @run main/othervm HandlersOnComplexUpdate UNSECURE
+ * @run main/othervm HandlersOnComplexUpdate SECURE
+ * @author danielfuchs
+ */
+public class HandlersOnComplexUpdate {
+
+    /**
+     * We will test the handling of abstract logger nodes with file handlers in
+     * two configurations:
+     * UNSECURE: No security manager.
+     * SECURE: With the security manager present - and the required
+     *         permissions granted.
+     */
+    public static enum TestCase {
+        UNSECURE, SECURE;
+        public void run(List<Properties> properties) throws Exception {
+            System.out.println("Running test case: " + name());
+            Configure.setUp(this, properties.get(0));
+            test(this.name(), properties);
+        }
+    }
+
+
+    private static final String PREFIX =
+            "FileHandler-" + UUID.randomUUID() + ".log";
+    private static final String userDir = System.getProperty("user.dir", ".");
+    private static final boolean userDirWritable = Files.isWritable(Paths.get(userDir));
+
+    private static final List<Properties> properties;
+    static {
+        // The test will call updateConfiguration() with each of these
+        // properties in sequence. The child logger is not released between each
+        // configuration. What is interesting here is mostly what happens between
+        // props4 and props5:
+        //
+        // In step 4 (props4) the configuration defines a handler for the
+        // logger com.foo (the direct parent of com.foo.child - which is the
+        // logger we hold on to).
+        //
+        // In step 5 (props5) the configuration has nothing concerning
+        // 'com.foo', but the handler has been migrated to 'com'.
+        // Since there doesn't exist any logger for 'com' (the previous
+        // configuration didn't have any configuration for 'com'), then
+        // 'com' will not be found when we process the existing loggers named
+        // in the configuration.
+        //
+        // So if we didn't also process the existing loggers not named in the
+        // configuration (such as com.foo.child) then no logger for 'com'
+        // would be created, which means that com.foo.child would not be
+        // able to inherit its configuration for 'com' until someone explicitely
+        // creates a logger for 'com'.
+        //
+        // This test check that a logger for 'com' will be created because
+        // 'com.foo.child' still exists when updateConfiguration() is called.
+
+        Properties props1 = new Properties();
+        props1.setProperty("test.name", "parent logger with handler");
+        props1.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props1.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props1.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props1.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props1.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props1.setProperty("test.checkHandlersOnParent", "true");
+        props1.setProperty("test.checkHandlersOn", "com.foo");
+        props1.setProperty("com.bar.level", "FINEST");
+
+        Properties props2 = new Properties();
+        props2.setProperty("test.name", "parent logger with handler");
+        props2.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props2.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props2.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props2.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props2.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props2.setProperty("test.checkHandlersOnParent", "true");
+        props2.setProperty("test.checkHandlersOn", "com.foo");
+        props2.setProperty("com.bar.level", "FINEST");
+
+        Properties props3 = new Properties();
+        props3.setProperty("test.name", "parent logger with handler");
+        props3.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props3.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props3.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props3.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props3.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props3.setProperty("test.checkHandlersOnParent", "true");
+        props3.setProperty("test.checkHandlersOn", "com.foo");
+        props3.setProperty("com.bar.level", "FINEST");
+
+        Properties props4 = new Properties();
+        props4.setProperty("test.name", "parent logger with handler");
+        props4.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props4.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props4.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props4.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props4.setProperty("test.checkHandlersOnParent", "true");
+        props4.setProperty("test.checkHandlersOn", "com.foo");
+        props4.setProperty("com.foo.handlers", FileHandler.class.getName());
+
+        Properties props5 = new Properties();
+        props5.setProperty("test.name", "parent logger with handler");
+        props5.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props5.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props5.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props5.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props5.setProperty("test.checkHandlersOnParent", "false");
+        props5.setProperty("test.checkHandlersOn", "com");
+        props5.setProperty("com.handlers", FileHandler.class.getName());
+
+        properties = Collections.unmodifiableList(Arrays.asList(
+                    props1, props2, props3, props4, props5));
+    }
+
+    /**
+     * This is the main test method. The rest is infrastructure.
+     * Creates a child of the 'com.foo' logger (com.foo.child) and holds on to
+     * it.
+     * <p>
+     * Then applies all given configurations in sequence and verifies assumptions
+     * about the handlers that com.foo should have, or not have.
+     * In the last configuration (props5) it also verifies that the
+     * logger 'com' has been created and has now the expected handler.
+     * <p>
+     * Finally releases the child logger after all configurations have been
+     * applied.
+     *
+     * @param name
+     * @param properties
+     * @throws Exception
+     */
+    static void test(String name, List<Properties> properties)
+            throws Exception {
+
+        System.out.println("\nTesting: " + name);
+        if (!userDirWritable) {
+            throw new RuntimeException("Not writable: "+userDir);
+        }
+
+        // Then create a child of the com.foo logger.
+        Logger fooChild = Logger.getLogger("com.foo.child");
+        fooChild.info("hello world");
+        Logger barChild = Logger.getLogger("com.bar.child");
+        barChild.info("hello world");
+
+        ReferenceQueue<Logger> queue = new ReferenceQueue();
+        WeakReference<Logger> fooRef = new WeakReference<>(Logger.getLogger("com.foo"), queue);
+        if (fooRef.get() != fooChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + fooChild.getParent() +"\n\texpected: " + fooRef.get());
+        }
+        WeakReference<Logger> barRef = new WeakReference<>(Logger.getLogger("com.bar"), queue);
+        if (barRef.get() != barChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + barChild.getParent() +"\n\texpected: " + barRef.get());
+        }
+        Reference<? extends Logger> ref2;
+        int max = 3;
+        barChild = null;
+        while ((ref2 = queue.poll()) == null) {
+            System.gc();
+            Thread.sleep(100);
+            if (--max == 0) break;
+        }
+
+        Throwable failed = null;
+        try {
+            if (ref2 != null) {
+                String refName = ref2 == fooRef ? "fooRef" : ref2 == barRef ? "barRef" : "unknown";
+                if (ref2 != barRef) {
+                    throw new RuntimeException("Unexpected logger reference cleared: " + refName);
+                } else {
+                    System.out.println("Reference " + refName + " cleared as expected");
+                }
+            } else if (ref2 == null) {
+                throw new RuntimeException("Expected 'barRef' to be cleared");
+            }
+            // Now lets try to check handlers, and
+            // attempt to update the configuration again.
+            Properties previousProps  = properties.get(0);
+            int expectedHandlersCount = 1;
+            boolean checkHandlersOnParent = Boolean.parseBoolean(
+                    previousProps.getProperty("test.checkHandlersOnParent", "true"));
+            String checkHandlersOn = previousProps.getProperty("test.checkHandlersOn", null);
+            for (int i=1; i<properties.size(); i++) {
+                System.out.println("\n*** Reconfiguration with properties["+i+"]\n");
+                Properties nextProps = properties.get(i);
+                boolean reconfigureHandlers = true;
+
+                if (checkHandlersOnParent) {
+                    assertEquals(expectedHandlersCount,
+                            fooChild.getParent().getHandlers().length,
+                            "fooChild.getParent().getHandlers().length");
+                }
+                if (checkHandlersOn != null) {
+                    Logger loggerWithHandlers = LogManager.getLogManager().getLogger(checkHandlersOn);
+                    if (loggerWithHandlers == null) {
+                        throw new RuntimeException("Logger with handlers not found: " + checkHandlersOn);
+                    }
+                    assertEquals(expectedHandlersCount,
+                            loggerWithHandlers.getHandlers().length,
+                            checkHandlersOn + ".getHandlers().length");
+                }
+
+                if (i == 4) {
+                    System.out.println("Last configuration...");
+                }
+                // Read configuration
+                Configure.doPrivileged(() -> Configure.updateConfigurationWith(nextProps, false));
+
+                expectedHandlersCount = reconfigureHandlers ? 1 : 0;
+                checkHandlersOnParent = Boolean.parseBoolean(
+                    nextProps.getProperty("test.checkHandlersOnParent", "true"));
+                checkHandlersOn = nextProps.getProperty("test.checkHandlersOn", null);
+
+                if (checkHandlersOnParent) {
+                    assertEquals(expectedHandlersCount,
+                        fooChild.getParent().getHandlers().length,
+                        "fooChild.getParent().getHandlers().length");
+                } else {
+                    assertEquals(0,
+                        fooChild.getParent().getHandlers().length,
+                        "fooChild.getParent().getHandlers().length");
+                }
+                if (checkHandlersOn != null) {
+                    Logger loggerWithHandlers = LogManager.getLogManager().getLogger(checkHandlersOn);
+                    if (loggerWithHandlers == null) {
+                        throw new RuntimeException("Logger with handlers not found: " + checkHandlersOn);
+                    }
+                    assertEquals(expectedHandlersCount,
+                            loggerWithHandlers.getHandlers().length,
+                            checkHandlersOn + ".getHandlers().length");
+                }
+            }
+        } catch (Throwable t) {
+            failed = t;
+        } finally {
+            final Throwable suppressed = failed;
+            Configure.doPrivileged(() -> LogManager.getLogManager().reset());
+            Configure.doPrivileged(() -> {
+                try {
+                    StringBuilder builder = new StringBuilder();
+                    Files.list(Paths.get(userDir))
+                        .filter((f) -> f.toString().contains(PREFIX))
+                        .filter((f) -> f.toString().endsWith(".lck"))
+                        .forEach((f) -> {
+                                builder.append(f.toString()).append('\n');
+                        });
+                    if (!builder.toString().isEmpty()) {
+                        throw new RuntimeException("Lock files not cleaned:\n"
+                                + builder.toString());
+                    }
+                } catch(RuntimeException | Error x) {
+                    if (suppressed != null) x.addSuppressed(suppressed);
+                    throw x;
+                } catch(Exception x) {
+                    if (suppressed != null) x.addSuppressed(suppressed);
+                    throw new RuntimeException(x);
+                }
+            });
+            fooChild = null;
+            System.out.println("Setting fooChild to: " + fooChild);
+            while ((ref2 = queue.poll()) == null) {
+                System.gc();
+                Thread.sleep(1000);
+            }
+            if (ref2 != fooRef) {
+                throw new RuntimeException("Unexpected reference: "
+                        + ref2 +"\n\texpected: " + fooRef);
+            }
+            if (ref2.get() != null) {
+                throw new RuntimeException("Referent not cleared: " + ref2.get());
+            }
+            System.out.println("Got fooRef after reset(), fooChild is " + fooChild);
+
+        }
+        if (failed != null) {
+            // should rarely happen...
+            throw new RuntimeException(failed);
+        }
+
+    }
+
+    public static void main(String... args) throws Exception {
+
+
+        if (args == null || args.length == 0) {
+            args = new String[] {
+                TestCase.UNSECURE.name(),
+                TestCase.SECURE.name(),
+            };
+        }
+
+        try {
+            for (String testName : args) {
+                TestCase test = TestCase.valueOf(testName);
+                test.run(properties);
+            }
+        } finally {
+            if (userDirWritable) {
+                Configure.doPrivileged(() -> {
+                    // cleanup - delete files that have been created
+                    try {
+                        Files.list(Paths.get(userDir))
+                            .filter((f) -> f.toString().contains(PREFIX))
+                            .forEach((f) -> {
+                                try {
+                                    System.out.println("deleting " + f);
+                                    Files.delete(f);
+                                } catch(Throwable t) {
+                                    System.err.println("Failed to delete " + f + ": " + t);
+                                }
+                            });
+                    } catch(Throwable t) {
+                        System.err.println("Cleanup failed to list files: " + t);
+                        t.printStackTrace();
+                    }
+                });
+            }
+        }
+    }
+
+    static class Configure {
+        static Policy policy = null;
+        static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return  new AtomicBoolean(false);
+            }
+        };
+        static void setUp(TestCase test, Properties propertyFile) {
+            switch (test) {
+                case SECURE:
+                    if (policy == null && System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    } else if (policy == null) {
+                        policy = new SimplePolicy(TestCase.SECURE, allowAll);
+                        Policy.setPolicy(policy);
+                        System.setSecurityManager(new SecurityManager());
+                    }
+                    if (System.getSecurityManager() == null) {
+                        throw new IllegalStateException("No SecurityManager.");
+                    }
+                    if (policy == null) {
+                        throw new IllegalStateException("policy not configured");
+                    }
+                    break;
+                case UNSECURE:
+                    if (System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    }
+                    break;
+                default:
+                    new InternalError("No such testcase: " + test);
+            }
+            doPrivileged(() -> {
+                configureWith(propertyFile);
+            });
+        }
+
+        static void configureWith(Properties propertyFile) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                LogManager.getLogManager().readConfiguration(bais);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void updateConfigurationWith(Properties propertyFile, boolean append) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                Function<String, BiFunction<String,String,String>> remapper =
+                        append ? (x) -> ((o, n) -> n == null ? o : n)
+                               : (x) -> ((o, n) -> n);
+                LogManager.getLogManager().updateConfiguration(bais, remapper);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void doPrivileged(Runnable run) {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                run.run();
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+        static <T> T callPrivileged(Callable<T> call) throws Exception {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                return call.call();
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+    }
+
+    @FunctionalInterface
+    public static interface FileHandlerSupplier {
+        public FileHandler test() throws Exception;
+    }
+
+    static final class TestAssertException extends RuntimeException {
+        TestAssertException(String msg) {
+            super(msg);
+        }
+    }
+
+    private static void assertEquals(long expected, long received, String msg) {
+        if (expected != received) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    final static class PermissionsBuilder {
+        final Permissions perms;
+        public PermissionsBuilder() {
+            this(new Permissions());
+        }
+        public PermissionsBuilder(Permissions perms) {
+            this.perms = perms;
+        }
+        public PermissionsBuilder add(Permission p) {
+            perms.add(p);
+            return this;
+        }
+        public PermissionsBuilder addAll(PermissionCollection col) {
+            if (col != null) {
+                for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+                    perms.add(e.nextElement());
+                }
+            }
+            return this;
+        }
+        public Permissions toPermissions() {
+            final PermissionsBuilder builder = new PermissionsBuilder();
+            builder.addAll(perms);
+            return builder.perms;
+        }
+    }
+
+    public static class SimplePolicy extends Policy {
+
+        final Permissions permissions;
+        final Permissions allPermissions;
+        final ThreadLocal<AtomicBoolean> allowAll; // actually: this should be in a thread locale
+        public SimplePolicy(TestCase test, ThreadLocal<AtomicBoolean> allowAll) {
+            this.allowAll = allowAll;
+            permissions = new Permissions();
+            permissions.add(new LoggingPermission("control", null));
+            permissions.add(new FilePermission(PREFIX+".lck", "read,write,delete"));
+            permissions.add(new FilePermission(PREFIX, "read,write"));
+
+            // these are used for configuring the test itself...
+            allPermissions = new Permissions();
+            allPermissions.add(new java.security.AllPermission());
+
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain domain, Permission permission) {
+            if (allowAll.get().get()) return allPermissions.implies(permission);
+            return permissions.implies(permission);
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/SimpleUpdateConfigWithInputStreamTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2015, 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+
+/**
+ * @test
+ * @bug 8033661
+ * @summary tests LogManager.updateConfiguration(InputStream, Function) method
+ * @run main/othervm SimpleUpdateConfigWithInputStreamTest UNSECURE
+ * @run main/othervm SimpleUpdateConfigWithInputStreamTest SECURE
+ * @author danielfuchs
+ */
+public class SimpleUpdateConfigWithInputStreamTest {
+
+    /**
+     * We will test updateConfiguration in
+     * two configurations:
+     * UNSECURE: No security manager.
+     * SECURE: With the security manager present - and the required
+     *         permissions granted.
+     */
+    public static enum TestCase {
+        UNSECURE, SECURE;
+        public void execute(Runnable run) {
+            System.out.println("Running test case: " + name());
+            try {
+               Configure.setUp(this);
+               Configure.doPrivileged(run, SimplePolicy.allowControl);
+            } finally {
+               Configure.doPrivileged(() -> {
+                   try {
+                       setSystemProperty("java.util.logging.config.file", null);
+                       LogManager.getLogManager().readConfiguration();
+                       System.gc();
+                   } catch (Exception x) {
+                       throw new RuntimeException(x);
+                   }
+               }, SimplePolicy.allowAll);
+            }
+        }
+    }
+
+    public static class MyHandler extends Handler {
+        static final AtomicLong seq = new AtomicLong();
+        long count = seq.incrementAndGet();
+
+        @Override
+        public void publish(LogRecord record) {
+        }
+
+        @Override
+        public void flush() {
+        }
+
+        @Override
+        public void close() throws SecurityException {
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + "("+count+")";
+        }
+
+    }
+
+    static String storePropertyToFile(String name, Properties props)
+        throws Exception {
+        return Configure.callPrivileged(() -> {
+            String scratch = System.getProperty("user.dir", ".");
+            Path p = Paths.get(scratch, name);
+            try (FileOutputStream fos = new FileOutputStream(p.toFile())) {
+                props.store(fos, name);
+            }
+            return p.toString();
+        }, SimplePolicy.allowAll);
+    }
+
+    static void setSystemProperty(String name, String value)
+        throws Exception {
+        Configure.doPrivileged(() -> {
+            if (value == null)
+                System.clearProperty(name);
+            else
+                System.setProperty(name, value);
+        }, SimplePolicy.allowAll);
+    }
+
+    static String trim(String value) {
+        return value == null ? null : value.trim();
+    }
+
+
+    /**
+     * Tests one of the configuration defined above.
+     * <p>
+     * This is the main test method (the rest is infrastructure).
+     */
+    static void testUpdateConfiguration() {
+        try {
+            // manager initialized with default configuration.
+            LogManager manager = LogManager.getLogManager();
+
+            // Test default configuration. It should not have
+            // any value for "com.foo.level" and "com.foo.handlers"
+            assertEquals(null, manager.getProperty("com.foo.level"),
+                "com.foo.level in default configuration");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in default configuration");
+
+            // Create a logging configuration file that contains
+            // com.foo.level=FINEST
+            // and set "java.util.logging.config.file" to this file.
+            Properties props = new Properties();
+            props.setProperty("com.foo.level", "FINEST");
+
+            // Update configuration with props
+            // then test that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            Configure.updateConfigurationWith(props, null);
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level in " + props);
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // call updateConfiguration with an empty stream.
+            // check that the new configuration no longer has
+            // any value for com.foo.level, and still no value
+            // for com.foo.handlers
+            Configure.updateConfigurationWith(new Properties(), null);
+            assertEquals(null, manager.getProperty("com.foo.level"),
+                    "com.foo.level in default configuration");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in default configuration");
+
+            // creates the com.foo logger, check it has
+            // the default config: no level, and no handlers
+            final Logger logger = Logger.getLogger("com.foo");
+            assertEquals(null, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // call updateConfiguration with 'props'
+            // check that the configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINEST level and still
+            // no handlers
+            Configure.updateConfigurationWith(props, null);
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level in " + props);
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // Calls updateConfiguration with a lambda whose effect should
+            // be to set the FINER level on the "com.foo" logger.
+            // Check that the new configuration has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINER level and still
+            // no handlers
+            Configure.updateConfigurationWith(props,
+                    (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINER level and still
+            // no handlers
+            Configure.updateConfigurationWith(props,
+                    (k) -> ((o, n) -> o));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level preserved by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in props, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger now has FINEST level and still
+            // no handlers
+            Configure.updateConfigurationWith(props,
+                    (k) -> ((o, n) -> n));
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // now set a handler on the com.foo logger.
+            MyHandler h = new MyHandler();
+            logger.addHandler(h);
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect should
+            // be to set the FINER level on the "com.foo" logger, and
+            // take the value from props for everything else.
+            // Check that the new configuration has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINER level, but that its
+            // handlers are still present and have not been reset
+            // since neither the old nor new configuration defined them.
+            Configure.updateConfigurationWith(props,
+                    (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + props);
+
+            // now add some configuration for com.foo.handlers
+            props.setProperty("com.foo.handlers", MyHandler.class.getName());
+
+            // we didn't call updateConfiguration, so just changing the
+            // content of props should have had no effect.
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINER level and still
+            // has its handlers and that they haven't been reset.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in props, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // check that the logger now has FINEST level
+            // and a new handler instance, since the old config
+            // had no handlers for com.foo and the new config has one.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            Handler[] loggerHandlers = logger.getHandlers().clone();
+            assertEquals(1, loggerHandlers.length,
+                    "Logger.getLogger(\"com.foo\").getHandlers().length");
+            assertEquals(MyHandler.class, loggerHandlers[0].getClass(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()[0].getClass()");
+            assertEquals(h.count + 1, ((MyHandler)logger.getHandlers()[0]).count,
+                    "Logger.getLogger(\"com.foo\").getHandlers()[0].count");
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // Because the content of the props hasn't changed, then
+            // it should also be a noop.
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a null lambda, whose effect is to
+            // take all values from the new configuration.
+            // Because the content of the props hasn't changed, then
+            // it should also be a noop.
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // now remove com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // from the configuration file.
+            props.remove("com.foo.handlers");
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in props, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINEST level
+            // and no handlers, since the old config
+            // had an handler for com.foo and the new config doesn't.
+            Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+
+        } catch (RuntimeException | Error r) {
+            throw r;
+        } catch (Exception x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args == null || args.length == 0) {
+            args = new String[] { "UNSECURE", "SECURE" };
+        }
+        for (String test : args) {
+            TestCase.valueOf(test).execute(SimpleUpdateConfigWithInputStreamTest::testUpdateConfiguration);
+        }
+    }
+
+    static class Configure {
+        static Policy policy = null;
+        static void setUp(TestCase test) {
+            switch (test) {
+                case SECURE:
+                    if (policy == null && System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    } else if (policy == null) {
+                        policy = new SimplePolicy(TestCase.SECURE);
+                        Policy.setPolicy(policy);
+                        System.setSecurityManager(new SecurityManager());
+                    }
+                    if (System.getSecurityManager() == null) {
+                        throw new IllegalStateException("No SecurityManager.");
+                    }
+                    if (policy == null) {
+                        throw new IllegalStateException("policy not configured");
+                    }
+                    break;
+                case UNSECURE:
+                    if (System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    }
+                    break;
+                default:
+                    throw new InternalError("No such testcase: " + test);
+            }
+        }
+
+        static void updateConfigurationWith(Properties propertyFile,
+                Function<String,BiFunction<String,String,String>> remapper) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                LogManager.getLogManager().updateConfiguration(bais, remapper);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void doPrivileged(Runnable run, ThreadLocal<AtomicBoolean> granter) {
+            final boolean old = granter.get().getAndSet(true);
+            try {
+                run.run();
+            } finally {
+                granter.get().set(old);
+            }
+        }
+        static <T> T callPrivileged(Callable<T> call,
+                ThreadLocal<AtomicBoolean> granter) throws Exception {
+            final boolean old = granter.get().getAndSet(true);
+            try {
+                return call.call();
+            } finally {
+                granter.get().set(old);
+            }
+        }
+    }
+
+    static final class TestAssertException extends RuntimeException {
+        TestAssertException(String msg) {
+            super(msg);
+        }
+    }
+
+    private static void assertEquals(long expected, long received, String msg) {
+        if (expected != received) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    private static void assertEquals(String expected, String received, String msg) {
+        if (!Objects.equals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    private static void assertEquals(Object expected, Object received, String msg) {
+        if (!Objects.equals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    public static String deepToString(Object o) {
+        if (o == null) {
+            return "null";
+        } else if (o.getClass().isArray()) {
+            String s;
+            if (o instanceof Object[])
+                s = Arrays.deepToString((Object[]) o);
+            else if (o instanceof byte[])
+                s = Arrays.toString((byte[]) o);
+            else if (o instanceof short[])
+                s = Arrays.toString((short[]) o);
+            else if (o instanceof int[])
+                s = Arrays.toString((int[]) o);
+            else if (o instanceof long[])
+                s = Arrays.toString((long[]) o);
+            else if (o instanceof char[])
+                s = Arrays.toString((char[]) o);
+            else if (o instanceof float[])
+                s = Arrays.toString((float[]) o);
+            else if (o instanceof double[])
+                s = Arrays.toString((double[]) o);
+            else if (o instanceof boolean[])
+                s = Arrays.toString((boolean[]) o);
+            else
+                s = o.toString();
+            return s;
+        } else {
+            return o.toString();
+        }
+    }
+
+    private static void assertDeepEquals(Object expected, Object received, String msg) {
+        if (!Objects.deepEquals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + deepToString(expected)
+                    +  "\n\tactual:   " + deepToString(received));
+        } else {
+            System.out.println("Got expected " + msg + ": " + deepToString(received));
+        }
+    }
+
+    final static class PermissionsBuilder {
+        final Permissions perms;
+        public PermissionsBuilder() {
+            this(new Permissions());
+        }
+        public PermissionsBuilder(Permissions perms) {
+            this.perms = perms;
+        }
+        public PermissionsBuilder add(Permission p) {
+            perms.add(p);
+            return this;
+        }
+        public PermissionsBuilder addAll(PermissionCollection col) {
+            if (col != null) {
+                for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+                    perms.add(e.nextElement());
+                }
+            }
+            return this;
+        }
+        public Permissions toPermissions() {
+            final PermissionsBuilder builder = new PermissionsBuilder();
+            builder.addAll(perms);
+            return builder.perms;
+        }
+    }
+
+    public static class SimplePolicy extends Policy {
+
+        final Permissions basic;
+        final Permissions control;
+        final Permissions all;
+        public final static ThreadLocal<AtomicBoolean> allowAll =
+                new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return new AtomicBoolean();
+            }
+        };
+        public final static ThreadLocal<AtomicBoolean> allowControl =
+                new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return new AtomicBoolean();
+            }
+        };
+        public SimplePolicy(TestCase test) {
+            basic = new Permissions();
+            control = new Permissions();
+            control.add(new LoggingPermission("control", null));
+
+            // these are used for configuring the test itself...
+            all = new Permissions();
+            all.add(new java.security.AllPermission());
+
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain domain, Permission permission) {
+            return getPermissions(domain).implies(permission);
+        }
+
+        public PermissionCollection permissions() {
+            PermissionsBuilder builder = new PermissionsBuilder();
+            if (allowAll.get().get()) {
+                builder.addAll(all);
+            } else {
+                builder.addAll(basic);
+                if (allowControl.get().get()) {
+                    builder.addAll(control);
+                }
+            }
+            return builder.toPermissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return permissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return permissions();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/SimpleUpdateConfigurationTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2015, 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.PropertyPermission;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+
+/**
+ * @test
+ * @bug 8033661
+ * @summary tests LogManager.updateConfiguration(Function) method
+ * @run main/othervm SimpleUpdateConfigurationTest UNSECURE
+ * @run main/othervm SimpleUpdateConfigurationTest SECURE
+ * @author danielfuchs
+ */
+public class SimpleUpdateConfigurationTest {
+
+    /**
+     * We will test updateConfiguration in
+     * two configurations:
+     * UNSECURE: No security manager.
+     * SECURE: With the security manager present - and the required
+     *         permissions granted.
+     */
+    public static enum TestCase {
+        UNSECURE, SECURE;
+        public void execute(Runnable run) {
+            System.out.println("Running test case: " + name());
+            try {
+               Configure.setUp(this);
+               Configure.doPrivileged(run, SimplePolicy.allowControl);
+            } finally {
+               Configure.doPrivileged(() -> {
+                   try {
+                       setSystemProperty("java.util.logging.config.file", null);
+                       LogManager.getLogManager().readConfiguration();
+                       System.gc();
+                   } catch (Exception x) {
+                       throw new RuntimeException(x);
+                   }
+               }, SimplePolicy.allowAll);
+            }
+        }
+    }
+
+    public static class MyHandler extends Handler {
+        static final AtomicLong seq = new AtomicLong();
+        long count = seq.incrementAndGet();
+
+        @Override
+        public void publish(LogRecord record) {
+        }
+
+        @Override
+        public void flush() {
+        }
+
+        @Override
+        public void close() throws SecurityException {
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + "("+count+")";
+        }
+
+    }
+
+    static String storePropertyToFile(String name, Properties props)
+        throws Exception {
+        return Configure.callPrivileged(() -> {
+            String scratch = System.getProperty("user.dir", ".");
+            Path p = Paths.get(scratch, name);
+            try (FileOutputStream fos = new FileOutputStream(p.toFile())) {
+                props.store(fos, name);
+            }
+            return p.toString();
+        }, SimplePolicy.allowAll);
+    }
+
+    static void setSystemProperty(String name, String value)
+        throws Exception {
+        Configure.doPrivileged(() -> {
+            if (value == null)
+                System.clearProperty(name);
+            else
+                System.setProperty(name, value);
+        }, SimplePolicy.allowAll);
+    }
+
+    static String trim(String value) {
+        return value == null ? null : value.trim();
+    }
+
+
+    /**
+     * Tests one of the configuration defined above.
+     * <p>
+     * This is the main test method (the rest is infrastructure).
+     */
+    static void testUpdateConfiguration() {
+        String configFile = null;
+        try {
+            // manager initialized with default configuration.
+            LogManager manager = LogManager.getLogManager();
+
+            // Test default configuration. It should not have
+            // any value for "com.foo.level" and "com.foo.handlers"
+            assertEquals(null, manager.getProperty("com.foo.level"),
+                "com.foo.level in default configuration");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in default configuration");
+
+            // Create a logging configuration file that contains
+            // com.foo.level=FINEST
+            // and set "java.util.logging.config.file" to this file.
+            Properties props = new Properties();
+            props.setProperty("com.foo.level", "FINEST");
+            configFile = storePropertyToFile("config1", props);
+            setSystemProperty("java.util.logging.config.file", configFile);
+
+            // Update configuration with configFile
+            // then test that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            manager.updateConfiguration(null);
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level in " + configFile);
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // clear ("java.util.logging.config.file" system property,
+            // and call updateConfiguration again.
+            // check that the new configuration no longer has
+            // any value for com.foo.level, and still no value
+            // for com.foo.handlers
+            setSystemProperty("java.util.logging.config.file", null);
+            manager.updateConfiguration(null);
+            assertEquals(null, manager.getProperty("com.foo.level"),
+                    "com.foo.level in default configuration");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in default configuration");
+
+            // creates the com.foo logger, check it has
+            // the default config: no level, and no handlers
+            final Logger logger = Logger.getLogger("com.foo");
+            assertEquals(null, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // set "java.util.logging.config.file" to configFile and
+            // call updateConfiguration.
+            // check that the configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINEST level and still
+            // no handlers
+            setSystemProperty("java.util.logging.config.file", configFile);
+            manager.updateConfiguration(null);
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level in " + configFile);
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // Calls updateConfiguration with a lambda whose effect should
+            // be to set the FINER level on the "com.foo" logger.
+            // Check that the new configuration has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINER level and still
+            // no handlers
+            manager.updateConfiguration(
+                    (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINER level and still
+            // no handlers
+            manager.updateConfiguration(
+                    (k) -> ((o, n) -> o));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level preserved by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in configFile, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger now has FINEST level and still
+            // no handlers
+            manager.updateConfiguration(
+                    (k) -> ((o, n) -> n));
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // now set a handler on the com.foo logger.
+            MyHandler h = new MyHandler();
+            logger.addHandler(h);
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect should
+            // be to set the FINER level on the "com.foo" logger, and
+            // take the value from configFile for everything else.
+            // Check that the new configuration has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger has now a FINER level, but that its
+            // handlers are still present and have not been reset
+            // since neither the old nor new configuration defined them.
+            manager.updateConfiguration(
+                    (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals(null, manager.getProperty("com.foo.handlers"),
+                "com.foo.handlers in " + configFile);
+
+            // now add some configuration for com.foo.handlers in the
+            // configuration file.
+            props.setProperty("com.foo.handlers", MyHandler.class.getName());
+            storePropertyToFile("config1", props);
+
+            // we didn't call updateConfiguration, so just changing the
+            // content of the file should have had no no effect yet.
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINER
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINER level and still
+            // has its handlers and that they haven't been reset.
+            manager.updateConfiguration((k) -> ((o, n) -> o));
+            assertEquals("FINER", manager.getProperty("com.foo.level"),
+                "com.foo.level set to FINER by updateConfiguration");
+            assertEquals(Level.FINER, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in configFile, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // check that the logger now has FINEST level
+            // and a new handler instance, since the old config
+            // had no handlers for com.foo and the new config has one.
+            manager.updateConfiguration((k) -> ((o, n) -> n));
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+            Handler[] loggerHandlers = logger.getHandlers().clone();
+            assertEquals(1, loggerHandlers.length,
+                    "Logger.getLogger(\"com.foo\").getHandlers().length");
+            assertEquals(MyHandler.class, loggerHandlers[0].getClass(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()[0].getClass()");
+            assertEquals(h.count + 1, ((MyHandler)logger.getHandlers()[0]).count,
+                    "Logger.getLogger(\"com.foo\").getHandlers()[0].count");
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            manager.updateConfiguration((k) -> ((o, n) -> o));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // Because the content of the configFile hasn't changed, then
+            // it should also be a noop.
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            manager.updateConfiguration((k) -> ((o, n) -> n));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a null lambda, whose effect is to
+            // take all values from the new configuration.
+            // Because the content of the configFile hasn't changed, then
+            // it should also be a noop.
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            manager.updateConfiguration((k) -> ((o, n) -> n));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // no remove com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // from the configuration file.
+            props.remove("com.foo.handlers");
+            storePropertyToFile("config1", props);
+
+            // Calls updateConfiguration with a lambda whose effect is a noop.
+            // This should not change the current configuration, so
+            // check that the new configuration still has
+            // com.foo.level=FINEST
+            // com.foo.handlers=SimpleUpdateConfigurationTest$MyHandler
+            // check that the logger still has FINEST level and still
+            // has its handlers and that they haven't been reset.
+            manager.updateConfiguration((k) -> ((o, n) -> o));
+            assertDeepEquals(loggerHandlers, logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(MyHandler.class.getName(),
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+            // Calls updateConfiguration with a lambda whose effect is to
+            // take all values from the new configuration.
+            // This should update the configuration to what is in configFile, so
+            // check that the new configuration has
+            // com.foo.level=FINEST
+            // and nothing for com.foo.handlers
+            // check that the logger still has FINEST level
+            // and no handlers, since the old config
+            // had an handler for com.foo and the new config doesn't.
+            manager.updateConfiguration((k) -> ((o, n) -> n));
+            assertDeepEquals(new Handler[0], logger.getHandlers(),
+                    "Logger.getLogger(\"com.foo\").getHandlers()");
+            assertEquals("FINEST", manager.getProperty("com.foo.level"),
+                "com.foo.level updated by updateConfiguration");
+            assertEquals(Level.FINEST, logger.getLevel(),
+                "Logger.getLogger(\"com.foo\").getLevel()");
+            assertEquals(null,
+                    manager.getProperty("com.foo.handlers"),
+                    "manager.getProperty(\"com.foo.handlers\")");
+
+
+        } catch (RuntimeException | Error r) {
+            throw r;
+        } catch (Exception x) {
+            throw new RuntimeException(x);
+        } finally {
+            if (configFile != null) {
+                // cleanup
+                final String file = configFile;
+                Configure.doPrivileged(() -> {
+                    try {
+                        Files.delete(Paths.get(file));
+                    } catch (RuntimeException | Error r) {
+                        throw r;
+                    } catch (Exception x) {
+                        throw new RuntimeException(x);
+                    }
+                }, SimplePolicy.allowAll);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args == null || args.length == 0) {
+            args = new String[] { "UNSECURE", "SECURE" };
+        }
+        for (String test : args) {
+            TestCase.valueOf(test).execute(SimpleUpdateConfigurationTest::testUpdateConfiguration);
+        }
+    }
+
+    static class Configure {
+        static Policy policy = null;
+        static void setUp(TestCase test) {
+            switch (test) {
+                case SECURE:
+                    if (policy == null && System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    } else if (policy == null) {
+                        policy = new SimplePolicy(TestCase.SECURE);
+                        Policy.setPolicy(policy);
+                        System.setSecurityManager(new SecurityManager());
+                    }
+                    if (System.getSecurityManager() == null) {
+                        throw new IllegalStateException("No SecurityManager.");
+                    }
+                    if (policy == null) {
+                        throw new IllegalStateException("policy not configured");
+                    }
+                    break;
+                case UNSECURE:
+                    if (System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    }
+                    break;
+                default:
+                    throw new InternalError("No such testcase: " + test);
+            }
+        }
+
+        static void updateConfigurationWith(Properties propertyFile,
+                Function<String,BiFunction<String,String,String>> remapper) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                LogManager.getLogManager().updateConfiguration(bais, remapper);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void doPrivileged(Runnable run, ThreadLocal<AtomicBoolean> granter) {
+            final boolean old = granter.get().getAndSet(true);
+            try {
+                run.run();
+            } finally {
+                granter.get().set(old);
+            }
+        }
+        static <T> T callPrivileged(Callable<T> call,
+                ThreadLocal<AtomicBoolean> granter) throws Exception {
+            final boolean old = granter.get().getAndSet(true);
+            try {
+                return call.call();
+            } finally {
+                granter.get().set(old);
+            }
+        }
+    }
+
+    static final class TestAssertException extends RuntimeException {
+        TestAssertException(String msg) {
+            super(msg);
+        }
+    }
+
+    private static void assertEquals(long expected, long received, String msg) {
+        if (expected != received) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    private static void assertEquals(String expected, String received, String msg) {
+        if (!Objects.equals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    private static void assertEquals(Object expected, Object received, String msg) {
+        if (!Objects.equals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    public static String deepToString(Object o) {
+        if (o == null) {
+            return "null";
+        } else if (o.getClass().isArray()) {
+            String s;
+            if (o instanceof Object[])
+                s = Arrays.deepToString((Object[]) o);
+            else if (o instanceof byte[])
+                s = Arrays.toString((byte[]) o);
+            else if (o instanceof short[])
+                s = Arrays.toString((short[]) o);
+            else if (o instanceof int[])
+                s = Arrays.toString((int[]) o);
+            else if (o instanceof long[])
+                s = Arrays.toString((long[]) o);
+            else if (o instanceof char[])
+                s = Arrays.toString((char[]) o);
+            else if (o instanceof float[])
+                s = Arrays.toString((float[]) o);
+            else if (o instanceof double[])
+                s = Arrays.toString((double[]) o);
+            else if (o instanceof boolean[])
+                s = Arrays.toString((boolean[]) o);
+            else
+                s = o.toString();
+            return s;
+        } else {
+            return o.toString();
+        }
+    }
+
+    private static void assertDeepEquals(Object expected, Object received, String msg) {
+        if (!Objects.deepEquals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + deepToString(expected)
+                    +  "\n\tactual:   " + deepToString(received));
+        } else {
+            System.out.println("Got expected " + msg + ": " + deepToString(received));
+        }
+    }
+
+    final static class PermissionsBuilder {
+        final Permissions perms;
+        public PermissionsBuilder() {
+            this(new Permissions());
+        }
+        public PermissionsBuilder(Permissions perms) {
+            this.perms = perms;
+        }
+        public PermissionsBuilder add(Permission p) {
+            perms.add(p);
+            return this;
+        }
+        public PermissionsBuilder addAll(PermissionCollection col) {
+            if (col != null) {
+                for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+                    perms.add(e.nextElement());
+                }
+            }
+            return this;
+        }
+        public Permissions toPermissions() {
+            final PermissionsBuilder builder = new PermissionsBuilder();
+            builder.addAll(perms);
+            return builder.perms;
+        }
+    }
+
+    public static class SimplePolicy extends Policy {
+
+        final Permissions basic;
+        final Permissions control;
+        final Permissions all;
+        public final static ThreadLocal<AtomicBoolean> allowAll =
+                new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return new AtomicBoolean();
+            }
+        };
+        public final static ThreadLocal<AtomicBoolean> allowControl =
+                new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return new AtomicBoolean();
+            }
+        };
+        public SimplePolicy(TestCase test) {
+            basic = new Permissions();
+            control = new Permissions();
+            control.add(new LoggingPermission("control", null));
+
+            // These permissions are required to call updateConfiguration(Function)
+            control.add(new PropertyPermission("java.util.logging.config.file", "read"));
+            control.add(new PropertyPermission("java.home", "read"));
+            control.add(new FilePermission(
+                    Paths.get(System.getProperty("user.dir", "."),"-").toString(), "read"));
+            control.add(new FilePermission(
+                    Paths.get(System.getProperty("java.home"),"conf","-").toString(), "read"));
+
+            // these are used for configuring the test itself...
+            all = new Permissions();
+            all.add(new java.security.AllPermission());
+
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain domain, Permission permission) {
+            return getPermissions(domain).implies(permission);
+        }
+
+        public PermissionCollection permissions() {
+            PermissionsBuilder builder = new PermissionsBuilder();
+            if (allowAll.get().get()) {
+                builder.addAll(all);
+            } else {
+                builder.addAll(basic);
+                if (allowControl.get().get()) {
+                    builder.addAll(control);
+                }
+            }
+            return builder.toPermissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return permissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return permissions();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/UpdateConfigurationTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2015, 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.logging.FileHandler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @test
+ * @bug 8033661
+ * @summary tests LogManager.updateConfiguration(bin)
+ * @run main/othervm UpdateConfigurationTest UNSECURE
+ * @run main/othervm UpdateConfigurationTest SECURE
+ * @author danielfuchs
+ */
+public class UpdateConfigurationTest {
+
+    /**
+     * We will test the handling of abstract logger nodes with file handlers in
+     * two configurations:
+     * UNSECURE: No security manager.
+     * SECURE: With the security manager present - and the required
+     *         permissions granted.
+     */
+    public static enum TestCase {
+        UNSECURE, SECURE;
+        public void run(Properties propertyFile, boolean last) throws Exception {
+            System.out.println("Running test case: " + name());
+            Configure.setUp(this);
+            test(this.name() + " " + propertyFile.getProperty("test.name"),
+                    propertyFile, last);
+        }
+    }
+
+
+    private static final String PREFIX =
+            "FileHandler-" + UUID.randomUUID() + ".log";
+    private static final String userDir = System.getProperty("user.dir", ".");
+    private static final boolean userDirWritable = Files.isWritable(Paths.get(userDir));
+
+    static enum ConfigMode { APPEND, REPLACE, DEFAULT;
+        boolean append() { return this == APPEND; }
+        Function<String, BiFunction<String,String,String>> remapper() {
+            switch(this) {
+                case APPEND:
+                    return (k) -> ((o,n) -> (n == null ? o : n));
+                case REPLACE:
+                    return (k) -> ((o,n) -> n);
+            }
+            return null;
+        }
+    }
+
+    private static final List<Properties> properties;
+    static {
+        // The test will be run with each of the configurations below.
+        // The 'child' logger is forgotten after each test
+
+        Properties props1 = new Properties();
+        props1.setProperty("test.name", "props1");
+        props1.setProperty("test.config.mode", ConfigMode.REPLACE.name());
+        props1.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props1.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props1.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props1.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props1.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props1.setProperty("com.bar.level", "FINEST");
+
+        Properties props2 = new Properties();
+        props2.setProperty("test.name", "props2");
+        props2.setProperty("test.config.mode", ConfigMode.DEFAULT.name());
+        props2.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props2.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props2.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props2.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props2.setProperty("com.foo.handlers", FileHandler.class.getName());
+        props2.setProperty("com.foo.handlers.ensureCloseOnReset", "true");
+        props2.setProperty("com.level", "FINE");
+
+        Properties props3 = new Properties();
+        props3.setProperty("test.name", "props3");
+        props3.setProperty("test.config.mode", ConfigMode.APPEND.name());
+        props3.setProperty(FileHandler.class.getName() + ".pattern", PREFIX);
+        props3.setProperty(FileHandler.class.getName() + ".limit", String.valueOf(Integer.MAX_VALUE));
+        props3.setProperty(FileHandler.class.getName() + ".level", "ALL");
+        props3.setProperty(FileHandler.class.getName() + ".formatter", "java.util.logging.SimpleFormatter");
+        props3.setProperty("com.foo.handlers", ""); // specify "" to override the value in the previous conf
+        props3.setProperty("com.foo.handlers.ensureCloseOnReset", "false");
+        props3.setProperty("com.bar.level", "FINER");
+
+
+        properties = Collections.unmodifiableList(Arrays.asList(
+                    props1, props2, props3, props1));
+    }
+
+    static Properties previous;
+    static Properties current;
+    static final Field propsField;
+    static {
+        LogManager manager = LogManager.getLogManager();
+        try {
+            propsField = LogManager.class.getDeclaredField("props");
+            propsField.setAccessible(true);
+            previous = current = (Properties) propsField.get(manager);
+        } catch (NoSuchFieldException | IllegalAccessException ex) {
+            throw new ExceptionInInitializerError(ex);
+        }
+    }
+
+    static Properties getProperties() {
+        try {
+            return (Properties) propsField.get(LogManager.getLogManager());
+        } catch (IllegalAccessException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    static String trim(String value) {
+        return value == null ? null : value.trim();
+    }
+
+
+    /**
+     * Tests one of the configuration defined above.
+     * <p>
+     * This is the main test method (the rest is infrastructure).
+     * <p>
+     * Creates a child of the com.foo logger (com.foo.child), resets
+     * the configuration, and verifies that com.foo has no handler.
+     * Then reapplies the configuration and verifies that the handler
+     * for com.foo has been reestablished, depending on whether
+     * java.util.logging.LogManager.reconfigureHandlers is present and
+     * true.
+     * <p>
+     * Finally releases the logger com.foo.child, so that com.foo can
+     * be garbage collected, and the next configuration can be
+     * tested.
+     */
+    static void test(ConfigMode mode, String name, Properties props, boolean last)
+            throws Exception {
+
+        // Then create a child of the com.foo logger.
+        Logger fooChild = Logger.getLogger("com.foo.child");
+        fooChild.info("hello world");
+        Logger barChild = Logger.getLogger("com.bar.child");
+        barChild.info("hello world");
+
+        ReferenceQueue<Logger> queue = new ReferenceQueue();
+        WeakReference<Logger> fooRef = new WeakReference<>(Logger.getLogger("com.foo"), queue);
+        if (fooRef.get() != fooChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + fooChild.getParent() +"\n\texpected: " + fooRef.get());
+        }
+        WeakReference<Logger> barRef = new WeakReference<>(Logger.getLogger("com.bar"), queue);
+        if (barRef.get() != barChild.getParent()) {
+            throw new RuntimeException("Unexpected parent logger: "
+                    + barChild.getParent() +"\n\texpected: " + barRef.get());
+        }
+        Reference<? extends Logger> ref2;
+        int max = 3;
+        barChild = null;
+        while ((ref2 = queue.poll()) == null) {
+            System.gc();
+            Thread.sleep(100);
+            if (--max == 0) break;
+        }
+
+        Throwable failed = null;
+        try {
+            if (ref2 != null) {
+                String refName = ref2 == fooRef ? "fooRef" : ref2 == barRef ? "barRef" : "unknown";
+                if (ref2 != barRef) {
+                    throw new RuntimeException("Unexpected logger reference cleared: " + refName);
+                } else {
+                    System.out.println("Reference " + refName + " cleared as expected");
+                }
+            } else if (ref2 == null) {
+                throw new RuntimeException("Expected 'barRef' to be cleared");
+            }
+            // Now lets try to  check that ref2 has expected handlers, and
+            // attempt to configure again.
+            String p = current.getProperty("com.foo.handlers", "").trim();
+            assertEquals(p.isEmpty() ? 0 : 1, fooChild.getParent().getHandlers().length,
+                    "["+name+"] fooChild.getParent().getHandlers().length");
+            Configure.doPrivileged(() -> Configure.updateConfigurationWith(props, mode.remapper()));
+            String p2 = previous.getProperty("com.foo.handlers", "").trim();
+            assertEquals(p, p2, "["+name+"] com.foo.handlers");
+            String n = trim(props.getProperty("com.foo.handlers", null));
+            boolean hasHandlers = mode.append()
+                    ? (n == null ? !p.isEmpty() : !n.isEmpty())
+                    : n != null && !n.isEmpty();
+            assertEquals( hasHandlers ? 1 : 0,
+                    fooChild.getParent().getHandlers().length,
+                    "["+name+"] fooChild.getParent().getHandlers().length"
+                    + "[p=\""+p+"\", n=" + (n==null?null:"\""+n+"\"") + "]");
+
+            checkProperties(mode, previous, current, props);
+
+        } catch (Throwable t) {
+            failed = t;
+        } finally {
+            if (last || failed != null) {
+                final Throwable suppressed = failed;
+                Configure.doPrivileged(LogManager.getLogManager()::reset);
+                Configure.doPrivileged(() -> {
+                    try {
+                        StringBuilder builder = new StringBuilder();
+                        Files.list(Paths.get(userDir))
+                            .filter((f) -> f.toString().contains(PREFIX))
+                            .filter((f) -> f.toString().endsWith(".lck"))
+                            .forEach((f) -> {
+                                    builder.append(f.toString()).append('\n');
+                            });
+                        if (!builder.toString().isEmpty()) {
+                            throw new RuntimeException("Lock files not cleaned:\n"
+                                    + builder.toString());
+                        }
+                    } catch(RuntimeException | Error x) {
+                        if (suppressed != null) x.addSuppressed(suppressed);
+                        throw x;
+                    } catch(Exception x) {
+                        if (suppressed != null) x.addSuppressed(suppressed);
+                        throw new RuntimeException(x);
+                    }
+                });
+
+                // Now we need to forget the child, so that loggers are released,
+                // and so that we can run the test with the next configuration...
+
+                fooChild = null;
+                System.out.println("Setting fooChild to: " + fooChild);
+                while ((ref2 = queue.poll()) == null) {
+                    System.gc();
+                    Thread.sleep(1000);
+                }
+                if (ref2 != fooRef) {
+                    throw new RuntimeException("Unexpected reference: "
+                            + ref2 +"\n\texpected: " + fooRef);
+                }
+                if (ref2.get() != null) {
+                    throw new RuntimeException("Referent not cleared: " + ref2.get());
+                }
+                System.out.println("Got fooRef after reset(), fooChild is " + fooChild);
+
+            }
+        }
+        if (failed != null) {
+            // should rarely happen...
+            throw new RuntimeException(failed);
+        }
+
+    }
+
+    private static void checkProperties(ConfigMode mode,
+            Properties previous, Properties current, Properties props) {
+        Set<String> set = new HashSet<>();
+
+        // Check that all property names from 'props' are in current.
+        set.addAll(props.stringPropertyNames());
+        set.removeAll(current.keySet());
+        if (!set.isEmpty()) {
+            throw new RuntimeException("Missing properties in current: " + set);
+        }
+        set.clear();
+        set.addAll(current.stringPropertyNames());
+        set.removeAll(previous.keySet());
+        set.removeAll(props.keySet());
+        if (!set.isEmpty()) {
+            throw new RuntimeException("Superfluous properties in current: " + set);
+        }
+        set.clear();
+        Stream<String> allnames =
+                Stream.concat(
+                    Stream.concat(previous.stringPropertyNames().stream(),
+                                  props.stringPropertyNames().stream()),
+                    current.stringPropertyNames().stream())
+                        .collect(Collectors.toCollection(TreeSet::new))
+                        .stream();
+        if (mode.append()) {
+            // Check that all previous property names are in current.
+            set.addAll(previous.stringPropertyNames());
+            set.removeAll(current.keySet());
+            if (!set.isEmpty()) {
+                throw new RuntimeException("Missing properties in current: " + set
+                    + "\n\tprevious: " + previous
+                    + "\n\tcurrent:  " + current
+                    + "\n\tprops:    " + props);
+
+            }
+            allnames.forEach((k) -> {
+                    String p = previous.getProperty(k, "").trim();
+                    String n = current.getProperty(k, "").trim();
+                    if (props.containsKey(k)) {
+                        assertEquals(props.getProperty(k), n, k);
+                    } else {
+                        assertEquals(p, n, k);
+                    }
+                });
+        } else {
+            // Check that only properties from 'props' are in current.
+            set.addAll(current.stringPropertyNames());
+            set.removeAll(props.keySet());
+            if (!set.isEmpty()) {
+                throw new RuntimeException("Superfluous properties in current: " + set);
+            }
+            allnames.forEach((k) -> {
+                    String p = previous.getProperty(k, "");
+                    String n = current.getProperty(k, "");
+                    if (props.containsKey(k)) {
+                        assertEquals(props.getProperty(k), n, k);
+                    } else {
+                        assertEquals("", n, k);
+                    }
+                });
+        }
+
+    }
+
+    public static void main(String... args) throws Exception {
+
+
+        if (args == null || args.length == 0) {
+            args = new String[] {
+                TestCase.UNSECURE.name(),
+                TestCase.SECURE.name(),
+            };
+        }
+
+        try {
+            for (String testName : args) {
+                TestCase test = TestCase.valueOf(testName);
+                for (int i=0; i<properties.size();i++) {
+                    Properties propertyFile = properties.get(i);
+                    test.run(propertyFile, i == properties.size() - 1);
+                }
+            }
+        } finally {
+            if (userDirWritable) {
+                Configure.doPrivileged(() -> {
+                    // cleanup - delete files that have been created
+                    try {
+                        Files.list(Paths.get(userDir))
+                            .filter((f) -> f.toString().contains(PREFIX))
+                            .forEach((f) -> {
+                                try {
+                                    System.out.println("deleting " + f);
+                                    Files.delete(f);
+                                } catch(Throwable t) {
+                                    System.err.println("Failed to delete " + f + ": " + t);
+                                }
+                            });
+                    } catch(Throwable t) {
+                        System.err.println("Cleanup failed to list files: " + t);
+                        t.printStackTrace();
+                    }
+                });
+            }
+        }
+    }
+
+    static class Configure {
+        static Policy policy = null;
+        static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
+            @Override
+            protected AtomicBoolean initialValue() {
+                return  new AtomicBoolean(false);
+            }
+        };
+        static void setUp(TestCase test) {
+            switch (test) {
+                case SECURE:
+                    if (policy == null && System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    } else if (policy == null) {
+                        policy = new SimplePolicy(TestCase.SECURE, allowAll);
+                        Policy.setPolicy(policy);
+                        System.setSecurityManager(new SecurityManager());
+                    }
+                    if (System.getSecurityManager() == null) {
+                        throw new IllegalStateException("No SecurityManager.");
+                    }
+                    if (policy == null) {
+                        throw new IllegalStateException("policy not configured");
+                    }
+                    break;
+                case UNSECURE:
+                    if (System.getSecurityManager() != null) {
+                        throw new IllegalStateException("SecurityManager already set");
+                    }
+                    break;
+                default:
+                    new InternalError("No such testcase: " + test);
+            }
+        }
+
+        static void updateConfigurationWith(Properties propertyFile,
+                Function<String,BiFunction<String,String,String>> remapper) {
+            try {
+                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+                propertyFile.store(bytes, propertyFile.getProperty("test.name"));
+                ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
+                LogManager.getLogManager().updateConfiguration(bais, remapper);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        static void doPrivileged(Runnable run) {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                Properties before = getProperties();
+                try {
+                    run.run();
+                } finally {
+                    Properties after = getProperties();
+                    if (before != after) {
+                        previous = before;
+                        current = after;
+                    }
+                }
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+        static <T> T callPrivileged(Callable<T> call) throws Exception {
+            final boolean old = allowAll.get().getAndSet(true);
+            try {
+                Properties before = getProperties();
+                try {
+                    return call.call();
+                } finally {
+                    Properties after = getProperties();
+                    if (before != after) {
+                        previous = before;
+                        current = after;
+                    }
+                }
+            } finally {
+                allowAll.get().set(old);
+            }
+        }
+    }
+
+    @FunctionalInterface
+    public static interface FileHandlerSupplier {
+        public FileHandler test() throws Exception;
+    }
+
+    static final class TestAssertException extends RuntimeException {
+        TestAssertException(String msg) {
+            super(msg);
+        }
+    }
+
+    private static void assertEquals(long expected, long received, String msg) {
+        if (expected != received) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+    private static void assertEquals(String expected, String received, String msg) {
+        if (!Objects.equals(expected, received)) {
+            throw new TestAssertException("Unexpected result for " + msg
+                    + ".\n\texpected: " + expected
+                    +  "\n\tactual:   " + received);
+        } else {
+            System.out.println("Got expected " + msg + ": " + received);
+        }
+    }
+
+
+    public static void test(String name, Properties props, boolean last) throws Exception {
+        ConfigMode configMode = ConfigMode.valueOf(props.getProperty("test.config.mode"));
+        System.out.println("\nTesting: " + name + " mode=" + configMode);
+        if (!userDirWritable) {
+            throw new RuntimeException("Not writable: "+userDir);
+        }
+        switch(configMode) {
+            case REPLACE:
+            case APPEND:
+            case DEFAULT:
+                test(configMode, name, props, last); break;
+            default:
+                throw new RuntimeException("Unknwown mode: " + configMode);
+        }
+    }
+
+    final static class PermissionsBuilder {
+        final Permissions perms;
+        public PermissionsBuilder() {
+            this(new Permissions());
+        }
+        public PermissionsBuilder(Permissions perms) {
+            this.perms = perms;
+        }
+        public PermissionsBuilder add(Permission p) {
+            perms.add(p);
+            return this;
+        }
+        public PermissionsBuilder addAll(PermissionCollection col) {
+            if (col != null) {
+                for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
+                    perms.add(e.nextElement());
+                }
+            }
+            return this;
+        }
+        public Permissions toPermissions() {
+            final PermissionsBuilder builder = new PermissionsBuilder();
+            builder.addAll(perms);
+            return builder.perms;
+        }
+    }
+
+    public static class SimplePolicy extends Policy {
+
+        final Permissions permissions;
+        final Permissions allPermissions;
+        final ThreadLocal<AtomicBoolean> allowAll; // actually: this should be in a thread locale
+        public SimplePolicy(TestCase test, ThreadLocal<AtomicBoolean> allowAll) {
+            this.allowAll = allowAll;
+            permissions = new Permissions();
+            permissions.add(new LoggingPermission("control", null));
+            permissions.add(new FilePermission(PREFIX+".lck", "read,write,delete"));
+            permissions.add(new FilePermission(PREFIX, "read,write"));
+
+            // these are used for configuring the test itself...
+            allPermissions = new Permissions();
+            allPermissions.add(new java.security.AllPermission());
+
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain domain, Permission permission) {
+            if (allowAll.get().get()) return allPermissions.implies(permission);
+            return permissions.implies(permission);
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return new PermissionsBuilder().addAll(allowAll.get().get()
+                    ? allPermissions : permissions).toPermissions();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ZipFile/ZipEntryFreeTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, 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 6907252
+ * @summary ZipFileInputStream Not Thread-Safe
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main ZipEntryFreeTest
+ */
+
+import java.io.*;
+import java.nio.file.Paths;
+import java.util.Random;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.zip.*;
+import jdk.testlibrary.FileUtils;
+
+public class ZipEntryFreeTest extends Thread {
+
+    private static final int NUM_THREADS = 5;
+    private static final int TEST_ITERATIONS = 5;
+    private static final String ZIPFILE_NAME = "large.zip";
+    private static final String ZIPENTRY_NAME = "random.txt";
+    private static InputStream is = null;
+    final Timer timer = new Timer();
+
+    public static void main(String args[]) throws Exception {
+        createZipFile();
+        try {
+            for (int i = 0; i < TEST_ITERATIONS; i++) {
+               runTest();
+            }
+        } finally {
+            FileUtils.deleteFileIfExistsWithRetry(Paths.get(ZIPFILE_NAME));
+        }
+    }
+
+    private static void runTest() throws Exception {
+        try (ZipFile zf = new ZipFile(new File(ZIPFILE_NAME))) {
+            is = zf.getInputStream(zf.getEntry(ZIPENTRY_NAME + "_0"));
+            Thread[] threadArray = new Thread[NUM_THREADS];
+            for (int i = 0; i < threadArray.length; i++) {
+                threadArray[i] = new ZipEntryFreeTest();
+            }
+            for (int i = 0; i < threadArray.length; i++) {
+                threadArray[i].start();
+            }
+            for (int i = 0; i < threadArray.length; i++) {
+                threadArray[i].join();
+            }
+        }
+    }
+
+    private static void createZipFile() throws Exception {
+        Random rnd = new Random(1000L);
+        byte[] contents = new byte[2_000_000];
+        ZipEntry ze = null;
+
+        try (ZipOutputStream zos =
+            new ZipOutputStream(new FileOutputStream(ZIPFILE_NAME))) {
+            // uncompressed mode seemed to tickle the crash
+            zos.setMethod(ZipOutputStream.STORED);
+            for (int ze_count = 0; ze_count < 10; ze_count++) {
+                rnd.nextBytes(contents);
+                ze = createZipEntry(contents, ze_count);
+                zos.putNextEntry(ze);
+                zos.write(contents, 0, contents.length);
+            }
+            zos.flush();
+        }
+    }
+
+    private static ZipEntry createZipEntry(byte[] b, int i) {
+        ZipEntry ze = new ZipEntry(ZIPENTRY_NAME + "_" + i);
+        ze.setCompressedSize(b.length);
+        ze.setSize(b.length);
+        CRC32 crc = new CRC32();
+        crc.update(b);
+        ze.setCrc(crc.getValue());
+        return ze;
+    }
+
+    @Override
+    public void run() {
+        try {
+            int iteration = 0;
+            TimerTask tt = (new TimerTask() {
+                @Override
+                public void run() {
+                    try {
+                        is.close();
+                    } catch (Exception ex) {
+                         ex.printStackTrace(System.out);
+                    }
+                }
+            });
+            timer.schedule(tt, 50);
+            while (is.read() != -1 && iteration++ < 1_000) { }
+        } catch (ZipException ze) {
+            // ZipException now expected instead of ZIP_Read crash
+            System.out.println(ze);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            timer.cancel();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/bind/jxc/8073519/InputWithError.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 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 javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class InputWithError {
+     public int a;
+     int compile-error;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/bind/jxc/8073519/SchemagenErrorReporting.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 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 8073519
+ * @summary test that schemagen tool reports errors during
+ * xsd generation process
+ * @library /lib/testlibrary
+ * @run testng/othervm SchemagenErrorReporting
+ */
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import jdk.testlibrary.JDKToolLauncher;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class SchemagenErrorReporting {
+
+    @Test
+    public void schemagenErrorReporting() throws Exception {
+        //schemagen tool output file name
+        final String SCHEMA_FILE = "schema1.xsd";
+        //Schemagen input java file with not compilable source
+        final String CLASS_FILE = "InputWithError.java";
+        //Test working, src directories and test output file
+        Path testWorkDir, testSrcDir, testOutput;
+
+        //Prepare test environment
+        //Create test directory inside scratch
+        testWorkDir = Paths.get(System.getProperty("user.dir", "."))
+                .resolve("SchemagenErrorReporting");
+        //Get test source directory
+        testSrcDir = Paths.get(System.getProperty("test.src", "."));
+        //Set test output file path
+        testOutput = testWorkDir.resolve("stdErrContent");
+        //Create test directory inside scratch directory
+        Files.createDirectory(testWorkDir);
+        //Copy java source from test.src to the test directory
+        Files.copy(testSrcDir.resolve(CLASS_FILE), testWorkDir.resolve(CLASS_FILE),
+                StandardCopyOption.REPLACE_EXISTING);
+
+        //Prepare process builder to run schemagen tool and save its output
+        JDKToolLauncher sgl = JDKToolLauncher.createUsingTestJDK("schemagen");
+        sgl.addToolArg(CLASS_FILE);
+        System.out.println("Executing: " + Arrays.asList(sgl.getCommand()));
+        ProcessBuilder pb = new ProcessBuilder(sgl.getCommand());
+        //Set schemagen work directory with the input java file
+        pb.directory(testWorkDir.toFile());
+        //Redirect schemagen output to file
+        pb.redirectError(testOutput.toFile());
+        Process p = pb.start();
+        int result = p.waitFor();
+        p.destroy();
+
+        //Read schemagen output from the file
+        String stdErrContent = Files.lines(testOutput)
+                .collect(Collectors.joining(System.lineSeparator(), System.lineSeparator(), ""));
+        System.out.println("Schemagen return value:" + result);
+        System.out.println("Error output:" + stdErrContent);
+        //Check test results:
+        //Schemagen finished with non-0 return value
+        Assert.assertNotEquals(result, 0);
+        //Schemagen output contains compile error message
+        Assert.assertTrue(stdErrContent.contains("InputWithError.java:28: error"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/resources/TimeZone/Bug8139107.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 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 8139107
+ * @summary Test that date parsing with DateTimeFormatter pattern
+ *   that contains timezone field doesn't trigger NPE. All supported
+ *   locales are tested.
+ * @run testng/othervm -Djava.locale.providers=JRE,SPI Bug8139107
+ */
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+import org.testng.annotations.Test;
+
+public class Bug8139107 {
+
+    @Test
+    public void testSupportedLocales() {
+        for (Locale loc:Locale.getAvailableLocales()) {
+            testLocale(loc);
+        }
+    }
+
+    //Test one locale
+    void testLocale(Locale tl) {
+        System.out.println("Locale:" + tl);
+        DateTimeFormatter inputDateTimeFormat = DateTimeFormatter
+                .ofPattern(pattern)
+                .withLocale(tl);
+        System.out.println("Parse result: " + inputDateTimeFormat.parse(inputDate));
+    }
+
+    // Input date time string with short time zone name
+    static final String inputDate = "06-10-2015 18:58:04 MSK";
+    // Pattern with time zone field
+    static final String pattern = "dd-MM-yyyy HH:mm:ss z";
+}
+
--- a/langtools/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -329,3 +329,4 @@
 e3445ccab58f741801021dec9aa46e7f2c09efd9 jdk9-b84
 7ef2c66892a3af15540c2800104c660c4f7f45e9 jdk9-b85
 130a7c2a85900dde04e119bc36853b73146e3414 jdk9-b86
+45f796d8cdcd8dbde5d4d660c3e749a14c923e6d jdk9-b87
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Wed Jul 05 20:54:58 2017 +0200
@@ -142,6 +142,10 @@
         return false;
     }
 
+    public boolean isIntegral() {
+        return false;
+    }
+
     public boolean isPrimitive() {
         return false;
     }
@@ -697,6 +701,20 @@
         }
 
         @Override
+        public boolean isIntegral() {
+            switch (tag) {
+                case CHAR:
+                case BYTE:
+                case SHORT:
+                case INT:
+                case LONG:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
         public boolean isPrimitive() {
             return true;
         }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jul 05 20:54:58 2017 +0200
@@ -409,6 +409,9 @@
  * Class name generation
  **************************************************************************/
 
+
+    private Map<Pair<Name, Name>, Integer> localClassNameIndexes = new HashMap<>();
+
     /** Return name of local class.
      *  This is of the form   {@code <enclClass> $ n <classname> }
      *  where
@@ -416,17 +419,28 @@
      *    classname is the simple name of the local class
      */
     Name localClassName(ClassSymbol c) {
-        for (int i=1; ; i++) {
-            Name flatname = names.
-                fromString("" + c.owner.enclClass().flatname +
-                           syntheticNameChar + i +
-                           c.name);
-            if (compiled.get(flatname) == null) return flatname;
+        Name enclFlatname = c.owner.enclClass().flatname;
+        String enclFlatnameStr = enclFlatname.toString();
+        Pair<Name, Name> key = new Pair<>(enclFlatname, c.name);
+        Integer index = localClassNameIndexes.get(key);
+        for (int i = (index == null) ? 1 : index; ; i++) {
+            Name flatname = names.fromString(enclFlatnameStr
+                    + syntheticNameChar + i + c.name);
+            if (compiled.get(flatname) == null) {
+                localClassNameIndexes.put(key, i + 1);
+                return flatname;
+            }
         }
     }
 
+    void clearLocalClassNameIndexes(ClassSymbol c) {
+        localClassNameIndexes.remove(new Pair<>(
+                c.owner.enclClass().flatname, c.name));
+    }
+
     public void newRound() {
         compiled.clear();
+        localClassNameIndexes.clear();
     }
 
 /* *************************************************************************
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 05 20:54:58 2017 +0200
@@ -472,6 +472,7 @@
                 if (csym == null) return;
                 typeEnvs.remove(csym);
                 chk.compiled.remove(csym.flatname);
+                chk.clearLocalClassNameIndexes(csym);
                 syms.classes.remove(csym.flatname);
                 super.visitClassDef(tree);
             }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Wed Jul 05 20:54:58 2017 +0200
@@ -404,13 +404,20 @@
      */
     class UnaryNumericOperator extends UnaryOperatorHelper {
 
+        Predicate<Type> numericTest;
+
         UnaryNumericOperator(Tag tag) {
+            this(tag, Type::isNumeric);
+        }
+
+        UnaryNumericOperator(Tag tag, Predicate<Type> numericTest) {
             super(tag);
+            this.numericTest = numericTest;
         }
 
         @Override
         public boolean test(Type type) {
-            return unaryPromotion(type).isNumeric();
+            return numericTest.test(unaryPromotion(type));
         }
 
         @Override
@@ -462,8 +469,15 @@
      */
     class BinaryNumericOperator extends BinaryOperatorHelper {
 
+        Predicate<Type> numericTest;
+
         BinaryNumericOperator(Tag tag) {
+            this(tag, Type::isNumeric);
+        }
+
+        BinaryNumericOperator(Tag tag, Predicate<Type> numericTest) {
             super(tag);
+            this.numericTest = numericTest;
         }
 
         @Override
@@ -474,7 +488,8 @@
 
         @Override
         public boolean test(Type arg1, Type arg2) {
-            return unaryPromotion(arg1).isNumeric() && unaryPromotion(arg2).isNumeric();
+            return numericTest.test(unaryPromotion(arg1)) &&
+                    numericTest.test(unaryPromotion(arg2));
         }
     }
 
@@ -518,20 +533,22 @@
 
         @Override
         public boolean test(Type arg1, Type arg2) {
-            return types.isSameType(arg1, syms.stringType) ||
+            boolean hasStringOp = types.isSameType(arg1, syms.stringType) ||
                     types.isSameType(arg2, syms.stringType);
+            boolean hasVoidOp = arg1.hasTag(TypeTag.VOID) || arg2.hasTag(TypeTag.VOID);
+            return hasStringOp && !hasVoidOp;
         }
 
         /**
          * This routine applies following mappings:
          * - if input type is primitive, apply numeric promotion
-         * - if input type is either 'null' or 'String' leave it untouched
+         * - if input type is either 'void', 'null' or 'String' leave it untouched
          * - otherwise return 'Object'
          */
         private Type stringPromotion(Type t) {
             if (t.isPrimitive()) {
                 return unaryPromotion(t);
-            } else if (t.hasTag(TypeTag.BOT) ||
+            } else if (t.hasTag(TypeTag.VOID) || t.hasTag(TypeTag.BOT) ||
                     types.isSameType(t, syms.stringType)) {
                 return t;
             } else if (t.hasTag(TypeTag.TYPEVAR)) {
@@ -640,7 +657,7 @@
                         .addUnaryOperator(FLOAT, FLOAT, fneg)
                         .addUnaryOperator(LONG, LONG, lneg)
                         .addUnaryOperator(INT, INT, ineg),
-                new UnaryNumericOperator(Tag.COMPL)
+                new UnaryNumericOperator(Tag.COMPL, Type::isIntegral)
                         .addUnaryOperator(LONG, LONG, lxor)
                         .addUnaryOperator(INT, INT, ixor),
                 new UnaryPrefixPostfixOperator(Tag.POSTINC)
@@ -713,17 +730,17 @@
                     .addBinaryOperator(INT, INT, INT, imod),
             new BinaryBooleanOperator(Tag.BITAND)
                     .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, iand),
-            new BinaryNumericOperator(Tag.BITAND)
+            new BinaryNumericOperator(Tag.BITAND, Type::isIntegral)
                     .addBinaryOperator(LONG, LONG, LONG, land)
                     .addBinaryOperator(INT, INT, INT, iand),
             new BinaryBooleanOperator(Tag.BITOR)
                     .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ior),
-            new BinaryNumericOperator(Tag.BITOR)
+            new BinaryNumericOperator(Tag.BITOR, Type::isIntegral)
                     .addBinaryOperator(LONG, LONG, LONG, lor)
                     .addBinaryOperator(INT, INT, INT, ior),
             new BinaryBooleanOperator(Tag.BITXOR)
                     .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ixor),
-            new BinaryNumericOperator(Tag.BITXOR)
+            new BinaryNumericOperator(Tag.BITXOR, Type::isIntegral)
                     .addBinaryOperator(LONG, LONG, LONG, lxor)
                     .addBinaryOperator(INT, INT, INT, ixor),
             new BinaryShiftOperator(Tag.SL)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 05 20:54:58 2017 +0200
@@ -3215,8 +3215,7 @@
                 findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
                 findMethod(env, site, name, argtypes, typeargtypes,
                         phase.isBoxingRequired(), phase.isVarargsRequired());
-            return site.getEnclosingType().hasTag(CLASS) && !hasEnclosingInstance(env, site) ?
-                        new BadConstructorReferenceError(sym) : sym;
+            return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym;
         }
 
         @Override
@@ -3349,9 +3348,12 @@
         }
     }
 
-    boolean hasEnclosingInstance(Env<AttrContext> env, Type type) {
-        Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
-        return encl != null && !encl.kind.isResolutionError();
+    boolean enclosingInstanceMissing(Env<AttrContext> env, Type type) {
+        if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) {
+            Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
+            return encl == null || encl.kind.isResolutionError();
+        }
+        return false;
     }
 
     private Symbol resolveSelfContainingInternal(Env<AttrContext> env,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8138840.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+ * @compile/fail/ref=T8138840.out -XDrawDiagnostics T8138840.java
+ */
+
+class T8138840 {
+    void test(int x, double d) {
+        Object o = x & d;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8138840.out	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,2 @@
+T8138840.java:10:22: compiler.err.operator.cant.be.applied.1: &, int, double
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139243.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+ *          'void' is erroneously accepted as a possible operand for string concatenation
+ * @compile/fail/ref=T8139243.out -XDrawDiagnostics T8139243.java
+ */
+
+class T8139243 {
+
+    void test(String s) {
+        s += m(); // compile time error
+    }
+
+    void m() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139243.out	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,2 @@
+T8139243.java:12:11: compiler.err.operator.cant.be.applied.1: +, java.lang.String, void
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139249.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+*           Unary operator erroneously applied to non-integral type operand
+ * @compile/fail/ref=T8139249.out -XDrawDiagnostics T8139249.java
+ */
+
+class T8139249 {
+    void test(float f2) {
+        float f1 = ~f2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139249.out	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,2 @@
+T8139249.java:11:20: compiler.err.operator.cant.be.applied: ~, float
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8000316/T8000316.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, 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 8000316
+ * @summary Huge performance bottleneck in com.sun.tools.javac.comp.Check.localClassName
+ * @modules jdk.compiler
+ * @run main T8000316
+ */
+
+import com.sun.source.util.JavacTask;
+import java.net.URI;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Locale;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+public class T8000316 {
+
+    final static int N_METHODS = 1024;
+    final static int N_CLASSES = 8;
+
+    static class TestClass extends SimpleJavaFileObject {
+
+        String methTemplate = "    public static Runnable get#N() {\n" +
+                              "        return new Runnable() {\n" +
+                              "            @Override\n" +
+                              "            public void run() {\n" +
+                              "                return;\n" +
+                              "            }\n" +
+                              "        };\n" +
+                              "    }\n";
+
+        String classTemplate = "\n\nclass Chain#N {\n\n#M }";
+
+        String source;
+
+        public TestClass() {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            StringBuilder buf = new StringBuilder();
+            StringBuilder fileBuf = new StringBuilder();
+
+            for (int i = 0 ; i < N_CLASSES ; i++) {
+                for (int j = 0; j < N_METHODS; j++) {
+                    buf.append(methTemplate.replace("#N", String.valueOf(j)));
+                    buf.append("\n");
+                }
+                fileBuf.append(classTemplate.replace("#M", buf.toString()).replace("#N", String.valueOf(i)));
+                buf = new StringBuilder();
+                source = fileBuf.toString();
+            }
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return source;
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        ArrayList<JavaFileObject> sources = new ArrayList<>();
+        sources.add(new TestClass());
+        new T8000316().run(sources);
+    }
+
+    void run(List<JavaFileObject> sources) throws Exception {
+        javax.tools.DiagnosticListener<JavaFileObject> dc = (diagnostic) -> {
+            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+                throw new AssertionError("unexpected diagnostic: " + diagnostic.getMessage(Locale.getDefault()));
+            }
+        };
+        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) {
+            JavacTask ct = (JavacTask)comp.getTask(null, fm, dc,
+                    null, null, sources);
+            ct.analyze();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/methodReference/MethodRefIntColonColonNewTest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,20 @@
+/**
+ * @test    /nodynamiccopyright/
+ * @bug     8139245
+ * @summary compiler crashes with exception on int:new method reference and generic method inference
+ * @compile/fail/ref=MethodRefIntColonColonNewTest.out -XDrawDiagnostics MethodRefIntColonColonNewTest.java
+ */
+
+public class MethodRefIntColonColonNewTest {
+
+    interface SAM<T> {
+        T m(T s);
+    }
+
+    static <T> SAM<T> infmethod(SAM<T> t) { return t; }
+
+    public static void main(String argv[]) {
+        SAM<Object> s = infmethod(int::new);
+        s.m();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/methodReference/MethodRefIntColonColonNewTest.out	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,3 @@
+MethodRefIntColonColonNewTest.java:17:35: compiler.err.type.found.req: int, (compiler.misc.type.req.class.array)
+MethodRefIntColonColonNewTest.java:18:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, compiler.misc.no.args, kindname.interface, MethodRefIntColonColonNewTest.SAM<T>, (compiler.misc.arg.length.mismatch)
+2 errors
--- a/langtools/test/tools/javac/proprietary/WarnClass.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/javac/proprietary/WarnClass.java	Wed Jul 05 20:54:58 2017 +0200
@@ -3,11 +3,11 @@
  * @bug     6380059
  * @summary Emit warnings for proprietary packages in the boot class path
  * @author  Peter von der Ah\u00e9
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
  * @compile WarnClass.java
  * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror WarnClass.java
  * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror -nowarn WarnClass.java
  * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror -Xlint:none WarnClass.java
  */
 
-public class WarnClass extends sun.misc.Lock {}
+public class WarnClass extends sun.security.x509.X509CertInfo {}
--- a/langtools/test/tools/javac/proprietary/WarnClass.out	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/javac/proprietary/WarnClass.out	Wed Jul 05 20:54:58 2017 +0200
@@ -1,4 +1,4 @@
-WarnClass.java:13:40: compiler.warn.sun.proprietary: sun.misc.Lock
+WarnClass.java:13:49: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
 - compiler.err.warnings.and.werror
 1 error
 1 warning
--- a/langtools/test/tools/javac/warnings/6594914/T6594914b.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/javac/warnings/6594914/T6594914b.java	Wed Jul 05 20:54:58 2017 +0200
@@ -2,29 +2,31 @@
  * @test /nodynamiccopyright/
  * @bug 6594914
  * @summary \\@SuppressWarnings("deprecation") does not not work for the type of a variable
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
  * @compile/ref=T6594914b.out -XDenableSunApiLintControl -XDrawDiagnostics -Xlint:sunapi T6594914b.java
  */
 
 
 class T6747671b {
 
-    sun.misc.Lock a1; //warn
+    sun.security.x509.X509CertInfo a1; //warn
 
     @SuppressWarnings("sunapi")
-    sun.misc.Lock a2;
+    sun.security.x509.X509CertInfo a2;
 
-    <X extends sun.misc.Lock> sun.misc.Lock m1(sun.misc.Lock a)
-            throws sun.misc.CEFormatException { return null; } //warn
+    <X extends sun.security.x509.X509CertInfo>
+    sun.security.x509.X509CertInfo m1(sun.security.x509.X509CertInfo a)
+            throws sun.security.x509.CertException { return null; } //warn
 
     @SuppressWarnings("sunapi")
-    <X extends sun.misc.Lock> sun.misc.Lock m2(sun.misc.Lock a)
-            throws sun.misc.CEFormatException { return null; }
+    <X extends sun.security.x509.X509CertInfo>
+    sun.security.x509.X509CertInfo m2(sun.security.x509.X509CertInfo a)
+            throws sun.security.x509.CertException { return null; }
 
     void test() {
-        sun.misc.Lock a1; //warn
+        sun.security.x509.X509CertInfo a1; //warn
 
         @SuppressWarnings("sunapi")
-        sun.misc.Lock a2;
+        sun.security.x509.X509CertInfo a2;
     }
 }
--- a/langtools/test/tools/javac/warnings/6594914/T6594914b.out	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/javac/warnings/6594914/T6594914b.out	Wed Jul 05 20:54:58 2017 +0200
@@ -1,7 +1,9 @@
-T6594914b.java:12:13: compiler.warn.sun.proprietary: sun.misc.Lock
-T6594914b.java:17:24: compiler.warn.sun.proprietary: sun.misc.Lock
-T6594914b.java:17:39: compiler.warn.sun.proprietary: sun.misc.Lock
-T6594914b.java:18:28: compiler.warn.sun.proprietary: sun.misc.CEFormatException
-T6594914b.java:17:56: compiler.warn.sun.proprietary: sun.misc.Lock
-T6594914b.java:25:17: compiler.warn.sun.proprietary: sun.misc.Lock
+T6594914b.java:12:22: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
+T6594914b.java:17:33: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
+T6594914b.java:18:22: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
+T6594914b.java:19:37: compiler.warn.sun.proprietary: sun.security.x509.CertException
+T6594914b.java:18:56: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
+T6594914b.java:27:26: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
+- compiler.note.deprecated.filename: T6594914b.java
+- compiler.note.deprecated.recompile
 6 warnings
--- a/langtools/test/tools/jdeps/APIDeps.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/jdeps/APIDeps.java	Wed Jul 05 20:54:58 2017 +0200
@@ -25,7 +25,7 @@
  * @test
  * @bug 8015912 8029216 8048063 8050804
  * @summary Test -apionly and -jdkinternals options
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
  *          java.management
  *          jdk.jdeps/com.sun.tools.classfile
  *          jdk.jdeps/com.sun.tools.jdeps
@@ -72,20 +72,20 @@
              new String[] {testDirBasename},
              new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-filter:none", "-P"});
         test(new File(mDir, "Gee.class"),
-             new String[] {"g.G", "sun.misc.Lock", "com.sun.tools.classfile.ClassFile",
+             new String[] {"g.G", "sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile",
                            "com.sun.management.ThreadMXBean", "com.sun.source.tree.BinaryTree"},
              new String[] {testDirBasename, "JDK internal API", "compact3", ""},
              new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});
 
         // -jdkinternals
         test(new File(mDir, "Gee.class"),
-             new String[] {"sun.misc.Lock", "com.sun.tools.classfile.ClassFile"},
+             new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile"},
              new String[] {"JDK internal API"},
              new String[] {"-jdkinternals"});
         // -jdkinternals parses all classes on -classpath and the input arguments
         test(new File(mDir, "Gee.class"),
              new String[] {"com.sun.tools.jdeps.Main", "com.sun.tools.classfile.ClassFile",
-                           "sun.misc.Lock", "sun.misc.Unsafe"},
+                           "sun.security.x509.X509CertInfo", "sun.misc.Unsafe"},
              new String[] {"JDK internal API"},
              new String[] {"-classpath", testDir.getPath(), "-jdkinternals"});
 
--- a/langtools/test/tools/jdeps/m/Gee.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/langtools/test/tools/jdeps/m/Gee.java	Wed Jul 05 20:54:58 2017 +0200
@@ -25,7 +25,7 @@
 
 
 class Gee extends g.G {
-    public sun.misc.Lock lock;
+    public sun.security.x509.X509CertInfo cert;
     public com.sun.tools.classfile.ClassFile cf;     // @jdk.Exported(false)
     public com.sun.source.tree.BinaryTree tree;      // @jdk.Exported
     public com.sun.management.ThreadMXBean mxbean;   // @jdk.Exported on package-info
--- a/nashorn/.hgtags	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/.hgtags	Wed Jul 05 20:54:58 2017 +0200
@@ -320,3 +320,4 @@
 214b97ba911f4d768c0214098739e32ab54c8503 jdk9-b84
 285628dac94332d95979de365630c93ab8fa9962 jdk9-b85
 e4283eeb182cbdf5004740728a404aac6afa1104 jdk9-b86
+0bf2fe0c7b3277cd247ed4f6faaf2b56d83139cf jdk9-b87
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/jsadapter-fallthrough.js	Wed Jul 05 20:54:58 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Demonstrate how to provide a default fall-through solution for adapted Java
+// objects, forwarding all calls that are not adapted.
+
+var Date = Java.type('java.time.LocalDate')
+
+function wrapDate(d) {
+    return new JSAdapter() {
+        __call__: function() {
+            // adapted (extra) methods
+            if (arguments[0] === 'yesterday') {
+                return d.minusDays(1)
+            }
+            // fall-through: forward all other, non-adapted method calls
+            var args = [d].concat(Array.prototype.slice.call(arguments, 1)) 
+            return Function.call.apply(d[arguments[0]], args)
+        }
+    }
+}
+
+var now = wrapDate(Date.now())
+
+print(now)
+print(now.yesterday()) // adapted
+print(now.lengthOfMonth()) // fall through to original method
+print(now.atTime(23, 42)) // arguments are passed through
+
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -96,8 +96,6 @@
  * guarding linkers so they aren't tempted to directly manipulate the call sites. The constructors of built-in
  * {@link RelinkableCallSite} implementations all need a call site descriptor. Even if you create your own call site
  * descriptors consider using {@link CallSiteDescriptorFactory#tokenizeName(String)} in your implementation.
- *
- * @author Attila Szegedi
  */
 public interface CallSiteDescriptor {
     /**
@@ -157,7 +155,9 @@
     public MethodType getMethodType();
 
     /**
-     * Returns the lookup passed to the bootstrap method.
+     * Returns the lookup passed to the bootstrap method. If the lookup isn't the public lookup, the
+     * implementation must check the {@code RuntimePermission("dynalink.getLookup")} permission if a security
+     * manager is present.
      * @return the lookup passed to the bootstrap method.
      */
     public Lookup getLookup();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java	Wed Jul 05 20:54:58 2017 +0200
@@ -85,9 +85,9 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.concurrent.atomic.AtomicReference;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
 import jdk.internal.dynalink.support.Lookup;
@@ -112,7 +112,14 @@
         PRUNE_SWITCHPOINTS = MethodHandles.insertArguments(PRUNE, 2, false);
     }
 
-    private final AtomicReference<LinkedList<GuardedInvocation>> invocations = new AtomicReference<>();
+    /**
+     * Contains the invocations currently linked into this call site's target. They are used when we are
+     * relinking to rebuild the guardWithTest chain. Valid values for this field are: {@code null} if there's
+     * no linked invocations, or an instance of {@link GuardedInvocation} if there is exactly one previous
+     * invocation, or an instance of {@code GuardedInvocation[]} if there is more than one previous
+     * invocation.
+     */
+    private Object invocations;
 
     /**
      * Creates a new chained call site.
@@ -142,10 +149,18 @@
     }
 
     private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
-        final LinkedList<GuardedInvocation> currentInvocations = invocations.get();
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        final LinkedList<GuardedInvocation> newInvocations =
-            currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone();
+        final Object currentInvocations = invocations;
+        final LinkedList<GuardedInvocation> newInvocations;
+        if (currentInvocations == null || reset) {
+            newInvocations = new LinkedList<>();
+        } else if (currentInvocations instanceof GuardedInvocation) {
+            newInvocations = new LinkedList<>();
+            newInvocations.add((GuardedInvocation)currentInvocations);
+        } else if (currentInvocations instanceof GuardedInvocation[]) {
+            newInvocations = new LinkedList<>(Arrays.asList(((GuardedInvocation[])currentInvocations)));
+        } else {
+            throw new AssertionError();
+        }
 
         // First, prune the chain of invalidated switchpoints, we always do this
         // We also remove any catches if the remove catches flag is set
@@ -177,12 +192,17 @@
             target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches);
         }
 
-        // If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case
-        // we lost the race for multithreaded update, just do nothing. Either the other thread installed the same thing
-        // we wanted to install, or otherwise, we'll be asked to relink again.
-        if(invocations.compareAndSet(currentInvocations, newInvocations)) {
-            setTarget(target);
+        switch (newInvocations.size()) {
+            case 0:
+                invocations = null;
+                break;
+            case 1:
+                invocations = newInvocations.getFirst();
+                break;
+            default:
+                invocations = newInvocations.toArray(new GuardedInvocation[newInvocations.size()]);
         }
+        setTarget(target);
         return target;
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DefaultBootstrapper.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DefaultBootstrapper.java	Wed Jul 05 20:54:58 2017 +0200
@@ -97,8 +97,6 @@
  * and one that just uses the passed caller as the lookup scope. Using the public lookup one is advised if your language
  * runtime has no concept of interacting with Java visibility scopes, as it results in a more lightweight runtime
  * information.
- *
- * @author Attila Szegedi
  */
 public class DefaultBootstrapper {
     private static final DynamicLinker dynamicLinker = new DynamicLinkerFactory().createLinker();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -147,15 +147,14 @@
  * additional parameters to the bootstrap method) to them.</li>
  *
  * </ul>
- *
- * @author Attila Szegedi
  */
-public class DynamicLinker {
+public final class DynamicLinker {
     private static final String CLASS_NAME = DynamicLinker.class.getName();
     private static final String RELINK_METHOD_NAME = "relink";
 
     private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives";
     private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
+    private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke.";
 
     private final LinkerServices linkerServices;
     private final GuardedInvocationFilter prelinkFilter;
@@ -305,26 +304,21 @@
         final StackTraceElement[] trace = new Throwable().getStackTrace();
         for(int i = 0; i < trace.length - 1; ++i) {
             final StackTraceElement frame = trace[i];
+            // If we found any of our linking entry points on the stack...
             if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) {
-                return trace[i + 1];
+                // ... then look for the first thing calling it that isn't j.l.invoke
+                for (int j = i + 1; j < trace.length; ++j) {
+                    final StackTraceElement frame2 = trace[j];
+                    if (!frame2.getClassName().startsWith(INVOKE_PACKAGE_PREFIX)) {
+                        return frame2;
+                    }
+                }
             }
         }
         return null;
     }
 
     /**
-     * Deprecated because of imprecise name.
-     *
-     * @deprecated Use {@link #getLinkedCallSiteLocation()} instead.
-     *
-     * @return see non-deprecated method
-     */
-    @Deprecated
-    public static StackTraceElement getRelinkedCallSiteLocation() {
-        return getLinkedCallSiteLocation();
-    }
-
-    /**
      * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()},
      * the frame immediately on top of the call site frame when the call site is
      * being linked for the first time.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -111,14 +111,13 @@
 import jdk.internal.dynalink.support.TypeUtilities;
 
 /**
- * A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
- * of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
- * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker} and a
- * {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on how to use this class.
- *
- * @author Attila Szegedi
+ * A factory class for creating {@link DynamicLinker}s. The usual dynamic linker is a linker composed of all
+ * {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
+ * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback
+ * {@link BeansLinker} and a {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on
+ * how to use this class.
  */
-public class DynamicLinkerFactory {
+public final class DynamicLinkerFactory {
     /**
      * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}.
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/MonomorphicCallSite.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/MonomorphicCallSite.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,8 +91,6 @@
  * A relinkable call site that implements monomorphic inline caching strategy. After it linked a method, it will keep it
  * until either its guard evaluates to false, or its switchpoint is invalidated, at which time it will throw away the
  * previous linkage, and trigger relinking with its associated {@link DynamicLinker}.
- *
- * @author Attila Szegedi
  */
 public class MonomorphicCallSite extends AbstractRelinkableCallSite {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NoSuchDynamicMethodException.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NoSuchDynamicMethodException.java	Wed Jul 05 20:54:58 2017 +0200
@@ -87,8 +87,6 @@
 
 /**
  * Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}.
- *
- * @author Attila Szegedi
  */
 public class NoSuchDynamicMethodException extends RuntimeException {
     private static final long serialVersionUID = 1L;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java	Wed Jul 05 20:54:58 2017 +0200
@@ -96,13 +96,11 @@
  * {@link ChainedCallSite} that retains a chain of already linked method handles. The reason this is defined as an
  * interface instead of a concrete, albeit abstract class is that it allows independent implementations to choose
  * between {@link MutableCallSite} and {@link VolatileCallSite} as they see fit.
- *
- * @author Attila Szegedi
  */
 public interface RelinkableCallSite {
     /**
-     * Initializes the relinkable call site by setting a relink-and-invoke method handle. The call site implementation
-     * is supposed to set this method handle as its target.
+     * Initializes the relinkable call site by setting a relink-and-invoke method handle. The call site
+     * implementation is supposed to set this method handle as its target.
      * @param relinkAndInvoke a relink-and-invoke method handle supplied by the {@link DynamicLinker}.
      */
     public void initialize(MethodHandle relinkAndInvoke);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -111,8 +111,6 @@
 /**
  * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
  * exposure and method calls for both static and instance facets of a class.
- *
- * @author Attila Szegedi
  */
 abstract class AbstractJavaLinker implements GuardingDynamicLinker {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AccessibleMembersLookup.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AccessibleMembersLookup.java	Wed Jul 05 20:54:58 2017 +0200
@@ -98,8 +98,6 @@
  * public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly
  * accessible superclass or implemented interface of the class, and use it instead of the member discovered on the
  * class.
- *
- * @author Attila Szegedi
  */
 class AccessibleMembersLookup {
     private final Map<MethodSignature, Method> methods;
@@ -140,8 +138,6 @@
 
     /**
      * A helper class that represents a method signature - name and argument types.
-     *
-     * @author Attila Szegedi
      */
     static final class MethodSignature {
         private final String name;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java	Wed Jul 05 20:54:58 2017 +0200
@@ -90,8 +90,6 @@
 
 /**
  * Represents overloaded methods applicable to a specific call site signature.
- *
- * @author Attila Szegedi
  */
 class ApplicableOverloadedMethods {
     private final List<SingleDynamicMethod> methods;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -102,8 +102,6 @@
 /**
  * A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by
  * {@link BeansLinker}.
- *
- * @author Attila Szegedi
  */
 class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker {
     BeanLinker(final Class<?> clazz) {
@@ -316,8 +314,6 @@
     /**
      * Contains methods to adapt an item getter/setter method handle to the requested type, optionally binding it to a
      * fixed key first.
-     * @author Attila Szegedi
-     * @version $Id: $
      */
     private static class Binder {
         private final LinkerServices linkerServices;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -125,8 +125,6 @@
  * <p><strong>Variable argument invocation</strong> is handled for both methods and constructors.</p>
  * <p>Currently, only public fields and methods are supported. Any Lookup objects passed in the
  * {@link LinkRequest}s are ignored and {@link MethodHandles#publicLookup()} is used instead.</p>
- *
- * @author Attila Szegedi
  */
 public class BeansLinker implements GuardingDynamicLinker {
     private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -98,8 +98,6 @@
  * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in
  * {@link #getTarget(java.lang.invoke.MethodHandles.Lookup)} to unreflect a method handle from the reflective member on
  * every request.
- *
- * @author Attila Szegedi
  */
 class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
     // Typed as "AccessibleObject" as it can be either a method or a constructor.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -93,7 +93,6 @@
  * A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and
  * methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by
  * the Dynalink as constructors for the instances of the class, {@link StaticClass} is used for this purpose.
- * @author Attila Szegedi
  */
 class ClassLinker extends BeanLinker {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java	Wed Jul 05 20:54:58 2017 +0200
@@ -92,8 +92,9 @@
 import jdk.internal.dynalink.support.TypeUtilities;
 
 /**
- *
- * @author Attila Szegedi
+ * Represents a sequence of {@link Class} objects, useful for representing method signatures. Provides value
+ * semantics for using them as map keys, as well as specificity calculations and applicability checks as per
+ * JLS.
  */
 final class ClassString {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -93,8 +93,6 @@
  * overloaded methods will perform overload resolution (actually, it will perform partial overloaded resolution at link
  * time, but if that fails to identify exactly one target method, it will generate a method handle that will perform the
  * rest of the overload resolution at invocation time for actual argument types).
- *
- * @author Attila Szegedi
  */
 abstract class DynamicMethod {
     private final String name;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java	Wed Jul 05 20:54:58 2017 +0200
@@ -97,7 +97,6 @@
 /**
  * Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are
  * subclasses for instance (bean) and static facet of a class.
- * @author Attila Szegedi
  */
 abstract class FacetIntrospector {
     private final Class<?> clazz;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/GuardedInvocationComponent.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/GuardedInvocationComponent.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,8 +91,6 @@
  * {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its
  * guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz"
  * expressions. This allows choosing the most restrictive guard as the guard for the composition of two components.
- * @author Attila Szegedi
- * @version $Id: $
  */
 class GuardedInvocationComponent {
     enum ValidationType {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java	Wed Jul 05 20:54:58 2017 +0200
@@ -94,8 +94,6 @@
 
 /**
  * Utility class that encapsulates the algorithm for choosing the maximally specific methods.
- *
- * @author Attila Szegedi
  */
 class MaximallySpecific {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -101,8 +101,6 @@
  * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all
  * constructors) for a particular class. Correctly handles overload resolution, variable arity methods, and caller
  * sensitive methods within the overloads.
- *
- * @author Attila Szegedi
  */
 class OverloadedDynamicMethod extends DynamicMethod {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -100,8 +100,6 @@
  * a vararg subset depending on the subclass. The method is for a fixed number of arguments though (as it is generated
  * for a concrete call site). As such, all methods in the subset can be invoked with the specified number of arguments
  * (exactly matching for fixargs, or having less than or equal fixed arguments, for varargs).
- *
- * @author Attila Szegedi
  */
 class OverloadedMethod {
     private final Map<ClassString, MethodHandle> argTypesToMethods = new ConcurrentHashMap<>();
@@ -122,7 +120,7 @@
         fixArgMethods = new ArrayList<>(methodHandles.size());
         varArgMethods = new ArrayList<>(methodHandles.size());
         final int argNum = callSiteType.parameterCount();
-        for(MethodHandle mh: methodHandles) {
+        for(final MethodHandle mh: methodHandles) {
             if(mh.isVarargsCollector()) {
                 final MethodHandle asFixed = mh.asFixedArity();
                 if(argNum == asFixed.type().parameterCount()) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -93,8 +93,6 @@
  * {@link #getTarget(Lookup)}. Can be used in general to represents dynamic methods bound to a single method handle,
  * even if that handle is not mapped to a Java method, i.e. as a wrapper around field getters/setters, array element
  * getters/setters, etc.
- *
- * @author Attila Szegedi
  */
 class SimpleDynamicMethod extends SingleDynamicMethod {
     private final MethodHandle target;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Wed Jul 05 20:54:58 2017 +0200
@@ -97,7 +97,6 @@
  * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the
  * target method to a call site type (including mapping variable arity methods to a call site signature with different
  * arity).
- * @author Attila Szegedi
  */
 abstract class SingleDynamicMethod extends DynamicMethod {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -99,7 +99,6 @@
 
 /**
  * Provides a linker for the {@link StaticClass} objects.
- * @author Attila Szegedi
  */
 class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
     private static final ClassValue<SingleClassStaticsLinker> linkers = new ClassValue<SingleClassStaticsLinker>() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java	Wed Jul 05 20:54:58 2017 +0200
@@ -90,15 +90,17 @@
  * of additional conversions. The static way of selecting the "most specific" method will fail more often, because there
  * will be multiple maximally specific method with unrelated signatures. In these cases, language runtimes can be asked
  * to resolve the ambiguity by expressing preferences for one conversion over the other.
- * @author Attila Szegedi
  */
 public interface ConversionComparator {
     /**
      * Enumeration of possible outcomes of comparing one conversion to another.
      */
     enum Comparison {
+        /** The conversions cannot be compared. **/
         INDETERMINATE,
+        /** The first conversion is better than the second one. **/
         TYPE_1_BETTER,
+        /** The second conversion is better than the first one. **/
         TYPE_2_BETTER,
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java	Wed Jul 05 20:54:58 2017 +0200
@@ -101,8 +101,6 @@
  * external invalidation of the invocation handle. The invocation handle is suitable for invocation if the guard
  * handle returns true for its arguments, and as long as the switch point is not invalidated. Both the guard and the
  * switch point are optional; neither, one, or both can be present.
- *
- * @author Attila Szegedi
  */
 public class GuardedInvocation {
     private final MethodHandle invocation;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,8 +89,6 @@
  * very least, it depends on the receiver belonging to the language runtime of the linker). Language runtime
  * implementors will normally implement one for their own language, and declare it in the
  * <tt>META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker</tt> file within their JAR file.
- *
- * @author Attila Szegedi
  */
 public interface GuardingDynamicLinker {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,8 +91,6 @@
  * very likely want to implement {@link ConversionComparator} interface too, as your additional language-specific
  * conversions, in absence of a strategy for prioritizing these conversions, will cause more ambiguity in selecting the
  * correct overload when trying to link to an overloaded POJO method.
- *
- * @author Attila Szegedi
  */
 public interface GuardingTypeConverterFactory {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,8 +89,6 @@
 /**
  * Represents a request to link a particular invocation at a particular call site. Instances of these requests are being
  * passed to {@link GuardingDynamicLinker}.
- *
- * @author Attila Szegedi
  */
 public interface LinkRequest {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java	Wed Jul 05 20:54:58 2017 +0200
@@ -95,8 +95,6 @@
  * Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns
  * them. You can think of it as the interface of the {@link DynamicLinker} that faces the {@link GuardingDynamicLinker}
  * s.
- *
- * @author Attila Szegedi
  */
 public interface LinkerServices {
     /**
@@ -130,7 +128,11 @@
      * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
      * {@link GuardingTypeConverterFactory}-produced type converters as filters.
      */
-    public MethodHandle asTypeLosslessReturn(MethodHandle handle, MethodType fromType);
+    public default MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
+        final Class<?> handleReturnType = handle.type().returnType();
+        return asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ?
+                fromType : fromType.changeReturnType(handleReturnType));
+    }
 
     /**
      * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
@@ -188,23 +190,4 @@
      * @return a method handle with parameters and/or return type potentially filtered for wrapping and unwrapping.
      */
     public MethodHandle filterInternalObjects(final MethodHandle target);
-
-    /**
-     * If we could just use Java 8 constructs, then {@code asTypeSafeReturn} would be a method with default
-     * implementation. Since we can't do that, we extract common default implementations into this static class.
-     */
-    public static class Implementation {
-        /**
-         * Default implementation for {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}.
-         * @param linkerServices the linker services that delegates to this implementation
-         * @param handle the passed handle
-         * @param fromType the passed type
-         * @return the converted method handle, as per the {@code asTypeSafeReturn} semantics.
-         */
-        public static MethodHandle asTypeLosslessReturn(final LinkerServices linkerServices, final MethodHandle handle, final MethodType fromType) {
-            final Class<?> handleReturnType = handle.type().returnType();
-            return linkerServices.asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ?
-                    fromType : fromType.changeReturnType(handleReturnType));
-        }
-    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -88,8 +88,6 @@
  * argument at linking invocation time. (The first argument is usually the receiver class). Most language-specific
  * linkers will fall into this category, as they recognize their native objects as Java objects of classes implementing
  * a specific language-native interface or superclass. The linker mechanism can optimize the dispatch for these linkers.
- *
- * @author Attila Szegedi
  */
 public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker {
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,7 +91,6 @@
 /**
  * A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens, as well
  * as a generally useful {@code equals} and {@code hashCode} methods.
- * @author Attila Szegedi
  */
 public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java	Wed Jul 05 20:54:58 2017 +0200
@@ -90,8 +90,6 @@
 
 /**
  * A basic implementation of the {@link RelinkableCallSite} as a {@link MutableCallSite} subclass.
- *
- * @author Attila Szegedi
  */
 public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite {
     private final CallSiteDescriptor descriptor;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,8 +91,6 @@
 /**
  * A linker that can't link any call site. Only used internally by {@link CompositeTypeBasedGuardingDynamicLinker}. Can
  * be used by other language runtimes if they need it though.
- *
- * @author Attila Szegedi
  */
 public class BottomGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -97,12 +97,12 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 
 /**
- * Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning it will
- * return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a descriptor
- * signifying public lookup for "dyn:getProp:color" of type "Object(Object)" will return the same object as long as
- * a previously created, at least softly reachable one exists. It also uses several different implementations of the
- * {@link CallSiteDescriptor} internally, and chooses the most space-efficient one based on the input.
- * @author Attila Szegedi
+ * Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning
+ * it will return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a
+ * descriptor signifying public lookup for {@code "dyn:getProp:color"} of type {@code Object(Object)} will
+ * return the same object as long as a previously created, at least softly reachable one exists. It also uses
+ * several different implementations of the {@link CallSiteDescriptor} internally, and chooses the most
+ * space-efficient one based on the input.
  */
 public class CallSiteDescriptorFactory {
     private static final WeakHashMap<CallSiteDescriptor, Reference<CallSiteDescriptor>> publicDescs =
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassMap.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassMap.java	Wed Jul 05 20:54:58 2017 +0200
@@ -96,7 +96,6 @@
  * A dual map that can either strongly or weakly reference a given class depending on whether the class is visible from
  * a class loader or not.
  *
- * @author Attila Szegedi
  * @param <T> the type of the values in the map
  */
 public abstract class ClassMap<T> {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -95,8 +95,6 @@
  * A {@link GuardingDynamicLinker} that delegates sequentially to a list of other guarding dynamic linkers. The first
  * value returned from a component linker other than null is returned. If no component linker returns an invocation,
  * null is returned.
- *
- * @author Attila Szegedi
  */
 public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker, Serializable {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -98,8 +98,6 @@
  * are queried sequentially on their {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
  * returning true are then bound to the class, and next time a receiver of same type is encountered, the linking is
  * delegated to those linkers only, speeding up dispatch.
- *
- * @author Attila Szegedi
  */
 public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker, Serializable {
     private static final long serialVersionUID = 1L;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -91,7 +91,6 @@
  * A default, fairly light implementation of a call site descriptor used for describing non-standard operations. It does
  * not store {@link Lookup} objects but always returns the public lookup from its {@link #getLookup()} method. If you
  * need to support non-public lookup, you can use {@link LookupCallSiteDescriptor}.
- * @author Attila Szegedi
  */
 class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Guards.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Guards.java	Wed Jul 05 20:54:58 2017 +0200
@@ -94,7 +94,6 @@
 /**
  * Utility methods for creating typical guards. TODO: introduce reasonable caching of created guards.
  *
- * @author Attila Szegedi
  */
 public class Guards {
     private static final Logger LOG = Logger
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkRequestImpl.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkRequestImpl.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,8 +89,6 @@
 /**
  * Default implementation of the {@link LinkRequest}, representing a link request to a call site that passes no language
  * runtime specific native context arguments on the stack.
- *
- * @author Attila Szegedi
  */
 public class LinkRequestImpl implements LinkRequest {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkerServicesImpl.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkerServicesImpl.java	Wed Jul 05 20:54:58 2017 +0200
@@ -94,8 +94,6 @@
 
 /**
  * Default implementation of the {@link LinkerServices} interface.
- *
- * @author Attila Szegedi
  */
 public class LinkerServicesImpl implements LinkerServices {
 
@@ -132,11 +130,6 @@
     }
 
     @Override
-    public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
-        return Implementation.asTypeLosslessReturn(this, handle, fromType);
-    }
-
-    @Override
     public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
         return typeConverterFactory.getTypeConverter(sourceType, targetType);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Lookup.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Lookup.java	Wed Jul 05 20:54:58 2017 +0200
@@ -93,8 +93,6 @@
 /**
  * A wrapper around MethodHandles.Lookup that masks checked exceptions in those cases when you're looking up methods
  * within your own codebase (therefore it is an error if they are not present).
- *
- * @author Attila Szegedi
  */
 public class Lookup {
     private final MethodHandles.Lookup lookup;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,7 +89,6 @@
 
 /**
  * A call site descriptor that stores a specific {@link Lookup}. It does not, however, store static bootstrap arguments.
- * @author Attila Szegedi
  */
 class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
     private final Lookup lookup;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java	Wed Jul 05 20:54:58 2017 +0200
@@ -99,8 +99,6 @@
  * have your own way of creating call site descriptors, but you still delegate to this method of the default factory
  * (it is recommended that you do), then you have demangling handled for you already, and only need to ensure that you
  * mangle the names when you're emitting them in the bytecode.
- *
- * @author Attila Szegedi
  */
 public class NameCodec {
     private static final char ESCAPE_CHAR = '\\';
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java	Wed Jul 05 20:54:58 2017 +0200
@@ -89,8 +89,6 @@
 /**
  * A link request implementation for call sites that pass language runtime specific context arguments on the stack. The
  * context specific arguments should be the first "n" arguments.
- *
- * @author Attila Szegedi
  */
 public class RuntimeContextLinkRequestImpl extends LinkRequestImpl {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java	Wed Jul 05 20:54:58 2017 +0200
@@ -103,8 +103,6 @@
  * A factory for type converters. This class is the main implementation behind the
  * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory}
  * instances and creates appropriate converters for method handles.
- *
- * @author Attila Szegedi
  */
 public class TypeConverterFactory {
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java	Wed Jul 05 20:54:58 2017 +0200
@@ -96,8 +96,6 @@
 
 /**
  * Various static utility methods for testing type relationships.
- *
- * @author Attila Szegedi
  */
 public class TypeUtilities {
     static final Class<Object> OBJECT_CLASS = Object.class;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Wed Jul 05 20:54:03 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Wed Jul 05 20:54:58 2017 +0200
@@ -211,11 +211,6 @@
         }
 
         @Override
-        public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
-            return Implementation.asTypeLosslessReturn(this, handle, fromType);
-        }
-
-        @Override
         public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
             return linkerServices.getTypeConverter(sourceType, targetType);
         }