Merge "Revert "JSR-166 update""
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 756ec02..21ad635 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -215,7 +215,7 @@
 LOCAL_SRC_FILES :=  $(call all-test-java-files-under, jsr166-tests)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs core-junit
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := jsr166-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
diff --git a/jsr166-tests/src/test/java/jsr166/AbstractExecutorServiceTest.java b/jsr166-tests/src/test/java/jsr166/AbstractExecutorServiceTest.java
index c293f13..9e83de2 100644
--- a/jsr166-tests/src/test/java/jsr166/AbstractExecutorServiceTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AbstractExecutorServiceTest.java
@@ -18,7 +18,6 @@
 import java.util.concurrent.AbstractExecutorService;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
@@ -39,7 +38,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AbstractExecutorServiceTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -197,25 +196,28 @@
     public void testInterruptedSubmit() throws InterruptedException {
         final CountDownLatch submitted    = new CountDownLatch(1);
         final CountDownLatch quittingTime = new CountDownLatch(1);
-        final Callable<Void> awaiter = new CheckedCallable<Void>() {
-            public Void realCall() throws InterruptedException {
-                assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS));
-                return null;
-            }};
         final ExecutorService p
             = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
                                      new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, quittingTime)) {
-            Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+        final Callable<Void> awaiter = new CheckedCallable<Void>() {
+            public Void realCall() throws InterruptedException {
+                quittingTime.await();
+                return null;
+            }};
+        try {
+            Thread t = new Thread(new CheckedInterruptedRunnable() {
                 public void realRun() throws Exception {
                     Future<Void> future = p.submit(awaiter);
                     submitted.countDown();
                     future.get();
                 }});
-
-            await(submitted);
+            t.start();
+            submitted.await();
             t.interrupt();
-            awaitTermination(t);
+            t.join();
+        } finally {
+            quittingTime.countDown();
+            joinPool(p);
         }
     }
 
@@ -224,32 +226,34 @@
      * throws exception
      */
     public void testSubmitEE() throws InterruptedException {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    60, TimeUnit.SECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            Callable c = new Callable() {
-                public Object call() { throw new ArithmeticException(); }};
-            try {
-                p.submit(c).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof ArithmeticException);
-            }
+
+        Callable c = new Callable() {
+            public Object call() { throw new ArithmeticException(); }};
+
+        try {
+            p.submit(c).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof ArithmeticException);
         }
+        joinPool(p);
     }
 
     /**
      * invokeAny(null) throws NPE
      */
     public void testInvokeAny1() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -257,12 +261,13 @@
      * invokeAny(empty collection) throws IAE
      */
     public void testInvokeAny2() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -270,16 +275,17 @@
      * invokeAny(c) throws NPE if c has null elements
      */
     public void testInvokeAny3() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<Long>> l = new ArrayList<Callable<Long>>();
-            l.add(new Callable<Long>() {
-                      public Long call() { throw new ArithmeticException(); }});
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+        l.add(new Callable<Long>() {
+            public Long call() { throw new ArithmeticException(); }});
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -287,16 +293,16 @@
      * invokeAny(c) throws ExecutionException if no task in c completes
      */
     public void testInvokeAny4() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -304,13 +310,15 @@
      * invokeAny(c) returns result of some task in c if at least one completes
      */
     public void testInvokeAny5() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -318,12 +326,13 @@
      * invokeAll(null) throws NPE
      */
     public void testInvokeAll1() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -331,10 +340,12 @@
      * invokeAll(empty collection) returns empty collection
      */
     public void testInvokeAll2() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -342,15 +353,16 @@
      * invokeAll(c) throws NPE if c has null elements
      */
     public void testInvokeAll3() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -358,8 +370,8 @@
      * get of returned element of invokeAll(c) throws exception on failed task
      */
     public void testInvokeAll4() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new NPETask());
             List<Future<String>> futures = e.invokeAll(l);
@@ -370,6 +382,8 @@
             } catch (ExecutionException success) {
                 assertTrue(success.getCause() instanceof NullPointerException);
             }
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -377,8 +391,8 @@
      * invokeAll(c) returns results of all completed tasks in c
      */
     public void testInvokeAll5() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -386,6 +400,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -393,12 +409,13 @@
      * timed invokeAny(null) throws NPE
      */
     public void testTimedInvokeAny1() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -406,14 +423,15 @@
      * timed invokeAny(null time unit) throws NPE
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -421,13 +439,13 @@
      * timed invokeAny(empty collection) throws IAE
      */
     public void testTimedInvokeAny2() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(),
-                            MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -435,16 +453,17 @@
      * timed invokeAny(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAny3() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<Long>> l = new ArrayList<Callable<Long>>();
-            l.add(new Callable<Long>() {
-                      public Long call() { throw new ArithmeticException(); }});
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+        l.add(new Callable<Long>() {
+            public Long call() { throw new ArithmeticException(); }});
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -452,18 +471,16 @@
      * timed invokeAny(c) throws ExecutionException if no task completes
      */
     public void testTimedInvokeAny4() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -471,15 +488,15 @@
      * timed invokeAny(c) returns result of some task in c
      */
     public void testTimedInvokeAny5() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -487,12 +504,13 @@
      * timed invokeAll(null) throws NPE
      */
     public void testTimedInvokeAll1() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -500,14 +518,15 @@
      * timed invokeAll(null time unit) throws NPE
      */
     public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -515,10 +534,12 @@
      * timed invokeAll(empty collection) returns empty collection
      */
     public void testTimedInvokeAll2() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -526,15 +547,16 @@
      * timed invokeAll(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAll3() throws InterruptedException {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new DirectExecutorService();
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -542,12 +564,12 @@
      * get of returned element of invokeAll(c) throws exception on failed task
      */
     public void testTimedInvokeAll4() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new NPETask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(1, futures.size());
             try {
                 futures.get(0).get();
@@ -555,6 +577,8 @@
             } catch (ExecutionException success) {
                 assertTrue(success.getCause() instanceof NullPointerException);
             }
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -562,51 +586,41 @@
      * timed invokeAll(c) returns results of all completed tasks in c
      */
     public void testTimedInvokeAll5() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new DirectExecutorService();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
     /**
      * timed invokeAll cancels tasks not completed by timeout
      */
-    public void testTimedInvokeAll6() throws Exception {
-        final ExecutorService e = new DirectExecutorService();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            for (long timeout = timeoutMillis();;) {
-                List<Callable<String>> tasks = new ArrayList<>();
-                tasks.add(new StringTask("0"));
-                tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout),
-                                             TEST_STRING));
-                tasks.add(new StringTask("2"));
-                long startTime = System.nanoTime();
-                List<Future<String>> futures =
-                    e.invokeAll(tasks, timeout, MILLISECONDS);
-                assertEquals(tasks.size(), futures.size());
-                assertTrue(millisElapsedSince(startTime) >= timeout);
-                for (Future future : futures)
-                    assertTrue(future.isDone());
-                try {
-                    assertEquals("0", futures.get(0).get());
-                    assertEquals(TEST_STRING, futures.get(1).get());
-                } catch (CancellationException retryWithLongerTimeout) {
-                    // unusual delay before starting second task
-                    timeout *= 2;
-                    if (timeout >= LONG_DELAY_MS / 2)
-                        fail("expected exactly one task to be cancelled");
-                    continue;
-                }
-                assertTrue(futures.get(2).isCancelled());
-                break;
-            }
+    public void testTimedInvokeAll6() throws InterruptedException {
+        ExecutorService e = new DirectExecutorService();
+        try {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(Executors.callable(possiblyInterruptedRunnable(2 * SHORT_DELAY_MS), TEST_STRING));
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+            assertEquals(l.size(), futures.size());
+            for (Future future : futures)
+                assertTrue(future.isDone());
+            assertFalse(futures.get(0).isCancelled());
+            assertFalse(futures.get(1).isCancelled());
+            assertTrue(futures.get(2).isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/AbstractQueueTest.java b/jsr166-tests/src/test/java/jsr166/AbstractQueueTest.java
index bf25668..2aa7326 100644
--- a/jsr166-tests/src/test/java/jsr166/AbstractQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AbstractQueueTest.java
@@ -24,7 +24,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AbstractQueueTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class Succeed extends AbstractQueue<Integer> {
@@ -158,7 +158,7 @@
     public void testAddAll3() {
         Succeed q = new Succeed();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         try {
             q.addAll(Arrays.asList(ints));
diff --git a/jsr166-tests/src/test/java/jsr166/AbstractQueuedLongSynchronizerTest.java b/jsr166-tests/src/test/java/jsr166/AbstractQueuedLongSynchronizerTest.java
index c462c73..8604d86 100644
--- a/jsr166-tests/src/test/java/jsr166/AbstractQueuedLongSynchronizerTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AbstractQueuedLongSynchronizerTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -241,33 +241,25 @@
      */
     void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
         long timeoutMillis = timeoutMillis();
-        long startTime;
+        long startTime = System.nanoTime();
         try {
             switch (awaitMethod) {
             case awaitTimed:
-                startTime = System.nanoTime();
                 assertFalse(c.await(timeoutMillis, MILLISECONDS));
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
                 break;
             case awaitNanos:
-                startTime = System.nanoTime();
                 long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
                 long nanosRemaining = c.awaitNanos(nanosTimeout);
                 assertTrue(nanosRemaining <= 0);
-                assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
                 break;
             case awaitUntil:
-                // We shouldn't assume that nanoTime and currentTimeMillis
-                // use the same time source, so don't use nanoTime here.
-                java.util.Date delayedDate = delayedDate(timeoutMillis());
                 assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
-                assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
                 break;
             default:
                 throw new UnsupportedOperationException();
             }
         } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
     }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/AbstractQueuedSynchronizerTest.java b/jsr166-tests/src/test/java/jsr166/AbstractQueuedSynchronizerTest.java
index d102fc6..b3c4110 100644
--- a/jsr166-tests/src/test/java/jsr166/AbstractQueuedSynchronizerTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AbstractQueuedSynchronizerTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AbstractQueuedSynchronizerTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -244,33 +244,25 @@
      */
     void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
         long timeoutMillis = timeoutMillis();
-        long startTime;
+        long startTime = System.nanoTime();
         try {
             switch (awaitMethod) {
             case awaitTimed:
-                startTime = System.nanoTime();
                 assertFalse(c.await(timeoutMillis, MILLISECONDS));
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
                 break;
             case awaitNanos:
-                startTime = System.nanoTime();
                 long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
                 long nanosRemaining = c.awaitNanos(nanosTimeout);
                 assertTrue(nanosRemaining <= 0);
-                assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
                 break;
             case awaitUntil:
-                // We shouldn't assume that nanoTime and currentTimeMillis
-                // use the same time source, so don't use nanoTime here.
-                java.util.Date delayedDate = delayedDate(timeoutMillis());
                 assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
-                assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
                 break;
             default:
                 throw new UnsupportedOperationException();
             }
         } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
     }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/ArrayBlockingQueueTest.java b/jsr166-tests/src/test/java/jsr166/ArrayBlockingQueueTest.java
index 902ae40..247c90e 100644
--- a/jsr166-tests/src/test/java/jsr166/ArrayBlockingQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ArrayBlockingQueueTest.java
@@ -26,7 +26,7 @@
 
 public class ArrayBlockingQueueTest extends JSR166TestCase {
 
-    // android-note: These tests have been moved into their own separate
+    // android-note: These tests have been moved into their own separate 
     // classes to work around CTS issues.
     //
     // public static class Fair extends BlockingQueueTest {
@@ -34,19 +34,17 @@
     //         return new ArrayBlockingQueue(SIZE, true);
     //     }
     // }
-
+    //
     // public static class NonFair extends BlockingQueueTest {
     //     protected BlockingQueue emptyCollection() {
     //         return new ArrayBlockingQueue(SIZE, false);
     //     }
     // }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(ArrayBlockingQueueTest.class,
     //                         new Fair().testSuite(),
@@ -111,7 +109,7 @@
      */
     public void testConstructor5() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = i;
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -173,7 +171,7 @@
             assertEquals(i, q.remove());
         }
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.remainingCapacity());
+            assertEquals(SIZE-i, q.remainingCapacity());
             assertEquals(SIZE, q.size() + q.remainingCapacity());
             assertTrue(q.add(i));
         }
@@ -221,7 +219,7 @@
     public void testAddAll3() {
         ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         try {
             q.addAll(Arrays.asList(ints));
@@ -458,23 +456,25 @@
         final CountDownLatch aboutToWait = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
                 }
+                long t0 = System.nanoTime();
                 aboutToWait.countDown();
                 try {
-                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    q.poll(MEDIUM_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                    assertTrue(millisElapsedSince(t0) < MEDIUM_DELAY_MS);
                 }
             }});
 
-        await(aboutToWait);
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        aboutToWait.await();
+        waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
         t.interrupt();
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         checkEmpty(q);
     }
 
@@ -577,7 +577,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -590,7 +590,7 @@
             ArrayBlockingQueue q = populatedQueue(SIZE);
             ArrayBlockingQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -624,23 +624,23 @@
             checkToArray(q);
             assertEquals(i, q.poll());
             checkToArray(q);
-            q.add(SIZE + i);
+            q.add(SIZE+i);
         }
         for (int i = 0; i < SIZE; i++) {
             checkToArray(q);
-            assertEquals(SIZE + i, q.poll());
+            assertEquals(SIZE+i, q.poll());
         }
     }
 
     void checkToArray2(ArrayBlockingQueue q) {
         int size = q.size();
-        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
+        Integer[] a1 = size == 0 ? null : new Integer[size-1];
         Integer[] a2 = new Integer[size];
-        Integer[] a3 = new Integer[size + 2];
+        Integer[] a3 = new Integer[size+2];
         if (size > 0) Arrays.fill(a1, 42);
         Arrays.fill(a2, 42);
         Arrays.fill(a3, 42);
-        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
+        Integer[] b1 = size == 0 ? null : (Integer[]) q.toArray(a1);
         Integer[] b2 = (Integer[]) q.toArray(a2);
         Integer[] b3 = (Integer[]) q.toArray(a3);
         assertSame(a2, b2);
@@ -654,7 +654,7 @@
             assertSame(b3[i], x);
         }
         assertNull(a3[size]);
-        assertEquals(42, (int) a3[size + 1]);
+        assertEquals(42, (int) a3[size+1]);
         if (size > 0) {
             assertNotSame(a1, b1);
             assertEquals(size, b1.length);
@@ -678,11 +678,11 @@
             checkToArray2(q);
             assertEquals(i, q.poll());
             checkToArray2(q);
-            q.add(SIZE + i);
+            q.add(SIZE+i);
         }
         for (int i = 0; i < SIZE; i++) {
             checkToArray2(q);
-            assertEquals(SIZE + i, q.poll());
+            assertEquals(SIZE+i, q.poll());
         }
     }
 
@@ -793,24 +793,24 @@
         final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
         q.add(one);
         q.add(two);
+        ExecutorService executor = Executors.newFixedThreadPool(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertFalse(q.offer(three));
-                    threadsStarted.await();
-                    assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
-                    assertEquals(0, q.remainingCapacity());
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(q.offer(three));
+                threadsStarted.await();
+                assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
+                assertEquals(0, q.remainingCapacity());
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    assertEquals(0, q.remainingCapacity());
-                    assertSame(one, q.take());
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertEquals(0, q.remainingCapacity());
+                assertSame(one, q.take());
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -819,22 +819,22 @@
     public void testPollInExecutor() {
         final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    checkEmpty(q);
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -886,7 +886,7 @@
         final ArrayBlockingQueue q = populatedQueue(SIZE);
         Thread t = new Thread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                q.put(new Integer(SIZE + 1));
+                q.put(new Integer(SIZE+1));
             }});
 
         t.start();
@@ -903,7 +903,7 @@
      * drainTo(c, n) empties first min(n, size) elements of queue into c
      */
     public void testDrainToN() {
-        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE * 2);
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE*2);
         for (int i = 0; i < SIZE + 2; ++i) {
             for (int j = 0; j < SIZE; j++)
                 assertTrue(q.offer(new Integer(j)));
@@ -911,7 +911,7 @@
             q.drainTo(l, i);
             int k = (i < SIZE) ? i : SIZE;
             assertEquals(k, l.size());
-            assertEquals(SIZE - k, q.size());
+            assertEquals(SIZE-k, q.size());
             for (int j = 0; j < k; ++j)
                 assertEquals(l.get(j), new Integer(j));
             do {} while (q.poll() != null);
diff --git a/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java b/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
index 23cc6b9..16290e9 100644
--- a/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
@@ -26,7 +26,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ArrayDequeTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -65,7 +65,8 @@
      */
     public void testConstructor4() {
         try {
-            new ArrayDeque(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new ArrayDeque(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -74,10 +75,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new ArrayDeque(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -115,7 +116,7 @@
     public void testSize() {
         ArrayDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.removeFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -128,8 +129,8 @@
      * push(null) throws NPE
      */
     public void testPushNull() {
-        ArrayDeque q = new ArrayDeque(1);
         try {
+            ArrayDeque q = new ArrayDeque(1);
             q.push(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -163,8 +164,8 @@
      * offer(null) throws NPE
      */
     public void testOfferNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.offer(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -174,8 +175,8 @@
      * offerFirst(null) throws NPE
      */
     public void testOfferFirstNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.offerFirst(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -185,8 +186,8 @@
      * offerLast(null) throws NPE
      */
     public void testOfferLastNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.offerLast(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -229,8 +230,8 @@
      * add(null) throws NPE
      */
     public void testAddNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.add(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -240,8 +241,8 @@
      * addFirst(null) throws NPE
      */
     public void testAddFirstNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.addFirst(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -251,8 +252,8 @@
      * addLast(null) throws NPE
      */
     public void testAddLastNull() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.addLast(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -295,8 +296,8 @@
      * addAll(null) throws NPE
      */
     public void testAddAll1() {
-        ArrayDeque q = new ArrayDeque();
         try {
+            ArrayDeque q = new ArrayDeque();
             q.addAll(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -306,9 +307,10 @@
      * addAll of a collection with null elements throws NPE
      */
     public void testAddAll2() {
-        ArrayDeque q = new ArrayDeque();
         try {
-            q.addAll(Arrays.asList(new Integer[SIZE]));
+            ArrayDeque q = new ArrayDeque();
+            Integer[] ints = new Integer[SIZE];
+            q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -318,11 +320,11 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        ArrayDeque q = new ArrayDeque();
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            ArrayDeque q = new ArrayDeque();
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -359,7 +361,7 @@
      */
     public void testPollLast() {
         ArrayDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollLast());
@@ -399,14 +401,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -444,7 +446,7 @@
      */
     public void testPeekLast() {
         ArrayDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.peekLast());
             assertEquals(i, q.pollLast());
             assertTrue(q.peekLast() == null ||
@@ -488,7 +490,7 @@
      */
     public void testLastElement() {
         ArrayDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.getLast());
             assertEquals(i, q.pollLast());
         }
@@ -539,7 +541,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeFirstOccurrence(new Integer(i)));
-            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -554,7 +556,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeLastOccurrence(new Integer(i)));
-            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeLastOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -609,7 +611,7 @@
             boolean changed = q.retainAll(p);
             assertEquals(changed, (i > 0));
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.removeFirst();
         }
     }
@@ -622,7 +624,7 @@
             ArrayDeque q = populatedDeque(SIZE);
             ArrayDeque p = populatedDeque(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 assertFalse(q.contains(p.removeFirst()));
             }
@@ -654,23 +656,23 @@
         for (int i = 0; i < SIZE; i++) {
             checkToArray(q);
             assertEquals(i, q.poll());
-            q.addLast(SIZE + i);
+            q.addLast(SIZE+i);
         }
         for (int i = 0; i < SIZE; i++) {
             checkToArray(q);
-            assertEquals(SIZE + i, q.poll());
+            assertEquals(SIZE+i, q.poll());
         }
     }
 
     void checkToArray2(ArrayDeque q) {
         int size = q.size();
-        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
+        Integer[] a1 = size == 0 ? null : new Integer[size-1];
         Integer[] a2 = new Integer[size];
-        Integer[] a3 = new Integer[size + 2];
+        Integer[] a3 = new Integer[size+2];
         if (size > 0) Arrays.fill(a1, 42);
         Arrays.fill(a2, 42);
         Arrays.fill(a3, 42);
-        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
+        Integer[] b1 = size == 0 ? null : (Integer[]) q.toArray(a1);
         Integer[] b2 = (Integer[]) q.toArray(a2);
         Integer[] b3 = (Integer[]) q.toArray(a3);
         assertSame(a2, b2);
@@ -684,7 +686,7 @@
             assertSame(b3[i], x);
         }
         assertNull(a3[size]);
-        assertEquals(42, (int) a3[size + 1]);
+        assertEquals(42, (int) a3[size+1]);
         if (size > 0) {
             assertNotSame(a1, b1);
             assertEquals(size, b1.length);
@@ -707,11 +709,11 @@
         for (int i = 0; i < SIZE; i++) {
             checkToArray2(q);
             assertEquals(i, q.poll());
-            q.addLast(SIZE + i);
+            q.addLast(SIZE+i);
         }
         for (int i = 0; i < SIZE; i++) {
             checkToArray2(q);
-            assertEquals(SIZE + i, q.poll());
+            assertEquals(SIZE+i, q.poll());
         }
     }
 
@@ -785,18 +787,18 @@
         final Random rng = new Random();
         for (int iters = 0; iters < 100; ++iters) {
             int max = rng.nextInt(5) + 2;
-            int split = rng.nextInt(max - 1) + 1;
+            int split = rng.nextInt(max-1) + 1;
             for (int j = 1; j <= max; ++j)
                 q.add(new Integer(j));
             Iterator it = q.iterator();
             for (int j = 1; j <= split; ++j)
                 assertEquals(it.next(), new Integer(j));
             it.remove();
-            assertEquals(it.next(), new Integer(split + 1));
+            assertEquals(it.next(), new Integer(split+1));
             for (int j = 1; j <= split; ++j)
                 q.remove(new Integer(j));
             it = q.iterator();
-            for (int j = split + 1; j <= max; ++j) {
+            for (int j = split+1; j <= max; ++j) {
                 assertEquals(it.next(), new Integer(j));
                 it.remove();
             }
@@ -853,18 +855,18 @@
         final Random rng = new Random();
         for (int iters = 0; iters < 100; ++iters) {
             int max = rng.nextInt(5) + 2;
-            int split = rng.nextInt(max - 1) + 1;
+            int split = rng.nextInt(max-1) + 1;
             for (int j = max; j >= 1; --j)
                 q.add(new Integer(j));
             Iterator it = q.descendingIterator();
             for (int j = 1; j <= split; ++j)
                 assertEquals(it.next(), new Integer(j));
             it.remove();
-            assertEquals(it.next(), new Integer(split + 1));
+            assertEquals(it.next(), new Integer(split+1));
             for (int j = 1; j <= split; ++j)
                 q.remove(new Integer(j));
             it = q.descendingIterator();
-            for (int j = split + 1; j <= max; ++j) {
+            for (int j = split+1; j <= max; ++j) {
                 assertEquals(it.next(), new Integer(j));
                 it.remove();
             }
diff --git a/jsr166-tests/src/test/java/jsr166/Atomic8Test.java b/jsr166-tests/src/test/java/jsr166/Atomic8Test.java
deleted file mode 100644
index f81c44f..0000000
--- a/jsr166-tests/src/test/java/jsr166/Atomic8Test.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicIntegerArray;
-import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicLongArray;
-import java.util.concurrent.atomic.AtomicLongFieldUpdater;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.atomic.AtomicReferenceArray;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class Atomic8Test extends JSR166TestCase {
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(Atomic8Test.class);
-    // }
-
-    /*
-     * Tests of atomic class methods accepting lambdas
-     * introduced in JDK8.
-     */
-
-    static long addLong17(long x) { return x + 17; }
-    static int addInt17(int x) { return x + 17; }
-    static Integer addInteger17(Integer x) {
-        return new Integer(x.intValue() + 17);
-    }
-    static Integer sumInteger(Integer x, Integer y) {
-        return new Integer(x.intValue() + y.intValue());
-    }
-
-    volatile long aLongField;
-    volatile int anIntField;
-    volatile Integer anIntegerField;
-
-    AtomicLongFieldUpdater aLongFieldUpdater() {
-        return AtomicLongFieldUpdater.newUpdater
-            (Atomic8Test.class, "aLongField");
-    }
-
-    AtomicIntegerFieldUpdater anIntFieldUpdater() {
-        return AtomicIntegerFieldUpdater.newUpdater
-            (Atomic8Test.class, "anIntField");
-    }
-
-    AtomicReferenceFieldUpdater<Atomic8Test,Integer> anIntegerFieldUpdater() {
-        return AtomicReferenceFieldUpdater.newUpdater
-            (Atomic8Test.class, Integer.class, "anIntegerField");
-    }
-
-    /**
-     * AtomicLong getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testLongGetAndUpdate() {
-        AtomicLong a = new AtomicLong(1L);
-        assertEquals(1L, a.getAndUpdate(Atomic8Test::addLong17));
-        assertEquals(18L, a.getAndUpdate(Atomic8Test::addLong17));
-        assertEquals(35L, a.get());
-    }
-
-    /**
-     * AtomicLong updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testLongUpdateAndGet() {
-        AtomicLong a = new AtomicLong(1L);
-        assertEquals(18L, a.updateAndGet(Atomic8Test::addLong17));
-        assertEquals(35L, a.updateAndGet(Atomic8Test::addLong17));
-    }
-
-    /**
-     * AtomicLong getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testLongGetAndAccumulate() {
-        AtomicLong a = new AtomicLong(1L);
-        assertEquals(1L, a.getAndAccumulate(2L, Long::sum));
-        assertEquals(3L, a.getAndAccumulate(3L, Long::sum));
-        assertEquals(6L, a.get());
-    }
-
-    /**
-     * AtomicLong accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testLongAccumulateAndGet() {
-        AtomicLong a = new AtomicLong(1L);
-        assertEquals(7L, a.accumulateAndGet(6L, Long::sum));
-        assertEquals(10L, a.accumulateAndGet(3L, Long::sum));
-        assertEquals(10L, a.get());
-    }
-
-    /**
-     * AtomicInteger getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testIntGetAndUpdate() {
-        AtomicInteger a = new AtomicInteger(1);
-        assertEquals(1, a.getAndUpdate(Atomic8Test::addInt17));
-        assertEquals(18, a.getAndUpdate(Atomic8Test::addInt17));
-        assertEquals(35, a.get());
-    }
-
-    /**
-     * AtomicInteger updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testIntUpdateAndGet() {
-        AtomicInteger a = new AtomicInteger(1);
-        assertEquals(18, a.updateAndGet(Atomic8Test::addInt17));
-        assertEquals(35, a.updateAndGet(Atomic8Test::addInt17));
-        assertEquals(35, a.get());
-    }
-
-    /**
-     * AtomicInteger getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testIntGetAndAccumulate() {
-        AtomicInteger a = new AtomicInteger(1);
-        assertEquals(1, a.getAndAccumulate(2, Integer::sum));
-        assertEquals(3, a.getAndAccumulate(3, Integer::sum));
-        assertEquals(6, a.get());
-    }
-
-    /**
-     * AtomicInteger accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testIntAccumulateAndGet() {
-        AtomicInteger a = new AtomicInteger(1);
-        assertEquals(7, a.accumulateAndGet(6, Integer::sum));
-        assertEquals(10, a.accumulateAndGet(3, Integer::sum));
-        assertEquals(10, a.get());
-    }
-
-    /**
-     * AtomicReference getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testReferenceGetAndUpdate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
-        assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get());
-    }
-
-    /**
-     * AtomicReference updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testReferenceUpdateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
-        assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get());
-    }
-
-    /**
-     * AtomicReference getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testReferenceGetAndAccumulate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
-        assertEquals(new Integer(1), a.getAndAccumulate(2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get());
-    }
-
-    /**
-     * AtomicReference accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testReferenceAccumulateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
-        assertEquals(new Integer(7), a.accumulateAndGet(6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.get());
-    }
-
-    /**
-     * AtomicLongArray getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testLongArrayGetAndUpdate() {
-        AtomicLongArray a = new AtomicLongArray(1);
-        a.set(0, 1);
-        assertEquals(1L, a.getAndUpdate(0, Atomic8Test::addLong17));
-        assertEquals(18L, a.getAndUpdate(0, Atomic8Test::addLong17));
-        assertEquals(35L, a.get(0));
-    }
-
-    /**
-     * AtomicLongArray updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testLongArrayUpdateAndGet() {
-        AtomicLongArray a = new AtomicLongArray(1);
-        a.set(0, 1);
-        assertEquals(18L, a.updateAndGet(0, Atomic8Test::addLong17));
-        assertEquals(35L, a.updateAndGet(0, Atomic8Test::addLong17));
-        assertEquals(35L, a.get(0));
-    }
-
-    /**
-     * AtomicLongArray getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testLongArrayGetAndAccumulate() {
-        AtomicLongArray a = new AtomicLongArray(1);
-        a.set(0, 1);
-        assertEquals(1L, a.getAndAccumulate(0, 2L, Long::sum));
-        assertEquals(3L, a.getAndAccumulate(0, 3L, Long::sum));
-        assertEquals(6L, a.get(0));
-    }
-
-    /**
-     * AtomicLongArray accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testLongArrayAccumulateAndGet() {
-        AtomicLongArray a = new AtomicLongArray(1);
-        a.set(0, 1);
-        assertEquals(7L, a.accumulateAndGet(0, 6L, Long::sum));
-        assertEquals(10L, a.accumulateAndGet(0, 3L, Long::sum));
-        assertEquals(10L, a.get(0));
-    }
-
-    /**
-     * AtomicIntegerArray getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testIntArrayGetAndUpdate() {
-        AtomicIntegerArray a = new AtomicIntegerArray(1);
-        a.set(0, 1);
-        assertEquals(1, a.getAndUpdate(0, Atomic8Test::addInt17));
-        assertEquals(18, a.getAndUpdate(0, Atomic8Test::addInt17));
-        assertEquals(35, a.get(0));
-    }
-
-    /**
-     * AtomicIntegerArray updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testIntArrayUpdateAndGet() {
-        AtomicIntegerArray a = new AtomicIntegerArray(1);
-        a.set(0, 1);
-        assertEquals(18, a.updateAndGet(0, Atomic8Test::addInt17));
-        assertEquals(35, a.updateAndGet(0, Atomic8Test::addInt17));
-        assertEquals(35, a.get(0));
-    }
-
-    /**
-     * AtomicIntegerArray getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testIntArrayGetAndAccumulate() {
-        AtomicIntegerArray a = new AtomicIntegerArray(1);
-        a.set(0, 1);
-        assertEquals(1, a.getAndAccumulate(0, 2, Integer::sum));
-        assertEquals(3, a.getAndAccumulate(0, 3, Integer::sum));
-        assertEquals(6, a.get(0));
-    }
-
-    /**
-     * AtomicIntegerArray accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testIntArrayAccumulateAndGet() {
-        AtomicIntegerArray a = new AtomicIntegerArray(1);
-        a.set(0, 1);
-        assertEquals(7, a.accumulateAndGet(0, 6, Integer::sum));
-        assertEquals(10, a.accumulateAndGet(0, 3, Integer::sum));
-    }
-
-    /**
-     * AtomicReferenceArray getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testReferenceArrayGetAndUpdate() {
-        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
-        a.set(0, one);
-        assertEquals(new Integer(1), a.getAndUpdate(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(0));
-    }
-
-    /**
-     * AtomicReferenceArray updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testReferenceArrayUpdateAndGet() {
-        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
-        a.set(0, one);
-        assertEquals(new Integer(18), a.updateAndGet(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(0, Atomic8Test::addInteger17));
-    }
-
-    /**
-     * AtomicReferenceArray getAndAccumulate returns previous value and updates
-     * with supplied function.
-     */
-    public void testReferenceArrayGetAndAccumulate() {
-        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
-        a.set(0, one);
-        assertEquals(new Integer(1), a.getAndAccumulate(0, 2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(0, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get(0));
-    }
-
-    /**
-     * AtomicReferenceArray accumulateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testReferenceArrayAccumulateAndGet() {
-        AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
-        a.set(0, one);
-        assertEquals(new Integer(7), a.accumulateAndGet(0, 6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(0, 3, Atomic8Test::sumInteger));
-    }
-
-    /**
-     * AtomicLongFieldUpdater getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testLongFieldUpdaterGetAndUpdate() {
-        AtomicLongFieldUpdater a = aLongFieldUpdater();
-        a.set(this, 1);
-        assertEquals(1L, a.getAndUpdate(this, Atomic8Test::addLong17));
-        assertEquals(18L, a.getAndUpdate(this, Atomic8Test::addLong17));
-        assertEquals(35L, a.get(this));
-        assertEquals(35L, aLongField);
-    }
-
-    /**
-     * AtomicLongFieldUpdater updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testLongFieldUpdaterUpdateAndGet() {
-        AtomicLongFieldUpdater a = aLongFieldUpdater();
-        a.set(this, 1);
-        assertEquals(18L, a.updateAndGet(this, Atomic8Test::addLong17));
-        assertEquals(35L, a.updateAndGet(this, Atomic8Test::addLong17));
-        assertEquals(35L, a.get(this));
-        assertEquals(35L, aLongField);
-    }
-
-    /**
-     * AtomicLongFieldUpdater getAndAccumulate returns previous value
-     * and updates with supplied function.
-     */
-    public void testLongFieldUpdaterGetAndAccumulate() {
-        AtomicLongFieldUpdater a = aLongFieldUpdater();
-        a.set(this, 1);
-        assertEquals(1L, a.getAndAccumulate(this, 2L, Long::sum));
-        assertEquals(3L, a.getAndAccumulate(this, 3L, Long::sum));
-        assertEquals(6L, a.get(this));
-        assertEquals(6L, aLongField);
-    }
-
-    /**
-     * AtomicLongFieldUpdater accumulateAndGet updates with supplied
-     * function and returns result.
-     */
-    public void testLongFieldUpdaterAccumulateAndGet() {
-        AtomicLongFieldUpdater a = aLongFieldUpdater();
-        a.set(this, 1);
-        assertEquals(7L, a.accumulateAndGet(this, 6L, Long::sum));
-        assertEquals(10L, a.accumulateAndGet(this, 3L, Long::sum));
-        assertEquals(10L, a.get(this));
-        assertEquals(10L, aLongField);
-    }
-
-    /**
-     * AtomicIntegerFieldUpdater getAndUpdate returns previous value and updates
-     * result of supplied function
-     */
-    public void testIntegerFieldUpdaterGetAndUpdate() {
-        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
-        a.set(this, 1);
-        assertEquals(1, a.getAndUpdate(this, Atomic8Test::addInt17));
-        assertEquals(18, a.getAndUpdate(this, Atomic8Test::addInt17));
-        assertEquals(35, a.get(this));
-        assertEquals(35, anIntField);
-    }
-
-    /**
-     * AtomicIntegerFieldUpdater updateAndGet updates with supplied function and
-     * returns result.
-     */
-    public void testIntegerFieldUpdaterUpdateAndGet() {
-        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
-        a.set(this, 1);
-        assertEquals(18, a.updateAndGet(this, Atomic8Test::addInt17));
-        assertEquals(35, a.updateAndGet(this, Atomic8Test::addInt17));
-        assertEquals(35, a.get(this));
-        assertEquals(35, anIntField);
-    }
-
-    /**
-     * AtomicIntegerFieldUpdater getAndAccumulate returns previous value
-     * and updates with supplied function.
-     */
-    public void testIntegerFieldUpdaterGetAndAccumulate() {
-        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
-        a.set(this, 1);
-        assertEquals(1, a.getAndAccumulate(this, 2, Integer::sum));
-        assertEquals(3, a.getAndAccumulate(this, 3, Integer::sum));
-        assertEquals(6, a.get(this));
-        assertEquals(6, anIntField);
-    }
-
-    /**
-     * AtomicIntegerFieldUpdater accumulateAndGet updates with supplied
-     * function and returns result.
-     */
-    public void testIntegerFieldUpdaterAccumulateAndGet() {
-        AtomicIntegerFieldUpdater a = anIntFieldUpdater();
-        a.set(this, 1);
-        assertEquals(7, a.accumulateAndGet(this, 6, Integer::sum));
-        assertEquals(10, a.accumulateAndGet(this, 3, Integer::sum));
-        assertEquals(10, a.get(this));
-        assertEquals(10, anIntField);
-    }
-
-    /**
-     * AtomicReferenceFieldUpdater getAndUpdate returns previous value
-     * and updates result of supplied function
-     */
-    public void testReferenceFieldUpdaterGetAndUpdate() {
-        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
-        a.set(this, one);
-        assertEquals(new Integer(1), a.getAndUpdate(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(this));
-        assertEquals(new Integer(35), anIntegerField);
-    }
-
-    /**
-     * AtomicReferenceFieldUpdater updateAndGet updates with supplied
-     * function and returns result.
-     */
-    public void testReferenceFieldUpdaterUpdateAndGet() {
-        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
-        a.set(this, one);
-        assertEquals(new Integer(18), a.updateAndGet(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(this));
-        assertEquals(new Integer(35), anIntegerField);
-    }
-
-    /**
-     * AtomicReferenceFieldUpdater returns previous value and updates
-     * with supplied function.
-     */
-    public void testReferenceFieldUpdaterGetAndAccumulate() {
-        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
-        a.set(this, one);
-        assertEquals(new Integer(1), a.getAndAccumulate(this, 2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(this, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get(this));
-        assertEquals(new Integer(6), anIntegerField);
-    }
-
-    /**
-     * AtomicReferenceFieldUpdater accumulateAndGet updates with
-     * supplied function and returns result.
-     */
-    public void testReferenceFieldUpdaterAccumulateAndGet() {
-        AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
-        a.set(this, one);
-        assertEquals(new Integer(7), a.accumulateAndGet(this, 6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(this, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.get(this));
-        assertEquals(new Integer(10), anIntegerField);
-    }
-
-    /**
-     * All Atomic getAndUpdate methods throw NullPointerException on
-     * null function argument
-     */
-    public void testGetAndUpdateNPE() {
-        Runnable[] throwingActions = {
-            () -> new AtomicLong().getAndUpdate(null),
-            () -> new AtomicInteger().getAndUpdate(null),
-            () -> new AtomicReference().getAndUpdate(null),
-            () -> new AtomicLongArray(1).getAndUpdate(0, null),
-            () -> new AtomicIntegerArray(1).getAndUpdate(0, null),
-            () -> new AtomicReferenceArray(1).getAndUpdate(0, null),
-            () -> aLongFieldUpdater().getAndUpdate(this, null),
-            () -> anIntFieldUpdater().getAndUpdate(this, null),
-            () -> anIntegerFieldUpdater().getAndUpdate(this, null),
-            ////() -> aLongFieldUpdater().getAndUpdate(null, Atomic8Test::addLong17),
-            ////() -> anIntFieldUpdater().getAndUpdate(null, Atomic8Test::addInt17),
-            ////() -> anIntegerFieldUpdater().getAndUpdate(null, Atomic8Test::addInteger17),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
-    }
-
-    /**
-     * All Atomic updateAndGet methods throw NullPointerException on null function argument
-     */
-    public void testUpdateAndGetNPE() {
-        Runnable[] throwingActions = {
-            () -> new AtomicLong().updateAndGet(null),
-            () -> new AtomicInteger().updateAndGet(null),
-            () -> new AtomicReference().updateAndGet(null),
-            () -> new AtomicLongArray(1).updateAndGet(0, null),
-            () -> new AtomicIntegerArray(1).updateAndGet(0, null),
-            () -> new AtomicReferenceArray(1).updateAndGet(0, null),
-            () -> aLongFieldUpdater().updateAndGet(this, null),
-            () -> anIntFieldUpdater().updateAndGet(this, null),
-            () -> anIntegerFieldUpdater().updateAndGet(this, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
-    }
-
-    /**
-     * All Atomic getAndAccumulate methods throw NullPointerException
-     * on null function argument
-     */
-    public void testGetAndAccumulateNPE() {
-        Runnable[] throwingActions = {
-            () -> new AtomicLong().getAndAccumulate(1L, null),
-            () -> new AtomicInteger().getAndAccumulate(1, null),
-            () -> new AtomicReference().getAndAccumulate(one, null),
-            () -> new AtomicLongArray(1).getAndAccumulate(0, 1L, null),
-            () -> new AtomicIntegerArray(1).getAndAccumulate(0, 1, null),
-            () -> new AtomicReferenceArray(1).getAndAccumulate(0, one, null),
-            () -> aLongFieldUpdater().getAndAccumulate(this, 1L, null),
-            () -> anIntFieldUpdater().getAndAccumulate(this, 1, null),
-            () -> anIntegerFieldUpdater().getAndAccumulate(this, one, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
-    }
-
-    /**
-     * All Atomic accumulateAndGet methods throw NullPointerException
-     * on null function argument
-     */
-    public void testAccumulateAndGetNPE() {
-        Runnable[] throwingActions = {
-            () -> new AtomicLong().accumulateAndGet(1L, null),
-            () -> new AtomicInteger().accumulateAndGet(1, null),
-            () -> new AtomicReference().accumulateAndGet(one, null),
-            () -> new AtomicLongArray(1).accumulateAndGet(0, 1L, null),
-            () -> new AtomicIntegerArray(1).accumulateAndGet(0, 1, null),
-            () -> new AtomicReferenceArray(1).accumulateAndGet(0, one, null),
-            () -> aLongFieldUpdater().accumulateAndGet(this, 1L, null),
-            () -> anIntFieldUpdater().accumulateAndGet(this, 1, null),
-            () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicBooleanTest.java b/jsr166-tests/src/test/java/jsr166/AtomicBooleanTest.java
index 6f5decf..bfe3fc6 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicBooleanTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicBooleanTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicBooleanTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicIntegerArrayTest.java b/jsr166-tests/src/test/java/jsr166/AtomicIntegerArrayTest.java
index c9e32aa..670b9ce 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicIntegerArrayTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicIntegerArrayTest.java
@@ -15,7 +15,6 @@
 import junit.framework.TestSuite;
 
 public class AtomicIntegerArrayTest extends JSR166TestCase {
-
     // android-note: Removed because the CTS runner does a bad job of
     // retrying tests that have suite() declarations.
     //
@@ -23,7 +22,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicIntegerArrayTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -291,7 +290,7 @@
                     assertTrue(v >= 0);
                     if (v != 0) {
                         done = false;
-                        if (aa.compareAndSet(i, v, v - 1))
+                        if (aa.compareAndSet(i, v, v-1))
                             ++counts;
                     }
                 }
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
index c8d3856..ef75b46 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicIntegerFieldUpdaterTest.java
@@ -15,10 +15,8 @@
 
 public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
     volatile int x = 0;
-    protected volatile int protectedField;
-    private volatile int privateField;
     int w;
-    float z;
+    long z;
     // android-note: Removed because the CTS runner does a bad job of
     // retrying tests that have suite() declarations.
     //
@@ -26,59 +24,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicIntegerFieldUpdaterTest.class);
-    // }
-
-    // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //                 AtomicIntegerFieldUpdater.newUpdater
-    //                 (AtomicIntegerFieldUpdaterTest.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //             AtomicIntegerFieldUpdater.newUpdater
-    //             (AtomicIntegerFieldUpdaterTest.class, "protectedField");
-    //         this.protectedField = 1;
-    //         assertTrue(a.compareAndSet(this, 1, 2));
-    //         assertTrue(a.compareAndSet(this, 2, -4));
-    //         assertEquals(-4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, -5, 7));
-    //         assertEquals(-4, a.get(this));
-    //         assertTrue(a.compareAndSet(this, -4, 7));
-    //         assertEquals(7, a.get(this));
-    //     }
-    // }
-
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) {
-    //         obj.x = 72;
-    //         AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //             AtomicIntegerFieldUpdater.newUpdater
-    //             (AtomicIntegerFieldUpdaterTest.class, "x");
-    //         assertEquals(72, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, 72, 73));
-    //         assertEquals(73, a.get(obj));
-    //     }
-
-    //     public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
-    //                 AtomicIntegerFieldUpdater.newUpdater
-    //                 (AtomicIntegerFieldUpdaterTest.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
+    //     return new TestSuite(...);
     // }
 
     AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> updaterFor(String fieldName) {
@@ -119,26 +65,6 @@
     }
 
     /**
-     * construction using private field from subclass throws RuntimeException
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicIntegerFieldUpdaterTestSubclass s =
-    //         new AtomicIntegerFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
-
-    /**
-     * construction from unrelated class; package access is allowed,
-     * private access is not
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
-
-    /**
      * get returns the last value set or assigned
      */
     public void testGetSet() {
@@ -183,34 +109,6 @@
     }
 
     /**
-     * compareAndSet succeeds in changing protected field value if
-     * equal to expected else fails
-     */
-    public void testCompareAndSetProtected() {
-        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
-        a = updaterFor("protectedField");
-        protectedField = 1;
-        assertTrue(a.compareAndSet(this, 1, 2));
-        assertTrue(a.compareAndSet(this, 2, -4));
-        assertEquals(-4, a.get(this));
-        assertFalse(a.compareAndSet(this, -5, 7));
-        assertEquals(-4, a.get(this));
-        assertTrue(a.compareAndSet(this, -4, 7));
-        assertEquals(7, a.get(this));
-    }
-
-    /**
-     * compareAndSet succeeds in changing protected field value if
-     * equal to expected else fails
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testCompareAndSetProtectedInSubclass() {
-    //     AtomicIntegerFieldUpdaterTestSubclass s =
-    //         new AtomicIntegerFieldUpdaterTestSubclass();
-    //     s.checkCompareAndSetProtectedSub();
-    // }
-
-    /**
      * compareAndSet in one thread enables another waiting for value
      * to succeed
      */
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicIntegerTest.java b/jsr166-tests/src/test/java/jsr166/AtomicIntegerTest.java
index 6392c54..cf73810 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicIntegerTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicIntegerTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicIntegerTest.class);
+    //     return new TestSuite(...);
     // }
 
     final int[] VALUES = {
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicLongArrayTest.java b/jsr166-tests/src/test/java/jsr166/AtomicLongArrayTest.java
index a60ecfd..08df01e 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicLongArrayTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicLongArrayTest.java
@@ -22,7 +22,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicLongArrayTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -290,7 +290,7 @@
                     assertTrue(v >= 0);
                     if (v != 0) {
                         done = false;
-                        if (aa.compareAndSet(i, v, v - 1))
+                        if (aa.compareAndSet(i, v, v-1))
                             ++counts;
                     }
                 }
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
index d46280b..204f814 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicLongFieldUpdaterTest.java
@@ -15,10 +15,9 @@
 
 public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
     volatile long x = 0;
-    protected volatile long protectedField;
-    private volatile long privateField;
+    int z;
     long w;
-    float z;
+
     // android-note: Removed because the CTS runner does a bad job of
     // retrying tests that have suite() declarations.
     //
@@ -26,59 +25,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicLongFieldUpdaterTest.class);
-    // }
-
-    // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //                 AtomicLongFieldUpdater.newUpdater
-    //                 (AtomicLongFieldUpdaterTest.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //             AtomicLongFieldUpdater.newUpdater
-    //             (AtomicLongFieldUpdaterTest.class, "protectedField");
-    //         this.protectedField = 1;
-    //         assertTrue(a.compareAndSet(this, 1, 2));
-    //         assertTrue(a.compareAndSet(this, 2, -4));
-    //         assertEquals(-4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, -5, 7));
-    //         assertEquals(-4, a.get(this));
-    //         assertTrue(a.compareAndSet(this, -4, 7));
-    //         assertEquals(7, a.get(this));
-    //     }
-    // }
-
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
-    //         obj.x = 72L;
-    //         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //             AtomicLongFieldUpdater.newUpdater
-    //             (AtomicLongFieldUpdaterTest.class, "x");
-    //         assertEquals(72L, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, 72L, 73L));
-    //         assertEquals(73L, a.get(obj));
-    //     }
-
-    //     public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
-    //                 AtomicLongFieldUpdater.newUpdater
-    //                 (AtomicLongFieldUpdaterTest.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
+    //     return new TestSuite(...);
     // }
 
     AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> updaterFor(String fieldName) {
@@ -119,26 +66,6 @@
     }
 
     /**
-     * construction using private field from subclass throws RuntimeException
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicLongFieldUpdaterTestSubclass s =
-    //         new AtomicLongFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
-
-    /**
-     * construction from unrelated class; package access is allowed,
-     * private access is not
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
-
-    /**
      * get returns the last value set or assigned
      */
     public void testGetSet() {
@@ -183,34 +110,6 @@
     }
 
     /**
-     * compareAndSet succeeds in changing protected field value if
-     * equal to expected else fails
-     */
-    public void testCompareAndSetProtected() {
-        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
-        a = updaterFor("protectedField");
-        protectedField = 1;
-        assertTrue(a.compareAndSet(this, 1, 2));
-        assertTrue(a.compareAndSet(this, 2, -4));
-        assertEquals(-4, a.get(this));
-        assertFalse(a.compareAndSet(this, -5, 7));
-        assertEquals(-4, a.get(this));
-        assertTrue(a.compareAndSet(this, -4, 7));
-        assertEquals(7, a.get(this));
-    }
-
-    /**
-     * compareAndSet succeeds in changing protected field value if
-     * equal to expected else fails
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testCompareAndSetProtectedInSubclass() {
-    //     AtomicLongFieldUpdaterTestSubclass s =
-    //         new AtomicLongFieldUpdaterTestSubclass();
-    //     s.checkCompareAndSetProtectedSub();
-    // }
-
-    /**
      * compareAndSet in one thread enables another waiting for value
      * to succeed
      */
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicLongTest.java b/jsr166-tests/src/test/java/jsr166/AtomicLongTest.java
index a8ee7c6..b9c1722 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicLongTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicLongTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicLongTest.class);
+    //     return new TestSuite(...);
     // }
 
     final long[] VALUES = {
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicMarkableReferenceTest.java b/jsr166-tests/src/test/java/jsr166/AtomicMarkableReferenceTest.java
index bd4e8cb..61b6b1b 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicMarkableReferenceTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicMarkableReferenceTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicMarkableReferenceTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicReferenceArrayTest.java b/jsr166-tests/src/test/java/jsr166/AtomicReferenceArrayTest.java
index f3aab44..1df2f9f 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicReferenceArrayTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicReferenceArrayTest.java
@@ -22,7 +22,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicReferenceArrayTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java b/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
index 9b2e9a9..4b0d946 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicReferenceFieldUpdaterTest.java
@@ -15,8 +15,6 @@
 
 public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
     volatile Integer x = null;
-    protected volatile Integer protectedField;
-    private volatile Integer privateField;
     Object z;
     Integer w;
     volatile int i;
@@ -28,62 +26,10 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicReferenceFieldUpdaterTest.class);
+    //     return new TestSuite(...);
     // }
 
-    // for testing subclass access
-    // android-note: Removed because android doesn't restrict reflection access
-    // static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
-    //     public void checkPrivateAccess() {
-    //         try {
-    //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //                 AtomicReferenceFieldUpdater.newUpdater
-    //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
-    //             shouldThrow();
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-
-    //     public void checkCompareAndSetProtectedSub() {
-    //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //             AtomicReferenceFieldUpdater.newUpdater
-    //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField");
-    //         this.protectedField = one;
-    //         assertTrue(a.compareAndSet(this, one, two));
-    //         assertTrue(a.compareAndSet(this, two, m4));
-    //         assertSame(m4, a.get(this));
-    //         assertFalse(a.compareAndSet(this, m5, seven));
-    //         assertFalse(seven == a.get(this));
-    //         assertTrue(a.compareAndSet(this, m4, seven));
-    //         assertSame(seven, a.get(this));
-    //     }
-    // }
-
-    // static class UnrelatedClass {
-    //     public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) {
-    //         obj.x = one;
-    //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //             AtomicReferenceFieldUpdater.newUpdater
-    //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
-    //         assertSame(one, a.get(obj));
-    //         assertTrue(a.compareAndSet(obj, one, two));
-    //         assertSame(two, a.get(obj));
-    //     }
-
-    //     public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) {
-    //         try {
-    //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
-    //                 AtomicReferenceFieldUpdater.newUpdater
-    //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
-    //             throw new AssertionError("should throw");
-    //         } catch (RuntimeException success) {
-    //             assertNotNull(success.getCause());
-    //         }
-    //     }
-    // }
-
-    static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
+    AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
         return AtomicReferenceFieldUpdater.newUpdater
             (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName);
     }
@@ -131,26 +77,6 @@
     }
 
     /**
-     * construction using private field from subclass throws RuntimeException
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testPrivateFieldInSubclass() {
-    //     AtomicReferenceFieldUpdaterTestSubclass s =
-    //         new AtomicReferenceFieldUpdaterTestSubclass();
-    //     s.checkPrivateAccess();
-    // }
-
-    /**
-     * construction from unrelated class; package access is allowed,
-     * private access is not
-     */
-    // android-note: Removed because android doesn't restrict reflection access
-    // public void testUnrelatedClassAccess() {
-    //     new UnrelatedClass().checkPackageAccess(this);
-    //     new UnrelatedClass().checkPrivateAccess(this);
-    // }
-
-    /**
      * get returns the last value set or assigned
      */
     public void testGetSet() {
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicReferenceTest.java b/jsr166-tests/src/test/java/jsr166/AtomicReferenceTest.java
index 4728970..457182f 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicReferenceTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicReferenceTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicReferenceTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/AtomicStampedReferenceTest.java b/jsr166-tests/src/test/java/jsr166/AtomicStampedReferenceTest.java
index a2e8c7f..b3ff06a 100644
--- a/jsr166-tests/src/test/java/jsr166/AtomicStampedReferenceTest.java
+++ b/jsr166-tests/src/test/java/jsr166/AtomicStampedReferenceTest.java
@@ -21,7 +21,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(AtomicStampedReferenceTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java b/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
index 1a188e1..db0f03d 100644
--- a/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
@@ -39,9 +39,9 @@
     // android-note: Explicitly instantiated.
     //
     // public Test testSuite() {
-    //     // TODO: filter the returned tests using the configuration
-    //     // information provided by the subclass via protected methods.
-    //     return new TestSuite(this.getClass());
+    //    // TODO: filter the returned tests using the configuration
+    //    // information provided by the subclass via protected methods.
+    //    return new TestSuite(this.getClass());
     // }
 
     //----------------------------------------------------------------
@@ -239,8 +239,6 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         barrier.await();
@@ -354,20 +352,20 @@
                 assertEquals((pass == 0), q.contains(elts[i]));
                 assertEquals((pass == 0), q.remove(elts[i]));
                 assertFalse(q.contains(elts[i]));
-                assertTrue(q.contains(elts[i - 1]));
+                assertTrue(q.contains(elts[i-1]));
                 if (i < size - 1)
-                    assertTrue(q.contains(elts[i + 1]));
+                    assertTrue(q.contains(elts[i+1]));
             }
         }
         if (size > 0)
             assertTrue(q.contains(elts[0]));
-        for (int i = size - 2; i >= 0; i -= 2) {
+        for (int i = size-2; i >= 0; i -= 2) {
             assertTrue(q.contains(elts[i]));
-            assertFalse(q.contains(elts[i + 1]));
+            assertFalse(q.contains(elts[i+1]));
             assertTrue(q.remove(elts[i]));
             assertFalse(q.contains(elts[i]));
-            assertFalse(q.remove(elts[i + 1]));
-            assertFalse(q.contains(elts[i + 1]));
+            assertFalse(q.remove(elts[i+1]));
+            assertFalse(q.contains(elts[i+1]));
         }
         checkEmpty(q);
     }
diff --git a/jsr166-tests/src/test/java/jsr166/Collection8Test.java b/jsr166-tests/src/test/java/jsr166/Collection8Test.java
deleted file mode 100644
index 634182b..0000000
--- a/jsr166-tests/src/test/java/jsr166/Collection8Test.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Consumer;
-
-import junit.framework.Test;
-
-/**
- * Contains tests applicable to all jdk8+ Collection implementations.
- * An extension of CollectionTest.
- */
-public class Collection8Test extends JSR166TestCase {
-    final CollectionImplementation impl;
-
-    /** Tests are parameterized by a Collection implementation. */
-    Collection8Test(CollectionImplementation impl, String methodName) {
-        super(methodName);
-        this.impl = impl;
-    }
-
-    public static Test testSuite(CollectionImplementation impl) {
-        return parameterizedTestSuite(Collection8Test.class,
-                                      CollectionImplementation.class,
-                                      impl);
-    }
-
-    /**
-     * stream().forEach returns elements in the collection
-     */
-    // TODO(streams):
-    // public void testForEach() throws Throwable {
-    //     final Collection c = impl.emptyCollection();
-    //     final AtomicLong count = new AtomicLong(0L);
-    //     final Object x = impl.makeElement(1);
-    //     final Object y = impl.makeElement(2);
-    //     final ArrayList found = new ArrayList();
-    //     Consumer<Object> spy = (o) -> { found.add(o); };
-    //     c.stream().forEach(spy);
-    //     assertTrue(found.isEmpty());
-
-    //     assertTrue(c.add(x));
-    //     c.stream().forEach(spy);
-    //     assertEquals(Collections.singletonList(x), found);
-    //     found.clear();
-
-    //     assertTrue(c.add(y));
-    //     c.stream().forEach(spy);
-    //     assertEquals(2, found.size());
-    //     assertTrue(found.contains(x));
-    //     assertTrue(found.contains(y));
-    //     found.clear();
-
-    //     c.clear();
-    //     c.stream().forEach(spy);
-    //     assertTrue(found.isEmpty());
-    // }
-
-    // public void testForEachConcurrentStressTest() throws Throwable {
-    //     if (!impl.isConcurrent()) return;
-    //     final Collection c = impl.emptyCollection();
-    //     final long testDurationMillis = timeoutMillis();
-    //     final AtomicBoolean done = new AtomicBoolean(false);
-    //     final Object elt = impl.makeElement(1);
-    //     final Future<?> f1, f2;
-    //     final ExecutorService pool = Executors.newCachedThreadPool();
-    //     try (PoolCleaner cleaner = cleaner(pool, done)) {
-    //         final CountDownLatch threadsStarted = new CountDownLatch(2);
-    //         Runnable checkElt = () -> {
-    //             threadsStarted.countDown();
-    //             while (!done.get())
-    //                 c.stream().forEach((x) -> { assertSame(x, elt); }); };
-    //         Runnable addRemove = () -> {
-    //             threadsStarted.countDown();
-    //             while (!done.get()) {
-    //                 assertTrue(c.add(elt));
-    //                 assertTrue(c.remove(elt));
-    //             }};
-    //         f1 = pool.submit(checkElt);
-    //         f2 = pool.submit(addRemove);
-    //         Thread.sleep(testDurationMillis);
-    //     }
-    //     assertNull(f1.get(0L, MILLISECONDS));
-    //     assertNull(f2.get(0L, MILLISECONDS));
-    // }
-
-    // public void testCollection8DebugFail() { fail(); }
-}
diff --git a/jsr166-tests/src/test/java/jsr166/CollectionImplementation.java b/jsr166-tests/src/test/java/jsr166/CollectionImplementation.java
deleted file mode 100644
index 4ba5bda..0000000
--- a/jsr166-tests/src/test/java/jsr166/CollectionImplementation.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import java.util.Collection;
-
-/** Allows tests to work with different Collection implementations. */
-public interface CollectionImplementation {
-    /** Returns the Collection class. */
-    public Class<?> klazz();
-    /** Returns an empty collection. */
-    public Collection emptyCollection();
-    public Object makeElement(int i);
-    public boolean isConcurrent();
-    public boolean permitsNulls();
-}
diff --git a/jsr166-tests/src/test/java/jsr166/CollectionTest.java b/jsr166-tests/src/test/java/jsr166/CollectionTest.java
deleted file mode 100644
index 44ef66d..0000000
--- a/jsr166-tests/src/test/java/jsr166/CollectionTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import java.util.Collection;
-
-import junit.framework.Test;
-
-/**
- * Contains tests applicable to all Collection implementations.
- */
-public class CollectionTest extends JSR166TestCase {
-    final CollectionImplementation impl;
-
-    /** Tests are parameterized by a Collection implementation. */
-    CollectionTest(CollectionImplementation impl, String methodName) {
-        super(methodName);
-        this.impl = impl;
-    }
-
-    public static Test testSuite(CollectionImplementation impl) {
-        return newTestSuite
-            (parameterizedTestSuite(CollectionTest.class,
-                                    CollectionImplementation.class,
-                                    impl),
-             jdk8ParameterizedTestSuite(CollectionTest.class,
-                                        CollectionImplementation.class,
-                                        impl));
-    }
-
-    /** A test of the CollectionImplementation implementation ! */
-    public void testEmptyMeansEmpty() {
-        assertTrue(impl.emptyCollection().isEmpty());
-        assertEquals(0, impl.emptyCollection().size());
-    }
-
-    // public void testCollectionDebugFail() { fail(); }
-}
diff --git a/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java b/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java
deleted file mode 100644
index 1372cc4..0000000
--- a/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java
+++ /dev/null
@@ -1,3959 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.concurrent.CompletableFuture.completedFuture;
-import static java.util.concurrent.CompletableFuture.failedFuture;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-// TODO(streams):
-//import java.util.stream.Collectors;
-//import java.util.stream.Stream;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class CompletableFutureTest extends JSR166TestCase {
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(CompletableFutureTest.class);
-    // }
-
-    static class CFException extends RuntimeException {}
-
-    void checkIncomplete(CompletableFuture<?> f) {
-        assertFalse(f.isDone());
-        assertFalse(f.isCancelled());
-        assertTrue(f.toString().contains("Not completed"));
-        try {
-            assertNull(f.getNow(null));
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        try {
-            f.get(0L, SECONDS);
-            shouldThrow();
-        }
-        catch (TimeoutException success) {}
-        catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
-        checkTimedGet(f, value);
-
-        try {
-            assertEquals(value, f.join());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        try {
-            assertEquals(value, f.getNow(null));
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        try {
-            assertEquals(value, f.get());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        assertTrue(f.isDone());
-        assertFalse(f.isCancelled());
-        assertFalse(f.isCompletedExceptionally());
-        assertTrue(f.toString().contains("[Completed normally]"));
-    }
-
-    /**
-     * Returns the "raw" internal exceptional completion of f,
-     * without any additional wrapping with CompletionException.
-     */
-    <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
-        // handle (and whenComplete) can distinguish between "direct"
-        // and "wrapped" exceptional completion
-        return f.handle((U u, Throwable t) -> t).join();
-    }
-
-    void checkCompletedExceptionally(CompletableFuture<?> f,
-                                     boolean wrapped,
-                                     Consumer<Throwable> checker) {
-        Throwable cause = exceptionalCompletion(f);
-        if (wrapped) {
-            assertTrue(cause instanceof CompletionException);
-            cause = cause.getCause();
-        }
-        checker.accept(cause);
-
-        long startTime = System.nanoTime();
-        try {
-            f.get(LONG_DELAY_MS, MILLISECONDS);
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(cause, success.getCause());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
-
-        try {
-            f.join();
-            shouldThrow();
-        } catch (CompletionException success) {
-            assertSame(cause, success.getCause());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            f.getNow(null);
-            shouldThrow();
-        } catch (CompletionException success) {
-            assertSame(cause, success.getCause());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            f.get();
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(cause, success.getCause());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        assertFalse(f.isCancelled());
-        assertTrue(f.isDone());
-        assertTrue(f.isCompletedExceptionally());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
-    }
-
-    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
-        checkCompletedExceptionally(f, true,
-            (t) -> assertTrue(t instanceof CFException));
-    }
-
-    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
-        checkCompletedExceptionally(f, true,
-            (t) -> assertTrue(t instanceof CancellationException));
-    }
-
-    void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
-        checkCompletedExceptionally(f, false,
-            (t) -> assertTrue(t instanceof TimeoutException));
-    }
-
-    void checkCompletedWithWrappedException(CompletableFuture<?> f,
-                                            Throwable ex) {
-        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
-    }
-
-    void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
-        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
-    }
-
-    void checkCancelled(CompletableFuture<?> f) {
-        long startTime = System.nanoTime();
-        try {
-            f.get(LONG_DELAY_MS, MILLISECONDS);
-            shouldThrow();
-        } catch (CancellationException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
-
-        try {
-            f.join();
-            shouldThrow();
-        } catch (CancellationException success) {}
-        try {
-            f.getNow(null);
-            shouldThrow();
-        } catch (CancellationException success) {}
-        try {
-            f.get();
-            shouldThrow();
-        } catch (CancellationException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        assertTrue(exceptionalCompletion(f) instanceof CancellationException);
-
-        assertTrue(f.isDone());
-        assertTrue(f.isCompletedExceptionally());
-        assertTrue(f.isCancelled());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
-    }
-
-    /**
-     * A newly constructed CompletableFuture is incomplete, as indicated
-     * by methods isDone, isCancelled, and getNow
-     */
-    public void testConstructor() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        checkIncomplete(f);
-    }
-
-    /**
-     * complete completes normally, as indicated by methods isDone,
-     * isCancelled, join, get, and getNow
-     */
-    public void testComplete() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        checkIncomplete(f);
-        assertTrue(f.complete(v1));
-        assertFalse(f.complete(v1));
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * completeExceptionally completes exceptionally, as indicated by
-     * methods isDone, isCancelled, join, get, and getNow
-     */
-    public void testCompleteExceptionally() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CFException ex = new CFException();
-        checkIncomplete(f);
-        f.completeExceptionally(ex);
-        checkCompletedExceptionally(f, ex);
-    }
-
-    /**
-     * cancel completes exceptionally and reports cancelled, as indicated by
-     * methods isDone, isCancelled, join, get, and getNow
-     */
-    public void testCancel() {
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        checkIncomplete(f);
-        assertTrue(f.cancel(mayInterruptIfRunning));
-        assertTrue(f.cancel(mayInterruptIfRunning));
-        assertTrue(f.cancel(!mayInterruptIfRunning));
-        checkCancelled(f);
-    }}
-
-    /**
-     * obtrudeValue forces completion with given value
-     */
-    public void testObtrudeValue() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        checkIncomplete(f);
-        assertTrue(f.complete(one));
-        checkCompletedNormally(f, one);
-        f.obtrudeValue(three);
-        checkCompletedNormally(f, three);
-        f.obtrudeValue(two);
-        checkCompletedNormally(f, two);
-        f = new CompletableFuture<>();
-        f.obtrudeValue(three);
-        checkCompletedNormally(f, three);
-        f.obtrudeValue(null);
-        checkCompletedNormally(f, null);
-        f = new CompletableFuture<>();
-        f.completeExceptionally(new CFException());
-        f.obtrudeValue(four);
-        checkCompletedNormally(f, four);
-    }
-
-    /**
-     * obtrudeException forces completion with given exception
-     */
-    public void testObtrudeException() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CFException ex;
-        CompletableFuture<Integer> f;
-
-        f = new CompletableFuture<>();
-        assertTrue(f.complete(v1));
-        for (int i = 0; i < 2; i++) {
-            f.obtrudeException(ex = new CFException());
-            checkCompletedExceptionally(f, ex);
-        }
-
-        f = new CompletableFuture<>();
-        for (int i = 0; i < 2; i++) {
-            f.obtrudeException(ex = new CFException());
-            checkCompletedExceptionally(f, ex);
-        }
-
-        f = new CompletableFuture<>();
-        f.completeExceptionally(ex = new CFException());
-        f.obtrudeValue(v1);
-        checkCompletedNormally(f, v1);
-        f.obtrudeException(ex = new CFException());
-        checkCompletedExceptionally(f, ex);
-        f.completeExceptionally(new CFException());
-        checkCompletedExceptionally(f, ex);
-        assertFalse(f.complete(v1));
-        checkCompletedExceptionally(f, ex);
-    }}
-
-    /**
-     * getNumberOfDependents returns number of dependent tasks
-     */
-    public void testGetNumberOfDependents() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        assertEquals(0, f.getNumberOfDependents());
-        final CompletableFuture<Void> g = m.thenRun(f, new Noop(m));
-        assertEquals(1, f.getNumberOfDependents());
-        assertEquals(0, g.getNumberOfDependents());
-        final CompletableFuture<Void> h = m.thenRun(f, new Noop(m));
-        assertEquals(2, f.getNumberOfDependents());
-        assertEquals(0, h.getNumberOfDependents());
-        assertTrue(f.complete(v1));
-        checkCompletedNormally(g, null);
-        checkCompletedNormally(h, null);
-        assertEquals(0, f.getNumberOfDependents());
-        assertEquals(0, g.getNumberOfDependents());
-        assertEquals(0, h.getNumberOfDependents());
-    }}
-
-    /**
-     * toString indicates current completion state
-     */
-    public void testToString() {
-        CompletableFuture<String> f;
-
-        f = new CompletableFuture<String>();
-        assertTrue(f.toString().contains("[Not completed]"));
-
-        assertTrue(f.complete("foo"));
-        assertTrue(f.toString().contains("[Completed normally]"));
-
-        f = new CompletableFuture<String>();
-        assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
-
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
-            f = new CompletableFuture<String>();
-            assertTrue(f.cancel(mayInterruptIfRunning));
-            assertTrue(f.toString().contains("[Completed exceptionally]"));
-        }
-    }
-
-    /**
-     * completedFuture returns a completed CompletableFuture with given value
-     */
-    public void testCompletedFuture() {
-        CompletableFuture<String> f = CompletableFuture.completedFuture("test");
-        checkCompletedNormally(f, "test");
-    }
-
-    abstract class CheckedAction {
-        int invocationCount = 0;
-        final ExecutionMode m;
-        CheckedAction(ExecutionMode m) { this.m = m; }
-        void invoked() {
-            m.checkExecutionMode();
-            assertEquals(0, invocationCount++);
-        }
-        void assertNotInvoked() { assertEquals(0, invocationCount); }
-        void assertInvoked() { assertEquals(1, invocationCount); }
-    }
-
-    abstract class CheckedIntegerAction extends CheckedAction {
-        Integer value;
-        CheckedIntegerAction(ExecutionMode m) { super(m); }
-        void assertValue(Integer expected) {
-            assertInvoked();
-            assertEquals(expected, value);
-        }
-    }
-
-    class IntegerSupplier extends CheckedAction
-        implements Supplier<Integer>
-    {
-        final Integer value;
-        IntegerSupplier(ExecutionMode m, Integer value) {
-            super(m);
-            this.value = value;
-        }
-        public Integer get() {
-            invoked();
-            return value;
-        }
-    }
-
-    // A function that handles and produces null values as well.
-    static Integer inc(Integer x) {
-        return (x == null) ? null : x + 1;
-    }
-
-    class NoopConsumer extends CheckedIntegerAction
-        implements Consumer<Integer>
-    {
-        NoopConsumer(ExecutionMode m) { super(m); }
-        public void accept(Integer x) {
-            invoked();
-            value = x;
-        }
-    }
-
-    class IncFunction extends CheckedIntegerAction
-        implements Function<Integer,Integer>
-    {
-        IncFunction(ExecutionMode m) { super(m); }
-        public Integer apply(Integer x) {
-            invoked();
-            return value = inc(x);
-        }
-    }
-
-    // Choose non-commutative actions for better coverage
-    // A non-commutative function that handles and produces null values as well.
-    static Integer subtract(Integer x, Integer y) {
-        return (x == null && y == null) ? null :
-            ((x == null) ? 42 : x.intValue())
-            - ((y == null) ? 99 : y.intValue());
-    }
-
-    class SubtractAction extends CheckedIntegerAction
-        implements BiConsumer<Integer, Integer>
-    {
-        SubtractAction(ExecutionMode m) { super(m); }
-        public void accept(Integer x, Integer y) {
-            invoked();
-            value = subtract(x, y);
-        }
-    }
-
-    class SubtractFunction extends CheckedIntegerAction
-        implements BiFunction<Integer, Integer, Integer>
-    {
-        SubtractFunction(ExecutionMode m) { super(m); }
-        public Integer apply(Integer x, Integer y) {
-            invoked();
-            return value = subtract(x, y);
-        }
-    }
-
-    class Noop extends CheckedAction implements Runnable {
-        Noop(ExecutionMode m) { super(m); }
-        public void run() {
-            invoked();
-        }
-    }
-
-    class FailingSupplier extends CheckedAction
-        implements Supplier<Integer>
-    {
-        FailingSupplier(ExecutionMode m) { super(m); }
-        public Integer get() {
-            invoked();
-            throw new CFException();
-        }
-    }
-
-    class FailingConsumer extends CheckedIntegerAction
-        implements Consumer<Integer>
-    {
-        FailingConsumer(ExecutionMode m) { super(m); }
-        public void accept(Integer x) {
-            invoked();
-            value = x;
-            throw new CFException();
-        }
-    }
-
-    class FailingBiConsumer extends CheckedIntegerAction
-        implements BiConsumer<Integer, Integer>
-    {
-        FailingBiConsumer(ExecutionMode m) { super(m); }
-        public void accept(Integer x, Integer y) {
-            invoked();
-            value = subtract(x, y);
-            throw new CFException();
-        }
-    }
-
-    class FailingFunction extends CheckedIntegerAction
-        implements Function<Integer, Integer>
-    {
-        FailingFunction(ExecutionMode m) { super(m); }
-        public Integer apply(Integer x) {
-            invoked();
-            value = x;
-            throw new CFException();
-        }
-    }
-
-    class FailingBiFunction extends CheckedIntegerAction
-        implements BiFunction<Integer, Integer, Integer>
-    {
-        FailingBiFunction(ExecutionMode m) { super(m); }
-        public Integer apply(Integer x, Integer y) {
-            invoked();
-            value = subtract(x, y);
-            throw new CFException();
-        }
-    }
-
-    class FailingRunnable extends CheckedAction implements Runnable {
-        FailingRunnable(ExecutionMode m) { super(m); }
-        public void run() {
-            invoked();
-            throw new CFException();
-        }
-    }
-
-    class CompletableFutureInc extends CheckedIntegerAction
-        implements Function<Integer, CompletableFuture<Integer>>
-    {
-        CompletableFutureInc(ExecutionMode m) { super(m); }
-        public CompletableFuture<Integer> apply(Integer x) {
-            invoked();
-            value = x;
-            CompletableFuture<Integer> f = new CompletableFuture<>();
-            assertTrue(f.complete(inc(x)));
-            return f;
-        }
-    }
-
-    class FailingCompletableFutureFunction extends CheckedIntegerAction
-        implements Function<Integer, CompletableFuture<Integer>>
-    {
-        FailingCompletableFutureFunction(ExecutionMode m) { super(m); }
-        public CompletableFuture<Integer> apply(Integer x) {
-            invoked();
-            value = x;
-            throw new CFException();
-        }
-    }
-
-    // Used for explicit executor tests
-    static final class ThreadExecutor implements Executor {
-        final AtomicInteger count = new AtomicInteger(0);
-        static final ThreadGroup tg = new ThreadGroup("ThreadExecutor");
-        static boolean startedCurrentThread() {
-            return Thread.currentThread().getThreadGroup() == tg;
-        }
-
-        public void execute(Runnable r) {
-            count.getAndIncrement();
-            new Thread(tg, r).start();
-        }
-    }
-
-    static final boolean defaultExecutorIsCommonPool
-        = ForkJoinPool.getCommonPoolParallelism() > 1;
-
-    /**
-     * Permits the testing of parallel code for the 3 different
-     * execution modes without copy/pasting all the test methods.
-     */
-    enum ExecutionMode {
-        SYNC {
-            public void checkExecutionMode() {
-                assertFalse(ThreadExecutor.startedCurrentThread());
-                assertNull(ForkJoinTask.getPool());
-            }
-            public CompletableFuture<Void> runAsync(Runnable a) {
-                throw new UnsupportedOperationException();
-            }
-            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
-                throw new UnsupportedOperationException();
-            }
-            public <T> CompletableFuture<Void> thenRun
-                (CompletableFuture<T> f, Runnable a) {
-                return f.thenRun(a);
-            }
-            public <T> CompletableFuture<Void> thenAccept
-                (CompletableFuture<T> f, Consumer<? super T> a) {
-                return f.thenAccept(a);
-            }
-            public <T,U> CompletableFuture<U> thenApply
-                (CompletableFuture<T> f, Function<? super T,U> a) {
-                return f.thenApply(a);
-            }
-            public <T,U> CompletableFuture<U> thenCompose
-                (CompletableFuture<T> f,
-                 Function<? super T,? extends CompletionStage<U>> a) {
-                return f.thenCompose(a);
-            }
-            public <T,U> CompletableFuture<U> handle
-                (CompletableFuture<T> f,
-                 BiFunction<? super T,Throwable,? extends U> a) {
-                return f.handle(a);
-            }
-            public <T> CompletableFuture<T> whenComplete
-                (CompletableFuture<T> f,
-                 BiConsumer<? super T,? super Throwable> a) {
-                return f.whenComplete(a);
-            }
-            public <T,U> CompletableFuture<Void> runAfterBoth
-                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
-                return f.runAfterBoth(g, a);
-            }
-            public <T,U> CompletableFuture<Void> thenAcceptBoth
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiConsumer<? super T,? super U> a) {
-                return f.thenAcceptBoth(g, a);
-            }
-            public <T,U,V> CompletableFuture<V> thenCombine
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiFunction<? super T,? super U,? extends V> a) {
-                return f.thenCombine(g, a);
-            }
-            public <T> CompletableFuture<Void> runAfterEither
-                (CompletableFuture<T> f,
-                 CompletionStage<?> g,
-                 java.lang.Runnable a) {
-                return f.runAfterEither(g, a);
-            }
-            public <T> CompletableFuture<Void> acceptEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Consumer<? super T> a) {
-                return f.acceptEither(g, a);
-            }
-            public <T,U> CompletableFuture<U> applyToEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Function<? super T,U> a) {
-                return f.applyToEither(g, a);
-            }
-        },
-
-        ASYNC {
-            public void checkExecutionMode() {
-                assertEquals(defaultExecutorIsCommonPool,
-                             (ForkJoinPool.commonPool() == ForkJoinTask.getPool()));
-            }
-            public CompletableFuture<Void> runAsync(Runnable a) {
-                return CompletableFuture.runAsync(a);
-            }
-            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
-                return CompletableFuture.supplyAsync(a);
-            }
-            public <T> CompletableFuture<Void> thenRun
-                (CompletableFuture<T> f, Runnable a) {
-                return f.thenRunAsync(a);
-            }
-            public <T> CompletableFuture<Void> thenAccept
-                (CompletableFuture<T> f, Consumer<? super T> a) {
-                return f.thenAcceptAsync(a);
-            }
-            public <T,U> CompletableFuture<U> thenApply
-                (CompletableFuture<T> f, Function<? super T,U> a) {
-                return f.thenApplyAsync(a);
-            }
-            public <T,U> CompletableFuture<U> thenCompose
-                (CompletableFuture<T> f,
-                 Function<? super T,? extends CompletionStage<U>> a) {
-                return f.thenComposeAsync(a);
-            }
-            public <T,U> CompletableFuture<U> handle
-                (CompletableFuture<T> f,
-                 BiFunction<? super T,Throwable,? extends U> a) {
-                return f.handleAsync(a);
-            }
-            public <T> CompletableFuture<T> whenComplete
-                (CompletableFuture<T> f,
-                 BiConsumer<? super T,? super Throwable> a) {
-                return f.whenCompleteAsync(a);
-            }
-            public <T,U> CompletableFuture<Void> runAfterBoth
-                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
-                return f.runAfterBothAsync(g, a);
-            }
-            public <T,U> CompletableFuture<Void> thenAcceptBoth
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiConsumer<? super T,? super U> a) {
-                return f.thenAcceptBothAsync(g, a);
-            }
-            public <T,U,V> CompletableFuture<V> thenCombine
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiFunction<? super T,? super U,? extends V> a) {
-                return f.thenCombineAsync(g, a);
-            }
-            public <T> CompletableFuture<Void> runAfterEither
-                (CompletableFuture<T> f,
-                 CompletionStage<?> g,
-                 java.lang.Runnable a) {
-                return f.runAfterEitherAsync(g, a);
-            }
-            public <T> CompletableFuture<Void> acceptEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Consumer<? super T> a) {
-                return f.acceptEitherAsync(g, a);
-            }
-            public <T,U> CompletableFuture<U> applyToEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Function<? super T,U> a) {
-                return f.applyToEitherAsync(g, a);
-            }
-        },
-
-        EXECUTOR {
-            public void checkExecutionMode() {
-                assertTrue(ThreadExecutor.startedCurrentThread());
-            }
-            public CompletableFuture<Void> runAsync(Runnable a) {
-                return CompletableFuture.runAsync(a, new ThreadExecutor());
-            }
-            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
-                return CompletableFuture.supplyAsync(a, new ThreadExecutor());
-            }
-            public <T> CompletableFuture<Void> thenRun
-                (CompletableFuture<T> f, Runnable a) {
-                return f.thenRunAsync(a, new ThreadExecutor());
-            }
-            public <T> CompletableFuture<Void> thenAccept
-                (CompletableFuture<T> f, Consumer<? super T> a) {
-                return f.thenAcceptAsync(a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<U> thenApply
-                (CompletableFuture<T> f, Function<? super T,U> a) {
-                return f.thenApplyAsync(a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<U> thenCompose
-                (CompletableFuture<T> f,
-                 Function<? super T,? extends CompletionStage<U>> a) {
-                return f.thenComposeAsync(a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<U> handle
-                (CompletableFuture<T> f,
-                 BiFunction<? super T,Throwable,? extends U> a) {
-                return f.handleAsync(a, new ThreadExecutor());
-            }
-            public <T> CompletableFuture<T> whenComplete
-                (CompletableFuture<T> f,
-                 BiConsumer<? super T,? super Throwable> a) {
-                return f.whenCompleteAsync(a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<Void> runAfterBoth
-                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
-                return f.runAfterBothAsync(g, a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<Void> thenAcceptBoth
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiConsumer<? super T,? super U> a) {
-                return f.thenAcceptBothAsync(g, a, new ThreadExecutor());
-            }
-            public <T,U,V> CompletableFuture<V> thenCombine
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends U> g,
-                 BiFunction<? super T,? super U,? extends V> a) {
-                return f.thenCombineAsync(g, a, new ThreadExecutor());
-            }
-            public <T> CompletableFuture<Void> runAfterEither
-                (CompletableFuture<T> f,
-                 CompletionStage<?> g,
-                 java.lang.Runnable a) {
-                return f.runAfterEitherAsync(g, a, new ThreadExecutor());
-            }
-            public <T> CompletableFuture<Void> acceptEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Consumer<? super T> a) {
-                return f.acceptEitherAsync(g, a, new ThreadExecutor());
-            }
-            public <T,U> CompletableFuture<U> applyToEither
-                (CompletableFuture<T> f,
-                 CompletionStage<? extends T> g,
-                 Function<? super T,U> a) {
-                return f.applyToEitherAsync(g, a, new ThreadExecutor());
-            }
-        };
-
-        public abstract void checkExecutionMode();
-        public abstract CompletableFuture<Void> runAsync(Runnable a);
-        public abstract <U> CompletableFuture<U> supplyAsync(Supplier<U> a);
-        public abstract <T> CompletableFuture<Void> thenRun
-            (CompletableFuture<T> f, Runnable a);
-        public abstract <T> CompletableFuture<Void> thenAccept
-            (CompletableFuture<T> f, Consumer<? super T> a);
-        public abstract <T,U> CompletableFuture<U> thenApply
-            (CompletableFuture<T> f, Function<? super T,U> a);
-        public abstract <T,U> CompletableFuture<U> thenCompose
-            (CompletableFuture<T> f,
-             Function<? super T,? extends CompletionStage<U>> a);
-        public abstract <T,U> CompletableFuture<U> handle
-            (CompletableFuture<T> f,
-             BiFunction<? super T,Throwable,? extends U> a);
-        public abstract <T> CompletableFuture<T> whenComplete
-            (CompletableFuture<T> f,
-             BiConsumer<? super T,? super Throwable> a);
-        public abstract <T,U> CompletableFuture<Void> runAfterBoth
-            (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a);
-        public abstract <T,U> CompletableFuture<Void> thenAcceptBoth
-            (CompletableFuture<T> f,
-             CompletionStage<? extends U> g,
-             BiConsumer<? super T,? super U> a);
-        public abstract <T,U,V> CompletableFuture<V> thenCombine
-            (CompletableFuture<T> f,
-             CompletionStage<? extends U> g,
-             BiFunction<? super T,? super U,? extends V> a);
-        public abstract <T> CompletableFuture<Void> runAfterEither
-            (CompletableFuture<T> f,
-             CompletionStage<?> g,
-             java.lang.Runnable a);
-        public abstract <T> CompletableFuture<Void> acceptEither
-            (CompletableFuture<T> f,
-             CompletionStage<? extends T> g,
-             Consumer<? super T> a);
-        public abstract <T,U> CompletableFuture<U> applyToEither
-            (CompletableFuture<T> f,
-             CompletionStage<? extends T> g,
-             Function<? super T,U> a);
-    }
-
-    /**
-     * exceptionally action is not invoked when source completes
-     * normally, and source result is propagated
-     */
-    public void testExceptionally_normalCompletion() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = f.exceptionally
-            ((Throwable t) -> {
-                a.getAndIncrement();
-                threadFail("should not be called");
-                return null;            // unreached
-            });
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedNormally(g, v1);
-        checkCompletedNormally(f, v1);
-        assertEquals(0, a.get());
-    }}
-
-    /**
-     * exceptionally action completes with function value on source
-     * exception
-     */
-    public void testExceptionally_exceptionalCompletion() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) f.completeExceptionally(ex);
-        final CompletableFuture<Integer> g = f.exceptionally
-            ((Throwable t) -> {
-                ExecutionMode.SYNC.checkExecutionMode();
-                threadAssertSame(t, ex);
-                a.getAndIncrement();
-                return v1;
-            });
-        if (createIncomplete) f.completeExceptionally(ex);
-
-        checkCompletedNormally(g, v1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * If an "exceptionally action" throws an exception, it completes
-     * exceptionally with that exception
-     */
-    public void testExceptionally_exceptionalCompletionActionFailed() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex1 = new CFException();
-        final CFException ex2 = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) f.completeExceptionally(ex1);
-        final CompletableFuture<Integer> g = f.exceptionally
-            ((Throwable t) -> {
-                ExecutionMode.SYNC.checkExecutionMode();
-                threadAssertSame(t, ex1);
-                a.getAndIncrement();
-                throw ex2;
-            });
-        if (createIncomplete) f.completeExceptionally(ex1);
-
-        checkCompletedWithWrappedException(g, ex2);
-        checkCompletedExceptionally(f, ex1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * whenComplete action executes on normal completion, propagating
-     * source result.
-     */
-    public void testWhenComplete_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.whenComplete
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertSame(result, v1);
-                threadAssertNull(t);
-                a.getAndIncrement();
-            });
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedNormally(g, v1);
-        checkCompletedNormally(f, v1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * whenComplete action executes on exceptional completion, propagating
-     * source result.
-     */
-    public void testWhenComplete_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) f.completeExceptionally(ex);
-        final CompletableFuture<Integer> g = m.whenComplete
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertNull(result);
-                threadAssertSame(t, ex);
-                a.getAndIncrement();
-            });
-        if (createIncomplete) f.completeExceptionally(ex);
-
-        checkCompletedWithWrappedException(g, ex);
-        checkCompletedExceptionally(f, ex);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * whenComplete action executes on cancelled source, propagating
-     * CancellationException.
-     */
-    public void testWhenComplete_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean createIncomplete : new boolean[] { true, false })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Integer> g = m.whenComplete
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertNull(result);
-                threadAssertTrue(t instanceof CancellationException);
-                a.getAndIncrement();
-            });
-        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
-
-        checkCompletedWithWrappedCancellationException(g);
-        checkCancelled(f);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * If a whenComplete action throws an exception when triggered by
-     * a normal completion, it completes exceptionally
-     */
-    public void testWhenComplete_sourceCompletedNormallyActionFailed() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.whenComplete
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertSame(result, v1);
-                threadAssertNull(t);
-                a.getAndIncrement();
-                throw ex;
-            });
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedWithWrappedException(g, ex);
-        checkCompletedNormally(f, v1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * If a whenComplete action throws an exception when triggered by
-     * a source completion that also throws an exception, the source
-     * exception takes precedence (unlike handle)
-     */
-    public void testWhenComplete_sourceFailedActionFailed() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex1 = new CFException();
-        final CFException ex2 = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-
-        if (!createIncomplete) f.completeExceptionally(ex1);
-        final CompletableFuture<Integer> g = m.whenComplete
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertSame(t, ex1);
-                threadAssertNull(result);
-                a.getAndIncrement();
-                throw ex2;
-            });
-        if (createIncomplete) f.completeExceptionally(ex1);
-
-        checkCompletedWithWrappedException(g, ex1);
-        checkCompletedExceptionally(f, ex1);
-        if (testImplementationDetails) {
-            assertEquals(1, ex1.getSuppressed().length);
-            assertSame(ex2, ex1.getSuppressed()[0]);
-        }
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * handle action completes normally with function value on normal
-     * completion of source
-     */
-    public void testHandle_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final AtomicInteger a = new AtomicInteger(0);
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.handle
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertSame(result, v1);
-                threadAssertNull(t);
-                a.getAndIncrement();
-                return inc(v1);
-            });
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedNormally(g, inc(v1));
-        checkCompletedNormally(f, v1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * handle action completes normally with function value on
-     * exceptional completion of source
-     */
-    public void testHandle_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex = new CFException();
-        if (!createIncomplete) f.completeExceptionally(ex);
-        final CompletableFuture<Integer> g = m.handle
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertNull(result);
-                threadAssertSame(t, ex);
-                a.getAndIncrement();
-                return v1;
-            });
-        if (createIncomplete) f.completeExceptionally(ex);
-
-        checkCompletedNormally(g, v1);
-        checkCompletedExceptionally(f, ex);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * handle action completes normally with function value on
-     * cancelled source
-     */
-    public void testHandle_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final AtomicInteger a = new AtomicInteger(0);
-        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Integer> g = m.handle
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertNull(result);
-                threadAssertTrue(t instanceof CancellationException);
-                a.getAndIncrement();
-                return v1;
-            });
-        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
-
-        checkCompletedNormally(g, v1);
-        checkCancelled(f);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * If a "handle action" throws an exception when triggered by
-     * a normal completion, it completes exceptionally
-     */
-    public void testHandle_sourceCompletedNormallyActionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex = new CFException();
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.handle
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertSame(result, v1);
-                threadAssertNull(t);
-                a.getAndIncrement();
-                throw ex;
-            });
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedWithWrappedException(g, ex);
-        checkCompletedNormally(f, v1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * If a "handle action" throws an exception when triggered by
-     * a source completion that also throws an exception, the action
-     * exception takes precedence (unlike whenComplete)
-     */
-    public void testHandle_sourceFailedActionFailed() {
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final AtomicInteger a = new AtomicInteger(0);
-        final CFException ex1 = new CFException();
-        final CFException ex2 = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-
-        if (!createIncomplete) f.completeExceptionally(ex1);
-        final CompletableFuture<Integer> g = m.handle
-            (f,
-             (Integer result, Throwable t) -> {
-                m.checkExecutionMode();
-                threadAssertNull(result);
-                threadAssertSame(ex1, t);
-                a.getAndIncrement();
-                throw ex2;
-            });
-        if (createIncomplete) f.completeExceptionally(ex1);
-
-        checkCompletedWithWrappedException(g, ex2);
-        checkCompletedExceptionally(f, ex1);
-        assertEquals(1, a.get());
-    }}
-
-    /**
-     * runAsync completes after running Runnable
-     */
-    public void testRunAsync_normalCompletion() {
-        ExecutionMode[] executionModes = {
-            ExecutionMode.ASYNC,
-            ExecutionMode.EXECUTOR,
-        };
-        for (ExecutionMode m : executionModes)
-    {
-        final Noop r = new Noop(m);
-        final CompletableFuture<Void> f = m.runAsync(r);
-        assertNull(f.join());
-        checkCompletedNormally(f, null);
-        r.assertInvoked();
-    }}
-
-    /**
-     * failing runAsync completes exceptionally after running Runnable
-     */
-    public void testRunAsync_exceptionalCompletion() {
-        ExecutionMode[] executionModes = {
-            ExecutionMode.ASYNC,
-            ExecutionMode.EXECUTOR,
-        };
-        for (ExecutionMode m : executionModes)
-    {
-        final FailingRunnable r = new FailingRunnable(m);
-        final CompletableFuture<Void> f = m.runAsync(r);
-        checkCompletedWithWrappedCFException(f);
-        r.assertInvoked();
-    }}
-
-    /**
-     * supplyAsync completes with result of supplier
-     */
-    public void testSupplyAsync_normalCompletion() {
-        ExecutionMode[] executionModes = {
-            ExecutionMode.ASYNC,
-            ExecutionMode.EXECUTOR,
-        };
-        for (ExecutionMode m : executionModes)
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final IntegerSupplier r = new IntegerSupplier(m, v1);
-        final CompletableFuture<Integer> f = m.supplyAsync(r);
-        assertSame(v1, f.join());
-        checkCompletedNormally(f, v1);
-        r.assertInvoked();
-    }}
-
-    /**
-     * Failing supplyAsync completes exceptionally
-     */
-    public void testSupplyAsync_exceptionalCompletion() {
-        ExecutionMode[] executionModes = {
-            ExecutionMode.ASYNC,
-            ExecutionMode.EXECUTOR,
-        };
-        for (ExecutionMode m : executionModes)
-    {
-        FailingSupplier r = new FailingSupplier(m);
-        CompletableFuture<Integer> f = m.supplyAsync(r);
-        checkCompletedWithWrappedCFException(f);
-        r.assertInvoked();
-    }}
-
-    // seq completion methods
-
-    /**
-     * thenRun result completes normally after normal completion of source
-     */
-    public void testThenRun_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
-        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
-
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        checkCompletedNormally(h4, null);
-        checkCompletedNormally(h5, null);
-        checkCompletedNormally(f, v1);
-        for (Noop r : rs) r.assertInvoked();
-    }}
-
-    /**
-     * thenRun result completes exceptionally after exceptional
-     * completion of source
-     */
-    public void testThenRun_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(f.completeExceptionally(ex));
-        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
-        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
-
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedWithWrappedException(h4, ex);
-        checkCompletedWithWrappedException(h5, ex);
-        checkCompletedExceptionally(f, ex);
-        for (Noop r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenRun result completes exceptionally if source cancelled
-     */
-    public void testThenRun_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
-        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
-
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        checkCompletedWithWrappedCancellationException(h4);
-        checkCompletedWithWrappedCancellationException(h5);
-        checkCancelled(f);
-        for (Noop r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenRun result completes exceptionally if action does
-     */
-    public void testThenRun_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final FailingRunnable[] rs = new FailingRunnable[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);
-
-        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
-        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
-
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        checkCompletedWithWrappedCFException(h4);
-        checkCompletedWithWrappedCFException(h5);
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * thenApply result completes normally after normal completion of source
-     */
-    public void testThenApply_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
-
-        checkCompletedNormally(h0, inc(v1));
-        checkCompletedNormally(h1, inc(v1));
-        checkCompletedNormally(h2, inc(v1));
-        checkCompletedNormally(h3, inc(v1));
-        checkCompletedNormally(f, v1);
-        for (IncFunction r : rs) r.assertValue(inc(v1));
-    }}
-
-    /**
-     * thenApply result completes exceptionally after exceptional
-     * completion of source
-     */
-    public void testThenApply_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
-        assertTrue(f.completeExceptionally(ex));
-        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedExceptionally(f, ex);
-        for (IncFunction r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenApply result completes exceptionally if source cancelled
-     */
-    public void testThenApply_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
-        assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        checkCancelled(f);
-        for (IncFunction r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenApply result completes exceptionally if action does
-     */
-    public void testThenApply_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final FailingFunction[] rs = new FailingFunction[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * thenAccept result completes normally after normal completion of source
-     */
-    public void testThenAccept_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final NoopConsumer[] rs = new NoopConsumer[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
-
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        checkCompletedNormally(f, v1);
-        for (NoopConsumer r : rs) r.assertValue(v1);
-    }}
-
-    /**
-     * thenAccept result completes exceptionally after exceptional
-     * completion of source
-     */
-    public void testThenAccept_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final NoopConsumer[] rs = new NoopConsumer[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
-        assertTrue(f.completeExceptionally(ex));
-        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedExceptionally(f, ex);
-        for (NoopConsumer r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenAccept result completes exceptionally if source cancelled
-     */
-    public void testThenAccept_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final NoopConsumer[] rs = new NoopConsumer[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
-        assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        checkCancelled(f);
-        for (NoopConsumer r : rs) r.assertNotInvoked();
-    }}
-
-    /**
-     * thenAccept result completes exceptionally if action does
-     */
-    public void testThenAccept_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final FailingConsumer[] rs = new FailingConsumer[4];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
-
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * thenCombine result completes normally after normal completion
-     * of sources
-     */
-    public void testThenCombine_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final SubtractFunction[] rs = new SubtractFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new SubtractFunction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Integer> h0 = m.thenCombine(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.thenCombine(fst, fst, rs[1]);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.thenCombine(fst, fst, rs[3]);
-        checkIncomplete(h0); rs[0].assertNotInvoked();
-        checkIncomplete(h2); rs[2].assertNotInvoked();
-        checkCompletedNormally(h1, subtract(w1, w1));
-        checkCompletedNormally(h3, subtract(w1, w1));
-        rs[1].assertValue(subtract(w1, w1));
-        rs[3].assertValue(subtract(w1, w1));
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Integer> h4 = m.thenCombine(f, g, rs[4]);
-
-        checkCompletedNormally(h0, subtract(v1, v2));
-        checkCompletedNormally(h2, subtract(v1, v2));
-        checkCompletedNormally(h4, subtract(v1, v2));
-        rs[0].assertValue(subtract(v1, v2));
-        rs[2].assertValue(subtract(v1, v2));
-        rs[4].assertValue(subtract(v1, v2));
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * thenCombine result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testThenCombine_exceptionalCompletion() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final SubtractFunction r1 = new SubtractFunction(m);
-        final SubtractFunction r2 = new SubtractFunction(m);
-        final SubtractFunction r3 = new SubtractFunction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.completeExceptionally(ex) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.completeExceptionally(ex);
-
-        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
-
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCompletedExceptionally(failFirst ? fst : snd, ex);
-    }}
-
-    /**
-     * thenCombine result completes exceptionally if either source cancelled
-     */
-    public void testThenCombine_sourceCancelled() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final SubtractFunction r1 = new SubtractFunction(m);
-        final SubtractFunction r2 = new SubtractFunction(m);
-        final SubtractFunction r3 = new SubtractFunction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.cancel(mayInterruptIfRunning) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.cancel(mayInterruptIfRunning);
-
-        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
-
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCancelled(failFirst ? fst : snd);
-    }}
-
-    /**
-     * thenCombine result completes exceptionally if action does
-     */
-    public void testThenCombine_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingBiFunction r1 = new FailingBiFunction(m);
-        final FailingBiFunction r2 = new FailingBiFunction(m);
-        final FailingBiFunction r3 = new FailingBiFunction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
-
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        r1.assertInvoked();
-        r2.assertInvoked();
-        r3.assertInvoked();
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * thenAcceptBoth result completes normally after normal
-     * completion of sources
-     */
-    public void testThenAcceptBoth_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final SubtractAction r1 = new SubtractAction(m);
-        final SubtractAction r2 = new SubtractAction(m);
-        final SubtractAction r3 = new SubtractAction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
-
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        r1.assertValue(subtract(v1, v2));
-        r2.assertValue(subtract(v1, v2));
-        r3.assertValue(subtract(v1, v2));
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * thenAcceptBoth result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testThenAcceptBoth_exceptionalCompletion() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final SubtractAction r1 = new SubtractAction(m);
-        final SubtractAction r2 = new SubtractAction(m);
-        final SubtractAction r3 = new SubtractAction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.completeExceptionally(ex) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.completeExceptionally(ex);
-
-        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
-
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCompletedExceptionally(failFirst ? fst : snd, ex);
-    }}
-
-    /**
-     * thenAcceptBoth result completes exceptionally if either source cancelled
-     */
-    public void testThenAcceptBoth_sourceCancelled() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final SubtractAction r1 = new SubtractAction(m);
-        final SubtractAction r2 = new SubtractAction(m);
-        final SubtractAction r3 = new SubtractAction(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.cancel(mayInterruptIfRunning) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.cancel(mayInterruptIfRunning);
-
-        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
-
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCancelled(failFirst ? fst : snd);
-    }}
-
-    /**
-     * thenAcceptBoth result completes exceptionally if action does
-     */
-    public void testThenAcceptBoth_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingBiConsumer r1 = new FailingBiConsumer(m);
-        final FailingBiConsumer r2 = new FailingBiConsumer(m);
-        final FailingBiConsumer r3 = new FailingBiConsumer(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
-
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        r1.assertInvoked();
-        r2.assertInvoked();
-        r3.assertInvoked();
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * runAfterBoth result completes normally after normal
-     * completion of sources
-     */
-    public void testRunAfterBoth_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final Noop r1 = new Noop(m);
-        final Noop r2 = new Noop(m);
-        final Noop r3 = new Noop(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
-
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        r1.assertInvoked();
-        r2.assertInvoked();
-        r3.assertInvoked();
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * runAfterBoth result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testRunAfterBoth_exceptionalCompletion() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final Noop r1 = new Noop(m);
-        final Noop r2 = new Noop(m);
-        final Noop r3 = new Noop(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.completeExceptionally(ex) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.completeExceptionally(ex);
-
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
-
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCompletedExceptionally(failFirst ? fst : snd, ex);
-    }}
-
-    /**
-     * runAfterBoth result completes exceptionally if either source cancelled
-     */
-    public void testRunAfterBoth_sourceCancelled() throws Throwable {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean fFirst : new boolean[] { true, false })
-        for (boolean failFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final Noop r1 = new Noop(m);
-        final Noop r2 = new Noop(m);
-        final Noop r3 = new Noop(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Callable<Boolean> complete1 = failFirst ?
-            () -> fst.cancel(mayInterruptIfRunning) :
-            () -> fst.complete(v1);
-        final Callable<Boolean> complete2 = failFirst ?
-            () -> snd.complete(v1) :
-            () -> snd.cancel(mayInterruptIfRunning);
-
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
-        assertTrue(complete1.call());
-        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
-        checkIncomplete(h1);
-        checkIncomplete(h2);
-        assertTrue(complete2.call());
-        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
-
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        r1.assertNotInvoked();
-        r2.assertNotInvoked();
-        r3.assertNotInvoked();
-        checkCompletedNormally(failFirst ? snd : fst, v1);
-        checkCancelled(failFirst ? fst : snd);
-    }}
-
-    /**
-     * runAfterBoth result completes exceptionally if action does
-     */
-    public void testRunAfterBoth_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingRunnable r1 = new FailingRunnable(m);
-        final FailingRunnable r2 = new FailingRunnable(m);
-        final FailingRunnable r3 = new FailingRunnable(m);
-
-        final CompletableFuture<Integer> fst =  fFirst ? f : g;
-        final CompletableFuture<Integer> snd = !fFirst ? f : g;
-        final Integer w1 =  fFirst ? v1 : v2;
-        final Integer w2 = !fFirst ? v1 : v2;
-
-        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
-        assertTrue(fst.complete(w1));
-        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
-        assertTrue(snd.complete(w2));
-        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
-
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        r1.assertInvoked();
-        r2.assertInvoked();
-        r3.assertInvoked();
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * applyToEither result completes normally after normal completion
-     * of either source
-     */
-    public void testApplyToEither_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.complete(v1);
-        checkCompletedNormally(h0, inc(v1));
-        checkCompletedNormally(h1, inc(v1));
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-        checkCompletedNormally(h2, inc(v1));
-        checkCompletedNormally(h3, inc(v1));
-        g.complete(v2);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
-        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
-        rs[4].assertValue(h4.join());
-        rs[5].assertValue(h5.join());
-        assertTrue(Objects.equals(inc(v1), h4.join()) ||
-                   Objects.equals(inc(v2), h4.join()));
-        assertTrue(Objects.equals(inc(v1), h5.join()) ||
-                   Objects.equals(inc(v2), h5.join()));
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-        checkCompletedNormally(h0, inc(v1));
-        checkCompletedNormally(h1, inc(v1));
-        checkCompletedNormally(h2, inc(v1));
-        checkCompletedNormally(h3, inc(v1));
-        for (int i = 0; i < 4; i++) rs[i].assertValue(inc(v1));
-    }}
-
-    /**
-     * applyToEither result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testApplyToEither_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final IncFunction[] rs = new IncFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.completeExceptionally(ex);
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        g.complete(v1);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
-        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
-        try {
-            assertEquals(inc(v1), h4.join());
-            rs[4].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h4, ex);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h5.join());
-            rs[5].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h5, ex);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCompletedExceptionally(f, ex);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedWithWrappedException(h4, ex);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    public void testApplyToEither_exceptionalCompletion2() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final IncFunction[] rs = new IncFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-
-        // unspecified behavior - both source completions available
-        try {
-            assertEquals(inc(v1), h0.join());
-            rs[0].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h0, ex);
-            rs[0].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h1.join());
-            rs[1].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h1, ex);
-            rs[1].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h2.join());
-            rs[2].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h2, ex);
-            rs[2].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h3.join());
-            rs[3].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h3, ex);
-            rs[3].assertNotInvoked();
-        }
-
-        checkCompletedNormally(f, v1);
-        checkCompletedExceptionally(g, ex);
-    }}
-
-    /**
-     * applyToEither result completes exceptionally if either source cancelled
-     */
-    public void testApplyToEither_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.cancel(mayInterruptIfRunning);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        g.complete(v1);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
-        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
-        try {
-            assertEquals(inc(v1), h4.join());
-            rs[4].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h4);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h5.join());
-            rs[5].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h5);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCancelled(f);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    public void testApplyToEither_sourceCancelled2() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final IncFunction[] rs = new IncFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        assertTrue(fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
-        assertTrue(!fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-
-        // unspecified behavior - both source completions available
-        try {
-            assertEquals(inc(v1), h0.join());
-            rs[0].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h0);
-            rs[0].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h1.join());
-            rs[1].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h1);
-            rs[1].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h2.join());
-            rs[2].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h2);
-            rs[2].assertNotInvoked();
-        }
-        try {
-            assertEquals(inc(v1), h3.join());
-            rs[3].assertValue(inc(v1));
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h3);
-            rs[3].assertNotInvoked();
-        }
-
-        checkCompletedNormally(f, v1);
-        checkCancelled(g);
-    }}
-
-    /**
-     * applyToEither result completes exceptionally if action does
-     */
-    public void testApplyToEither_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingFunction[] rs = new FailingFunction[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);
-
-        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
-        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
-        f.complete(v1);
-        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
-        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
-
-        g.complete(v2);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
-        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
-
-        checkCompletedWithWrappedCFException(h4);
-        assertTrue(Objects.equals(v1, rs[4].value) ||
-                   Objects.equals(v2, rs[4].value));
-        checkCompletedWithWrappedCFException(h5);
-        assertTrue(Objects.equals(v1, rs[5].value) ||
-                   Objects.equals(v2, rs[5].value));
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * acceptEither result completes normally after normal completion
-     * of either source
-     */
-    public void testAcceptEither_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final NoopConsumer[] rs = new NoopConsumer[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.complete(v1);
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        rs[0].assertValue(v1);
-        rs[1].assertValue(v1);
-        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        rs[2].assertValue(v1);
-        rs[3].assertValue(v1);
-        g.complete(v2);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
-        checkCompletedNormally(h4, null);
-        checkCompletedNormally(h5, null);
-        assertTrue(Objects.equals(v1, rs[4].value) ||
-                   Objects.equals(v2, rs[4].value));
-        assertTrue(Objects.equals(v1, rs[5].value) ||
-                   Objects.equals(v2, rs[5].value));
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
-    }}
-
-    /**
-     * acceptEither result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testAcceptEither_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final NoopConsumer[] rs = new NoopConsumer[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.completeExceptionally(ex);
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-
-        g.complete(v1);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
-        try {
-            assertNull(h4.join());
-            rs[4].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h4, ex);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertNull(h5.join());
-            rs[5].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h5, ex);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCompletedExceptionally(f, ex);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedWithWrappedException(h4, ex);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    public void testAcceptEither_exceptionalCompletion2() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final NoopConsumer[] rs = new NoopConsumer[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
-        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-
-        // unspecified behavior - both source completions available
-        try {
-            assertEquals(null, h0.join());
-            rs[0].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h0, ex);
-            rs[0].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h1.join());
-            rs[1].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h1, ex);
-            rs[1].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h2.join());
-            rs[2].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h2, ex);
-            rs[2].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h3.join());
-            rs[3].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h3, ex);
-            rs[3].assertNotInvoked();
-        }
-
-        checkCompletedNormally(f, v1);
-        checkCompletedExceptionally(g, ex);
-    }}
-
-    /**
-     * acceptEither result completes exceptionally if either source cancelled
-     */
-    public void testAcceptEither_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final NoopConsumer[] rs = new NoopConsumer[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.cancel(mayInterruptIfRunning);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-
-        g.complete(v1);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
-        try {
-            assertNull(h4.join());
-            rs[4].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h4);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertNull(h5.join());
-            rs[5].assertValue(v1);
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h5);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCancelled(f);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    /**
-     * acceptEither result completes exceptionally if action does
-     */
-    public void testAcceptEither_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingConsumer[] rs = new FailingConsumer[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);
-
-        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
-        f.complete(v1);
-        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
-
-        g.complete(v2);
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
-
-        checkCompletedWithWrappedCFException(h4);
-        assertTrue(Objects.equals(v1, rs[4].value) ||
-                   Objects.equals(v2, rs[4].value));
-        checkCompletedWithWrappedCFException(h5);
-        assertTrue(Objects.equals(v1, rs[5].value) ||
-                   Objects.equals(v2, rs[5].value));
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-    }}
-
-    /**
-     * runAfterEither result completes normally after normal completion
-     * of either source
-     */
-    public void testRunAfterEither_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.complete(v1);
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        rs[0].assertInvoked();
-        rs[1].assertInvoked();
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        rs[2].assertInvoked();
-        rs[3].assertInvoked();
-
-        g.complete(v2);
-
-        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-        checkCompletedNormally(h0, null);
-        checkCompletedNormally(h1, null);
-        checkCompletedNormally(h2, null);
-        checkCompletedNormally(h3, null);
-        checkCompletedNormally(h4, null);
-        checkCompletedNormally(h5, null);
-        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
-    }}
-
-    /**
-     * runAfterEither result completes exceptionally after exceptional
-     * completion of either source
-     */
-    public void testRunAfterEither_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        assertTrue(f.completeExceptionally(ex));
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-
-        assertTrue(g.complete(v1));
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
-        try {
-            assertNull(h4.join());
-            rs[4].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h4, ex);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertNull(h5.join());
-            rs[5].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h5, ex);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCompletedExceptionally(f, ex);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedException(h0, ex);
-        checkCompletedWithWrappedException(h1, ex);
-        checkCompletedWithWrappedException(h2, ex);
-        checkCompletedWithWrappedException(h3, ex);
-        checkCompletedWithWrappedException(h4, ex);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    public void testRunAfterEither_exceptionalCompletion2() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean fFirst : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CFException ex = new CFException();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
-        assertTrue( fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-
-        // unspecified behavior - both source completions available
-        try {
-            assertEquals(null, h0.join());
-            rs[0].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h0, ex);
-            rs[0].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h1.join());
-            rs[1].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h1, ex);
-            rs[1].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h2.join());
-            rs[2].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h2, ex);
-            rs[2].assertNotInvoked();
-        }
-        try {
-            assertEquals(null, h3.join());
-            rs[3].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedException(h3, ex);
-            rs[3].assertNotInvoked();
-        }
-
-        checkCompletedNormally(f, v1);
-        checkCompletedExceptionally(g, ex);
-    }}
-
-    /**
-     * runAfterEither result completes exceptionally if either source cancelled
-     */
-    public void testRunAfterEither_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final Noop[] rs = new Noop[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
-
-        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
-        checkIncomplete(h0);
-        checkIncomplete(h1);
-        rs[0].assertNotInvoked();
-        rs[1].assertNotInvoked();
-        f.cancel(mayInterruptIfRunning);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-
-        assertTrue(g.complete(v1));
-
-        // unspecified behavior - both source completions available
-        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
-        try {
-            assertNull(h4.join());
-            rs[4].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h4);
-            rs[4].assertNotInvoked();
-        }
-        try {
-            assertNull(h5.join());
-            rs[5].assertInvoked();
-        } catch (CompletionException ok) {
-            checkCompletedWithWrappedCancellationException(h5);
-            rs[5].assertNotInvoked();
-        }
-
-        checkCancelled(f);
-        checkCompletedNormally(g, v1);
-        checkCompletedWithWrappedCancellationException(h0);
-        checkCompletedWithWrappedCancellationException(h1);
-        checkCompletedWithWrappedCancellationException(h2);
-        checkCompletedWithWrappedCancellationException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
-    }}
-
-    /**
-     * runAfterEither result completes exceptionally if action does
-     */
-    public void testRunAfterEither_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (Integer v1 : new Integer[] { 1, null })
-        for (Integer v2 : new Integer[] { 2, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final FailingRunnable[] rs = new FailingRunnable[6];
-        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);
-
-        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
-        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
-        assertTrue(f.complete(v1));
-        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
-        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        for (int i = 0; i < 4; i++) rs[i].assertInvoked();
-        assertTrue(g.complete(v2));
-        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
-        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
-        checkCompletedWithWrappedCFException(h4);
-        checkCompletedWithWrappedCFException(h5);
-
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v2);
-        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
-    }}
-
-    /**
-     * thenCompose result completes normally after normal completion of source
-     */
-    public void testThenCompose_normalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFutureInc r = new CompletableFutureInc(m);
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.thenCompose(f, r);
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedNormally(g, inc(v1));
-        checkCompletedNormally(f, v1);
-        r.assertValue(v1);
-    }}
-
-    /**
-     * thenCompose result completes exceptionally after exceptional
-     * completion of source
-     */
-    public void testThenCompose_exceptionalCompletion() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-    {
-        final CFException ex = new CFException();
-        final CompletableFutureInc r = new CompletableFutureInc(m);
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        if (!createIncomplete) f.completeExceptionally(ex);
-        final CompletableFuture<Integer> g = m.thenCompose(f, r);
-        if (createIncomplete) f.completeExceptionally(ex);
-
-        checkCompletedWithWrappedException(g, ex);
-        checkCompletedExceptionally(f, ex);
-        r.assertNotInvoked();
-    }}
-
-    /**
-     * thenCompose result completes exceptionally if action does
-     */
-    public void testThenCompose_actionFailed() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final FailingCompletableFutureFunction r
-            = new FailingCompletableFutureFunction(m);
-        if (!createIncomplete) assertTrue(f.complete(v1));
-        final CompletableFuture<Integer> g = m.thenCompose(f, r);
-        if (createIncomplete) assertTrue(f.complete(v1));
-
-        checkCompletedWithWrappedCFException(g);
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * thenCompose result completes exceptionally if source cancelled
-     */
-    public void testThenCompose_sourceCancelled() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (boolean createIncomplete : new boolean[] { true, false })
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-    {
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFutureInc r = new CompletableFutureInc(m);
-        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
-        final CompletableFuture<Integer> g = m.thenCompose(f, r);
-        if (createIncomplete) {
-            checkIncomplete(g);
-            assertTrue(f.cancel(mayInterruptIfRunning));
-        }
-
-        checkCompletedWithWrappedCancellationException(g);
-        checkCancelled(f);
-    }}
-
-    /**
-     * thenCompose result completes exceptionally if the result of the action does
-     */
-    public void testThenCompose_actionReturnsFailingFuture() {
-        for (ExecutionMode m : ExecutionMode.values())
-        for (int order = 0; order < 6; order++)
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> f = new CompletableFuture<>();
-        final CompletableFuture<Integer> g = new CompletableFuture<>();
-        final CompletableFuture<Integer> h;
-        // Test all permutations of orders
-        switch (order) {
-        case 0:
-            assertTrue(f.complete(v1));
-            assertTrue(g.completeExceptionally(ex));
-            h = m.thenCompose(f, (x -> g));
-            break;
-        case 1:
-            assertTrue(f.complete(v1));
-            h = m.thenCompose(f, (x -> g));
-            assertTrue(g.completeExceptionally(ex));
-            break;
-        case 2:
-            assertTrue(g.completeExceptionally(ex));
-            assertTrue(f.complete(v1));
-            h = m.thenCompose(f, (x -> g));
-            break;
-        case 3:
-            assertTrue(g.completeExceptionally(ex));
-            h = m.thenCompose(f, (x -> g));
-            assertTrue(f.complete(v1));
-            break;
-        case 4:
-            h = m.thenCompose(f, (x -> g));
-            assertTrue(f.complete(v1));
-            assertTrue(g.completeExceptionally(ex));
-            break;
-        case 5:
-            h = m.thenCompose(f, (x -> g));
-            assertTrue(f.complete(v1));
-            assertTrue(g.completeExceptionally(ex));
-            break;
-        default: throw new AssertionError();
-        }
-
-        checkCompletedExceptionally(g, ex);
-        checkCompletedWithWrappedException(h, ex);
-        checkCompletedNormally(f, v1);
-    }}
-
-    // other static methods
-
-    /**
-     * allOf(no component futures) returns a future completed normally
-     * with the value null
-     */
-    public void testAllOf_empty() throws Exception {
-        CompletableFuture<Void> f = CompletableFuture.allOf();
-        checkCompletedNormally(f, null);
-    }
-
-    /**
-     * allOf returns a future completed normally with the value null
-     * when all components complete normally
-     */
-    public void testAllOf_normal() throws Exception {
-        for (int k = 1; k < 10; k++) {
-            CompletableFuture<Integer>[] fs
-                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
-            for (int i = 0; i < k; i++)
-                fs[i] = new CompletableFuture<>();
-            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
-            for (int i = 0; i < k; i++) {
-                checkIncomplete(f);
-                checkIncomplete(CompletableFuture.allOf(fs));
-                fs[i].complete(one);
-            }
-            checkCompletedNormally(f, null);
-            checkCompletedNormally(CompletableFuture.allOf(fs), null);
-        }
-    }
-
-    public void testAllOf_backwards() throws Exception {
-        for (int k = 1; k < 10; k++) {
-            CompletableFuture<Integer>[] fs
-                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
-            for (int i = 0; i < k; i++)
-                fs[i] = new CompletableFuture<>();
-            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
-            for (int i = k - 1; i >= 0; i--) {
-                checkIncomplete(f);
-                checkIncomplete(CompletableFuture.allOf(fs));
-                fs[i].complete(one);
-            }
-            checkCompletedNormally(f, null);
-            checkCompletedNormally(CompletableFuture.allOf(fs), null);
-        }
-    }
-
-    public void testAllOf_exceptional() throws Exception {
-        for (int k = 1; k < 10; k++) {
-            CompletableFuture<Integer>[] fs
-                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
-            CFException ex = new CFException();
-            for (int i = 0; i < k; i++)
-                fs[i] = new CompletableFuture<>();
-            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
-            for (int i = 0; i < k; i++) {
-                checkIncomplete(f);
-                checkIncomplete(CompletableFuture.allOf(fs));
-                if (i != k / 2) {
-                    fs[i].complete(i);
-                    checkCompletedNormally(fs[i], i);
-                } else {
-                    fs[i].completeExceptionally(ex);
-                    checkCompletedExceptionally(fs[i], ex);
-                }
-            }
-            checkCompletedWithWrappedException(f, ex);
-            checkCompletedWithWrappedException(CompletableFuture.allOf(fs), ex);
-        }
-    }
-
-    /**
-     * anyOf(no component futures) returns an incomplete future
-     */
-    public void testAnyOf_empty() throws Exception {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Object> f = CompletableFuture.anyOf();
-        checkIncomplete(f);
-
-        f.complete(v1);
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * anyOf returns a future completed normally with a value when
-     * a component future does
-     */
-    public void testAnyOf_normal() throws Exception {
-        for (int k = 0; k < 10; k++) {
-            CompletableFuture[] fs = new CompletableFuture[k];
-            for (int i = 0; i < k; i++)
-                fs[i] = new CompletableFuture<>();
-            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
-            checkIncomplete(f);
-            for (int i = 0; i < k; i++) {
-                fs[i].complete(i);
-                checkCompletedNormally(f, 0);
-                int x = (int) CompletableFuture.anyOf(fs).join();
-                assertTrue(0 <= x && x <= i);
-            }
-        }
-    }
-    public void testAnyOf_normal_backwards() throws Exception {
-        for (int k = 0; k < 10; k++) {
-            CompletableFuture[] fs = new CompletableFuture[k];
-            for (int i = 0; i < k; i++)
-                fs[i] = new CompletableFuture<>();
-            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
-            checkIncomplete(f);
-            for (int i = k - 1; i >= 0; i--) {
-                fs[i].complete(i);
-                checkCompletedNormally(f, k - 1);
-                int x = (int) CompletableFuture.anyOf(fs).join();
-                assertTrue(i <= x && x <= k - 1);
-            }
-        }
-    }
-
-    /**
-     * anyOf result completes exceptionally when any component does.
-     */
-    public void testAnyOf_exceptional() throws Exception {
-        for (int k = 0; k < 10; k++) {
-            CompletableFuture[] fs = new CompletableFuture[k];
-            CFException[] exs = new CFException[k];
-            for (int i = 0; i < k; i++) {
-                fs[i] = new CompletableFuture<>();
-                exs[i] = new CFException();
-            }
-            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
-            checkIncomplete(f);
-            for (int i = 0; i < k; i++) {
-                fs[i].completeExceptionally(exs[i]);
-                checkCompletedWithWrappedException(f, exs[0]);
-                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
-            }
-        }
-    }
-
-    public void testAnyOf_exceptional_backwards() throws Exception {
-        for (int k = 0; k < 10; k++) {
-            CompletableFuture[] fs = new CompletableFuture[k];
-            CFException[] exs = new CFException[k];
-            for (int i = 0; i < k; i++) {
-                fs[i] = new CompletableFuture<>();
-                exs[i] = new CFException();
-            }
-            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
-            checkIncomplete(f);
-            for (int i = k - 1; i >= 0; i--) {
-                fs[i].completeExceptionally(exs[i]);
-                checkCompletedWithWrappedException(f, exs[k - 1]);
-                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
-            }
-        }
-    }
-
-    /**
-     * Completion methods throw NullPointerException with null arguments
-     */
-    public void testNPE() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = new CompletableFuture<>();
-        CompletableFuture<Integer> nullFuture = (CompletableFuture<Integer>)null;
-        ThreadExecutor exec = new ThreadExecutor();
-
-        Runnable[] throwingActions = {
-            () -> CompletableFuture.supplyAsync(null),
-            () -> CompletableFuture.supplyAsync(null, exec),
-            () -> CompletableFuture.supplyAsync(new IntegerSupplier(ExecutionMode.SYNC, 42), null),
-
-            () -> CompletableFuture.runAsync(null),
-            () -> CompletableFuture.runAsync(null, exec),
-            () -> CompletableFuture.runAsync(() -> {}, null),
-
-            () -> f.completeExceptionally(null),
-
-            () -> f.thenApply(null),
-            () -> f.thenApplyAsync(null),
-            () -> f.thenApplyAsync((x) -> x, null),
-            () -> f.thenApplyAsync(null, exec),
-
-            () -> f.thenAccept(null),
-            () -> f.thenAcceptAsync(null),
-            () -> f.thenAcceptAsync((x) -> {} , null),
-            () -> f.thenAcceptAsync(null, exec),
-
-            () -> f.thenRun(null),
-            () -> f.thenRunAsync(null),
-            () -> f.thenRunAsync(() -> {} , null),
-            () -> f.thenRunAsync(null, exec),
-
-            () -> f.thenCombine(g, null),
-            () -> f.thenCombineAsync(g, null),
-            () -> f.thenCombineAsync(g, null, exec),
-            () -> f.thenCombine(nullFuture, (x, y) -> x),
-            () -> f.thenCombineAsync(nullFuture, (x, y) -> x),
-            () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec),
-            () -> f.thenCombineAsync(g, (x, y) -> x, null),
-
-            () -> f.thenAcceptBoth(g, null),
-            () -> f.thenAcceptBothAsync(g, null),
-            () -> f.thenAcceptBothAsync(g, null, exec),
-            () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}),
-            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}),
-            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec),
-            () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null),
-
-            () -> f.runAfterBoth(g, null),
-            () -> f.runAfterBothAsync(g, null),
-            () -> f.runAfterBothAsync(g, null, exec),
-            () -> f.runAfterBoth(nullFuture, () -> {}),
-            () -> f.runAfterBothAsync(nullFuture, () -> {}),
-            () -> f.runAfterBothAsync(nullFuture, () -> {}, exec),
-            () -> f.runAfterBothAsync(g, () -> {}, null),
-
-            () -> f.applyToEither(g, null),
-            () -> f.applyToEitherAsync(g, null),
-            () -> f.applyToEitherAsync(g, null, exec),
-            () -> f.applyToEither(nullFuture, (x) -> x),
-            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
-            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
-            () -> f.applyToEitherAsync(g, (x) -> x, null),
-
-            () -> f.acceptEither(g, null),
-            () -> f.acceptEitherAsync(g, null),
-            () -> f.acceptEitherAsync(g, null, exec),
-            () -> f.acceptEither(nullFuture, (x) -> {}),
-            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
-            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
-            () -> f.acceptEitherAsync(g, (x) -> {}, null),
-
-            () -> f.runAfterEither(g, null),
-            () -> f.runAfterEitherAsync(g, null),
-            () -> f.runAfterEitherAsync(g, null, exec),
-            () -> f.runAfterEither(nullFuture, () -> {}),
-            () -> f.runAfterEitherAsync(nullFuture, () -> {}),
-            () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec),
-            () -> f.runAfterEitherAsync(g, () -> {}, null),
-
-            () -> f.thenCompose(null),
-            () -> f.thenComposeAsync(null),
-            () -> f.thenComposeAsync(new CompletableFutureInc(ExecutionMode.EXECUTOR), null),
-            () -> f.thenComposeAsync(null, exec),
-
-            () -> f.exceptionally(null),
-
-            () -> f.handle(null),
-
-            () -> CompletableFuture.allOf((CompletableFuture<?>)null),
-            () -> CompletableFuture.allOf((CompletableFuture<?>[])null),
-            () -> CompletableFuture.allOf(f, null),
-            () -> CompletableFuture.allOf(null, f),
-
-            () -> CompletableFuture.anyOf((CompletableFuture<?>)null),
-            () -> CompletableFuture.anyOf((CompletableFuture<?>[])null),
-            () -> CompletableFuture.anyOf(f, null),
-            () -> CompletableFuture.anyOf(null, f),
-
-            () -> f.obtrudeException(null),
-
-            () -> CompletableFuture.delayedExecutor(1L, SECONDS, null),
-            () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()),
-            () -> CompletableFuture.delayedExecutor(1L, null),
-
-            () -> f.orTimeout(1L, null),
-            () -> f.completeOnTimeout(42, 1L, null),
-
-            () -> CompletableFuture.failedFuture(null),
-            () -> CompletableFuture.failedStage(null),
-        };
-
-        assertThrows(NullPointerException.class, throwingActions);
-        assertEquals(0, exec.count.get());
-    }
-
-    /**
-     * toCompletableFuture returns this CompletableFuture.
-     */
-    public void testToCompletableFuture() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        assertSame(f, f.toCompletableFuture());
-    }
-
-    // jdk9
-
-    /**
-     * newIncompleteFuture returns an incomplete CompletableFuture
-     */
-    public void testNewIncompleteFuture() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = f.newIncompleteFuture();
-        checkIncomplete(f);
-        checkIncomplete(g);
-        f.complete(v1);
-        checkCompletedNormally(f, v1);
-        checkIncomplete(g);
-        g.complete(v1);
-        checkCompletedNormally(g, v1);
-        assertSame(g.getClass(), CompletableFuture.class);
-    }}
-
-    /**
-     * completedStage returns a completed CompletionStage
-     */
-    public void testCompletedStage() {
-        AtomicInteger x = new AtomicInteger(0);
-        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
-        CompletionStage<Integer> f = CompletableFuture.completedStage(1);
-        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
-        assertEquals(x.get(), 1);
-        assertNull(r.get());
-    }
-
-    /**
-     * defaultExecutor by default returns the commonPool if
-     * it supports more than one thread.
-     */
-    public void testDefaultExecutor() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        Executor e = f.defaultExecutor();
-        Executor c = ForkJoinPool.commonPool();
-        if (ForkJoinPool.getCommonPoolParallelism() > 1)
-            assertSame(e, c);
-        else
-            assertNotSame(e, c);
-    }
-
-    /**
-     * failedFuture returns a CompletableFuture completed
-     * exceptionally with the given Exception
-     */
-    public void testFailedFuture() {
-        CFException ex = new CFException();
-        CompletableFuture<Integer> f = CompletableFuture.failedFuture(ex);
-        checkCompletedExceptionally(f, ex);
-    }
-
-    /**
-     * failedFuture(null) throws NPE
-     */
-    public void testFailedFuture_null() {
-        try {
-            CompletableFuture<Integer> f = CompletableFuture.failedFuture(null);
-            shouldThrow();
-        } catch (NullPointerException success) {}
-    }
-
-    /**
-     * copy returns a CompletableFuture that is completed normally,
-     * with the same value, when source is.
-     */
-    public void testCopy() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = f.copy();
-        checkIncomplete(f);
-        checkIncomplete(g);
-        f.complete(1);
-        checkCompletedNormally(f, 1);
-        checkCompletedNormally(g, 1);
-    }
-
-    /**
-     * copy returns a CompletableFuture that is completed exceptionally
-     * when source is.
-     */
-    public void testCopy2() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = f.copy();
-        checkIncomplete(f);
-        checkIncomplete(g);
-        CFException ex = new CFException();
-        f.completeExceptionally(ex);
-        checkCompletedExceptionally(f, ex);
-        checkCompletedWithWrappedException(g, ex);
-    }
-
-    /**
-     * minimalCompletionStage returns a CompletableFuture that is
-     * completed normally, with the same value, when source is.
-     */
-    public void testMinimalCompletionStage() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletionStage<Integer> g = f.minimalCompletionStage();
-        AtomicInteger x = new AtomicInteger(0);
-        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
-        checkIncomplete(f);
-        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
-        f.complete(1);
-        checkCompletedNormally(f, 1);
-        assertEquals(x.get(), 1);
-        assertNull(r.get());
-    }
-
-    /**
-     * minimalCompletionStage returns a CompletableFuture that is
-     * completed exceptionally when source is.
-     */
-    public void testMinimalCompletionStage2() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletionStage<Integer> g = f.minimalCompletionStage();
-        AtomicInteger x = new AtomicInteger(0);
-        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
-        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
-        checkIncomplete(f);
-        CFException ex = new CFException();
-        f.completeExceptionally(ex);
-        checkCompletedExceptionally(f, ex);
-        assertEquals(x.get(), 0);
-        assertEquals(r.get().getCause(), ex);
-    }
-
-    /**
-     * failedStage returns a CompletionStage completed
-     * exceptionally with the given Exception
-     */
-    public void testFailedStage() {
-        CFException ex = new CFException();
-        CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
-        AtomicInteger x = new AtomicInteger(0);
-        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
-        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
-        assertEquals(x.get(), 0);
-        assertEquals(r.get(), ex);
-    }
-
-    /**
-     * completeAsync completes with value of given supplier
-     */
-    public void testCompleteAsync() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        f.completeAsync(() -> v1);
-        f.join();
-        checkCompletedNormally(f, v1);
-    }}
-
-    /**
-     * completeAsync completes exceptionally if given supplier throws
-     */
-    public void testCompleteAsync2() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CFException ex = new CFException();
-        f.completeAsync(() -> {if (true) throw ex; return 1;});
-        try {
-            f.join();
-            shouldThrow();
-        } catch (CompletionException success) {}
-        checkCompletedWithWrappedException(f, ex);
-    }
-
-    /**
-     * completeAsync with given executor completes with value of given supplier
-     */
-    public void testCompleteAsync3() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        ThreadExecutor executor = new ThreadExecutor();
-        f.completeAsync(() -> v1, executor);
-        assertSame(v1, f.join());
-        checkCompletedNormally(f, v1);
-        assertEquals(1, executor.count.get());
-    }}
-
-    /**
-     * completeAsync with given executor completes exceptionally if
-     * given supplier throws
-     */
-    public void testCompleteAsync4() {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CFException ex = new CFException();
-        ThreadExecutor executor = new ThreadExecutor();
-        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
-        try {
-            f.join();
-            shouldThrow();
-        } catch (CompletionException success) {}
-        checkCompletedWithWrappedException(f, ex);
-        assertEquals(1, executor.count.get());
-    }
-
-    /**
-     * orTimeout completes with TimeoutException if not complete
-     */
-    public void testOrTimeout_timesOut() {
-        long timeoutMillis = timeoutMillis();
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        long startTime = System.nanoTime();
-        f.orTimeout(timeoutMillis, MILLISECONDS);
-        checkCompletedWithTimeoutException(f);
-        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-    }
-
-    /**
-     * orTimeout completes normally if completed before timeout
-     */
-    public void testOrTimeout_completed() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = new CompletableFuture<>();
-        long startTime = System.nanoTime();
-        f.complete(v1);
-        f.orTimeout(LONG_DELAY_MS, MILLISECONDS);
-        g.orTimeout(LONG_DELAY_MS, MILLISECONDS);
-        g.complete(v1);
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v1);
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
-    }}
-
-    /**
-     * completeOnTimeout completes with given value if not complete
-     */
-    public void testCompleteOnTimeout_timesOut() {
-        testInParallel(() -> testCompleteOnTimeout_timesOut(42),
-                       () -> testCompleteOnTimeout_timesOut(null));
-    }
-
-    public void testCompleteOnTimeout_timesOut(Integer v) {
-        long timeoutMillis = timeoutMillis();
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        long startTime = System.nanoTime();
-        f.completeOnTimeout(v, timeoutMillis, MILLISECONDS);
-        assertSame(v, f.join());
-        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-        f.complete(99);         // should have no effect
-        checkCompletedNormally(f, v);
-    }
-
-    /**
-     * completeOnTimeout has no effect if completed within timeout
-     */
-    public void testCompleteOnTimeout_completed() {
-        for (Integer v1 : new Integer[] { 1, null })
-    {
-        CompletableFuture<Integer> f = new CompletableFuture<>();
-        CompletableFuture<Integer> g = new CompletableFuture<>();
-        long startTime = System.nanoTime();
-        f.complete(v1);
-        f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
-        g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
-        g.complete(v1);
-        checkCompletedNormally(f, v1);
-        checkCompletedNormally(g, v1);
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
-    }}
-
-    /**
-     * delayedExecutor returns an executor that delays submission
-     */
-    public void testDelayedExecutor() {
-        testInParallel(() -> testDelayedExecutor(null, null),
-                       () -> testDelayedExecutor(null, 1),
-                       () -> testDelayedExecutor(new ThreadExecutor(), 1),
-                       () -> testDelayedExecutor(new ThreadExecutor(), 1));
-    }
-
-    public void testDelayedExecutor(Executor executor, Integer v) throws Exception {
-        long timeoutMillis = timeoutMillis();
-        // Use an "unreasonably long" long timeout to catch lingering threads
-        long longTimeoutMillis = 1000 * 60 * 60 * 24;
-        final Executor delayer, longDelayer;
-        if (executor == null) {
-            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS);
-            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS);
-        } else {
-            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS, executor);
-            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS, executor);
-        }
-        long startTime = System.nanoTime();
-        CompletableFuture<Integer> f =
-            CompletableFuture.supplyAsync(() -> v, delayer);
-        CompletableFuture<Integer> g =
-            CompletableFuture.supplyAsync(() -> v, longDelayer);
-
-        assertNull(g.getNow(null));
-
-        assertSame(v, f.get(LONG_DELAY_MS, MILLISECONDS));
-        long millisElapsed = millisElapsedSince(startTime);
-        assertTrue(millisElapsed >= timeoutMillis);
-        assertTrue(millisElapsed < LONG_DELAY_MS / 2);
-
-        checkCompletedNormally(f, v);
-
-        checkIncomplete(g);
-        assertTrue(g.cancel(true));
-    }
-
-    //--- tests of implementation details; not part of official tck ---
-
-    Object resultOf(CompletableFuture<?> f) {
-        try {
-            java.lang.reflect.Field resultField
-                = CompletableFuture.class.getDeclaredField("result");
-            resultField.setAccessible(true);
-            return resultField.get(f);
-        } catch (Throwable t) { throw new AssertionError(t); }
-    }
-
-    public void testExceptionPropagationReusesResultObject() {
-        if (!testImplementationDetails) return;
-        for (ExecutionMode m : ExecutionMode.values())
-    {
-        final CFException ex = new CFException();
-        final CompletableFuture<Integer> v42 = CompletableFuture.completedFuture(42);
-        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
-
-        List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
-            = new ArrayList<>();
-
-        funs.add((y) -> m.thenRun(y, new Noop(m)));
-        funs.add((y) -> m.thenAccept(y, new NoopConsumer(m)));
-        funs.add((y) -> m.thenApply(y, new IncFunction(m)));
-
-        funs.add((y) -> m.runAfterEither(y, incomplete, new Noop(m)));
-        funs.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m)));
-        funs.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m)));
-
-        funs.add((y) -> m.runAfterBoth(y, v42, new Noop(m)));
-        funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
-        funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));
-
-        funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
-
-        funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));
-
-        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {y, v42}));
-        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {y, incomplete}));
-
-        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
-                 fun : funs) {
-            CompletableFuture<Integer> f = new CompletableFuture<>();
-            f.completeExceptionally(ex);
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
-            checkCompletedWithWrappedException(src, ex);
-            CompletableFuture<?> dep = fun.apply(src);
-            checkCompletedWithWrappedException(dep, ex);
-            assertSame(resultOf(src), resultOf(dep));
-        }
-
-        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
-                 fun : funs) {
-            CompletableFuture<Integer> f = new CompletableFuture<>();
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
-            CompletableFuture<?> dep = fun.apply(src);
-            f.completeExceptionally(ex);
-            checkCompletedWithWrappedException(src, ex);
-            checkCompletedWithWrappedException(dep, ex);
-            assertSame(resultOf(src), resultOf(dep));
-        }
-
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
-                 fun : funs) {
-            CompletableFuture<Integer> f = new CompletableFuture<>();
-            f.cancel(mayInterruptIfRunning);
-            checkCancelled(f);
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
-            checkCompletedWithWrappedCancellationException(src);
-            CompletableFuture<?> dep = fun.apply(src);
-            checkCompletedWithWrappedCancellationException(dep);
-            assertSame(resultOf(src), resultOf(dep));
-        }
-
-        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
-        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
-                 fun : funs) {
-            CompletableFuture<Integer> f = new CompletableFuture<>();
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
-            CompletableFuture<?> dep = fun.apply(src);
-            f.cancel(mayInterruptIfRunning);
-            checkCancelled(f);
-            checkCompletedWithWrappedCancellationException(src);
-            checkCompletedWithWrappedCancellationException(dep);
-            assertSame(resultOf(src), resultOf(dep));
-        }
-    }}
-
-    /**
-     * Minimal completion stages throw UOE for all non-CompletionStage methods
-     */
-   // TODO(streams):
-    // public void testMinimalCompletionStage_minimality() {
-    //     if (!testImplementationDetails) return;
-    //     Function<Method, String> toSignature =
-    //         (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
-    //     Predicate<Method> isNotStatic =
-    //         (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
-    //     List<Method> minimalMethods =
-    //         Stream.of(Object.class, CompletionStage.class)
-    //         .flatMap((klazz) -> Stream.of(klazz.getMethods()))
-    //         .filter(isNotStatic)
-    //         .collect(Collectors.toList());
-    //     // Methods from CompletableFuture permitted NOT to throw UOE
-    //     String[] signatureWhitelist = {
-    //         "newIncompleteFuture[]",
-    //         "defaultExecutor[]",
-    //         "minimalCompletionStage[]",
-    //         "copy[]",
-    //     };
-    //     Set<String> permittedMethodSignatures =
-    //         Stream.concat(minimalMethods.stream().map(toSignature),
-    //                       Stream.of(signatureWhitelist))
-    //         .collect(Collectors.toSet());
-    //     List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
-    //         .filter(isNotStatic)
-    //         .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
-    //         .collect(Collectors.toList());
-
-    //     CompletionStage<Integer> minimalStage =
-    //         new CompletableFuture<Integer>().minimalCompletionStage();
-
-    //     List<Method> bugs = new ArrayList<>();
-    //     for (Method method : allMethods) {
-    //         Class<?>[] parameterTypes = method.getParameterTypes();
-    //         Object[] args = new Object[parameterTypes.length];
-    //         // Manufacture boxed primitives for primitive params
-    //         for (int i = 0; i < args.length; i++) {
-    //             Class<?> type = parameterTypes[i];
-    //             if (parameterTypes[i] == boolean.class)
-    //                 args[i] = false;
-    //             else if (parameterTypes[i] == int.class)
-    //                 args[i] = 0;
-    //             else if (parameterTypes[i] == long.class)
-    //                 args[i] = 0L;
-    //         }
-    //         try {
-    //             method.invoke(minimalStage, args);
-    //             bugs.add(method);
-    //         }
-    //         catch (java.lang.reflect.InvocationTargetException expected) {
-    //             if (! (expected.getCause() instanceof UnsupportedOperationException)) {
-    //                 bugs.add(method);
-    //                 // expected.getCause().printStackTrace();
-    //             }
-    //         }
-    //         catch (ReflectiveOperationException bad) { throw new Error(bad); }
-    //     }
-    //     if (!bugs.isEmpty())
-    //         throw new Error("Methods did not throw UOE: " + bugs.toString());
-    // }
-
-    static class Monad {
-        static class ZeroException extends RuntimeException {
-            public ZeroException() { super("monadic zero"); }
-        }
-        // "return", "unit"
-        static <T> CompletableFuture<T> unit(T value) {
-            return completedFuture(value);
-        }
-        // monadic zero ?
-        static <T> CompletableFuture<T> zero() {
-            return failedFuture(new ZeroException());
-        }
-        // >=>
-        static <T,U,V> Function<T, CompletableFuture<V>> compose
-            (Function<T, CompletableFuture<U>> f,
-             Function<U, CompletableFuture<V>> g) {
-            return (x) -> f.apply(x).thenCompose(g);
-        }
-
-        static void assertZero(CompletableFuture<?> f) {
-            try {
-                f.getNow(null);
-                throw new AssertionFailedError("should throw");
-            } catch (CompletionException success) {
-                assertTrue(success.getCause() instanceof ZeroException);
-            }
-        }
-
-        static <T> void assertFutureEquals(CompletableFuture<T> f,
-                                           CompletableFuture<T> g) {
-            T fval = null, gval = null;
-            Throwable fex = null, gex = null;
-
-            try { fval = f.get(); }
-            catch (ExecutionException ex) { fex = ex.getCause(); }
-            catch (Throwable ex) { fex = ex; }
-
-            try { gval = g.get(); }
-            catch (ExecutionException ex) { gex = ex.getCause(); }
-            catch (Throwable ex) { gex = ex; }
-
-            if (fex != null || gex != null)
-                assertSame(fex.getClass(), gex.getClass());
-            else
-                assertEquals(fval, gval);
-        }
-
-        static class PlusFuture<T> extends CompletableFuture<T> {
-            AtomicReference<Throwable> firstFailure = new AtomicReference<>(null);
-        }
-
-        /** Implements "monadic plus". */
-        static <T> CompletableFuture<T> plus(CompletableFuture<? extends T> f,
-                                             CompletableFuture<? extends T> g) {
-            PlusFuture<T> plus = new PlusFuture<T>();
-            BiConsumer<T, Throwable> action = (T result, Throwable ex) -> {
-                try {
-                    if (ex == null) {
-                        if (plus.complete(result))
-                            if (plus.firstFailure.get() != null)
-                                plus.firstFailure.set(null);
-                    }
-                    else if (plus.firstFailure.compareAndSet(null, ex)) {
-                        if (plus.isDone())
-                            plus.firstFailure.set(null);
-                    }
-                    else {
-                        // first failure has precedence
-                        Throwable first = plus.firstFailure.getAndSet(null);
-
-                        // may fail with "Self-suppression not permitted"
-                        try { first.addSuppressed(ex); }
-                        catch (Exception ignored) {}
-
-                        plus.completeExceptionally(first);
-                    }
-                } catch (Throwable unexpected) {
-                    plus.completeExceptionally(unexpected);
-                }
-            };
-            f.whenComplete(action);
-            g.whenComplete(action);
-            return plus;
-        }
-    }
-
-    /**
-     * CompletableFuture is an additive monad - sort of.
-     * https://en.wikipedia.org/wiki/Monad_(functional_programming)#Additive_monads
-     */
-    public void testAdditiveMonad() throws Throwable {
-        Function<Long, CompletableFuture<Long>> unit = Monad::unit;
-        CompletableFuture<Long> zero = Monad.zero();
-
-        // Some mutually non-commutative functions
-        Function<Long, CompletableFuture<Long>> triple
-            = (x) -> Monad.unit(3 * x);
-        Function<Long, CompletableFuture<Long>> inc
-            = (x) -> Monad.unit(x + 1);
-
-        // unit is a right identity: m >>= unit === m
-        Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit),
-                                 inc.apply(5L));
-        // unit is a left identity: (unit x) >>= f === f x
-        Monad.assertFutureEquals(unit.apply(5L).thenCompose(inc),
-                                 inc.apply(5L));
-
-        // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) )
-        Monad.assertFutureEquals(
-            unit.apply(5L).thenCompose(inc).thenCompose(triple),
-            unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple)));
-
-        // The case for CompletableFuture as an additive monad is weaker...
-
-        // zero is a monadic zero
-        Monad.assertZero(zero);
-
-        // left zero: zero >>= f === zero
-        Monad.assertZero(zero.thenCompose(inc));
-        // right zero: f >>= (\x -> zero) === zero
-        Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero));
-
-        // f plus zero === f
-        Monad.assertFutureEquals(Monad.unit(5L),
-                                 Monad.plus(Monad.unit(5L), zero));
-        // zero plus f === f
-        Monad.assertFutureEquals(Monad.unit(5L),
-                                 Monad.plus(zero, Monad.unit(5L)));
-        // zero plus zero === zero
-        Monad.assertZero(Monad.plus(zero, zero));
-        {
-            CompletableFuture<Long> f = Monad.plus(Monad.unit(5L),
-                                                   Monad.unit(8L));
-            // non-determinism
-            assertTrue(f.get() == 5L || f.get() == 8L);
-        }
-
-        CompletableFuture<Long> godot = new CompletableFuture<>();
-        // f plus godot === f (doesn't wait for godot)
-        Monad.assertFutureEquals(Monad.unit(5L),
-                                 Monad.plus(Monad.unit(5L), godot));
-        // godot plus f === f (doesn't wait for godot)
-        Monad.assertFutureEquals(Monad.unit(5L),
-                                 Monad.plus(godot, Monad.unit(5L)));
-    }
-
-//     static <U> U join(CompletionStage<U> stage) {
-//         CompletableFuture<U> f = new CompletableFuture<>();
-//         stage.whenComplete((v, ex) -> {
-//             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
-//         });
-//         return f.join();
-//     }
-
-//     static <U> boolean isDone(CompletionStage<U> stage) {
-//         CompletableFuture<U> f = new CompletableFuture<>();
-//         stage.whenComplete((v, ex) -> {
-//             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
-//         });
-//         return f.isDone();
-//     }
-
-//     static <U> U join2(CompletionStage<U> stage) {
-//         return stage.toCompletableFuture().copy().join();
-//     }
-
-//     static <U> boolean isDone2(CompletionStage<U> stage) {
-//         return stage.toCompletableFuture().copy().isDone();
-//     }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java
deleted file mode 100644
index 60de8b9..0000000
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMap8Test.java
+++ /dev/null
@@ -1,1096 +0,0 @@
-/*
- * 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 jsr166;
-
-import static java.util.Spliterator.CONCURRENT;
-import static java.util.Spliterator.DISTINCT;
-import static java.util.Spliterator.NONNULL;
-
-import java.util.AbstractMap;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.LongAdder;
-import java.util.function.BiFunction;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class ConcurrentHashMap8Test extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(ConcurrentHashMap8Test.class);
-    // }
-
-    /**
-     * Returns a new map from Integers 1-5 to Strings "A"-"E".
-     */
-    private static ConcurrentHashMap map5() {
-        ConcurrentHashMap map = new ConcurrentHashMap(5);
-        assertTrue(map.isEmpty());
-        map.put(one, "A");
-        map.put(two, "B");
-        map.put(three, "C");
-        map.put(four, "D");
-        map.put(five, "E");
-        assertFalse(map.isEmpty());
-        assertEquals(5, map.size());
-        return map;
-    }
-
-    /**
-     * getOrDefault returns value if present, else default
-     */
-    public void testGetOrDefault() {
-        ConcurrentHashMap map = map5();
-        assertEquals(map.getOrDefault(one, "Z"), "A");
-        assertEquals(map.getOrDefault(six, "Z"), "Z");
-    }
-
-    /**
-     * computeIfAbsent adds when the given key is not present
-     */
-    public void testComputeIfAbsent() {
-        ConcurrentHashMap map = map5();
-        map.computeIfAbsent(six, (x) -> "Z");
-        assertTrue(map.containsKey(six));
-    }
-
-    /**
-     * computeIfAbsent does not replace if the key is already present
-     */
-    public void testComputeIfAbsent2() {
-        ConcurrentHashMap map = map5();
-        assertEquals("A", map.computeIfAbsent(one, (x) -> "Z"));
-    }
-
-    /**
-     * computeIfAbsent does not add if function returns null
-     */
-    public void testComputeIfAbsent3() {
-        ConcurrentHashMap map = map5();
-        map.computeIfAbsent(six, (x) -> null);
-        assertFalse(map.containsKey(six));
-    }
-
-    /**
-     * computeIfPresent does not replace if the key is already present
-     */
-    public void testComputeIfPresent() {
-        ConcurrentHashMap map = map5();
-        map.computeIfPresent(six, (x, y) -> "Z");
-        assertFalse(map.containsKey(six));
-    }
-
-    /**
-     * computeIfPresent adds when the given key is not present
-     */
-    public void testComputeIfPresent2() {
-        ConcurrentHashMap map = map5();
-        assertEquals("Z", map.computeIfPresent(one, (x, y) -> "Z"));
-    }
-
-    /**
-     * compute does not replace if the function returns null
-     */
-    public void testCompute() {
-        ConcurrentHashMap map = map5();
-        map.compute(six, (x, y) -> null);
-        assertFalse(map.containsKey(six));
-    }
-
-    /**
-     * compute adds when the given key is not present
-     */
-    public void testCompute2() {
-        ConcurrentHashMap map = map5();
-        assertEquals("Z", map.compute(six, (x, y) -> "Z"));
-    }
-
-    /**
-     * compute replaces when the given key is present
-     */
-    public void testCompute3() {
-        ConcurrentHashMap map = map5();
-        assertEquals("Z", map.compute(one, (x, y) -> "Z"));
-    }
-
-    /**
-     * compute removes when the given key is present and function returns null
-     */
-    public void testCompute4() {
-        ConcurrentHashMap map = map5();
-        map.compute(one, (x, y) -> null);
-        assertFalse(map.containsKey(one));
-    }
-
-    /**
-     * merge adds when the given key is not present
-     */
-    public void testMerge1() {
-        ConcurrentHashMap map = map5();
-        assertEquals("Y", map.merge(six, "Y", (x, y) -> "Z"));
-    }
-
-    /**
-     * merge replaces when the given key is present
-     */
-    public void testMerge2() {
-        ConcurrentHashMap map = map5();
-        assertEquals("Z", map.merge(one, "Y", (x, y) -> "Z"));
-    }
-
-    /**
-     * merge removes when the given key is present and function returns null
-     */
-    public void testMerge3() {
-        ConcurrentHashMap map = map5();
-        map.merge(one, "Y", (x, y) -> null);
-        assertFalse(map.containsKey(one));
-    }
-
-    static Set<Integer> populatedSet(int n) {
-        Set<Integer> a = ConcurrentHashMap.<Integer>newKeySet();
-        assertTrue(a.isEmpty());
-        for (int i = 0; i < n; i++)
-            assertTrue(a.add(i));
-        assertEquals(n == 0, a.isEmpty());
-        assertEquals(n, a.size());
-        return a;
-    }
-
-    static Set populatedSet(Integer[] elements) {
-        Set<Integer> a = ConcurrentHashMap.<Integer>newKeySet();
-        assertTrue(a.isEmpty());
-        for (int i = 0; i < elements.length; i++)
-            assertTrue(a.add(elements[i]));
-        assertFalse(a.isEmpty());
-        assertEquals(elements.length, a.size());
-        return a;
-    }
-
-    /**
-     * replaceAll replaces all matching values.
-     */
-    public void testReplaceAll() {
-        ConcurrentHashMap<Integer, String> map = map5();
-        map.replaceAll((x, y) -> { return x > 3 ? "Z" : y; });
-        assertEquals("A", map.get(one));
-        assertEquals("B", map.get(two));
-        assertEquals("C", map.get(three));
-        assertEquals("Z", map.get(four));
-        assertEquals("Z", map.get(five));
-    }
-
-    /**
-     * Default-constructed set is empty
-     */
-    public void testNewKeySet() {
-        Set a = ConcurrentHashMap.newKeySet();
-        assertTrue(a.isEmpty());
-    }
-
-    /**
-     * keySet.add adds the key with the established value to the map;
-     * remove removes it.
-     */
-    public void testKeySetAddRemove() {
-        ConcurrentHashMap map = map5();
-        Set set1 = map.keySet();
-        Set set2 = map.keySet(true);
-        set2.add(six);
-        assertTrue(((ConcurrentHashMap.KeySetView)set2).getMap() == map);
-        assertTrue(((ConcurrentHashMap.KeySetView)set1).getMap() == map);
-        assertEquals(set2.size(), map.size());
-        assertEquals(set1.size(), map.size());
-        assertTrue((Boolean)map.get(six));
-        assertTrue(set1.contains(six));
-        assertTrue(set2.contains(six));
-        set2.remove(six);
-        assertNull(map.get(six));
-        assertFalse(set1.contains(six));
-        assertFalse(set2.contains(six));
-    }
-
-    /**
-     * keySet.addAll adds each element from the given collection
-     */
-    public void testAddAll() {
-        Set full = populatedSet(3);
-        assertTrue(full.addAll(Arrays.asList(three, four, five)));
-        assertEquals(6, full.size());
-        assertFalse(full.addAll(Arrays.asList(three, four, five)));
-        assertEquals(6, full.size());
-    }
-
-    /**
-     * keySet.addAll adds each element from the given collection that did not
-     * already exist in the set
-     */
-    public void testAddAll2() {
-        Set full = populatedSet(3);
-        // "one" is duplicate and will not be added
-        assertTrue(full.addAll(Arrays.asList(three, four, one)));
-        assertEquals(5, full.size());
-        assertFalse(full.addAll(Arrays.asList(three, four, one)));
-        assertEquals(5, full.size());
-    }
-
-    /**
-     * keySet.add will not add the element if it already exists in the set
-     */
-    public void testAdd2() {
-        Set full = populatedSet(3);
-        assertFalse(full.add(one));
-        assertEquals(3, full.size());
-    }
-
-    /**
-     * keySet.add adds the element when it does not exist in the set
-     */
-    public void testAdd3() {
-        Set full = populatedSet(3);
-        assertTrue(full.add(three));
-        assertTrue(full.contains(three));
-        assertFalse(full.add(three));
-        assertTrue(full.contains(three));
-    }
-
-    /**
-     * keySet.add throws UnsupportedOperationException if no default
-     * mapped value
-     */
-    public void testAdd4() {
-        Set full = map5().keySet();
-        try {
-            full.add(three);
-            shouldThrow();
-        } catch (UnsupportedOperationException success) {}
-    }
-
-    /**
-     * keySet.add throws NullPointerException if the specified key is
-     * null
-     */
-    public void testAdd5() {
-        Set full = populatedSet(3);
-        try {
-            full.add(null);
-            shouldThrow();
-        } catch (NullPointerException success) {}
-    }
-
-    /**
-     * KeySetView.getMappedValue returns the map's mapped value
-     */
-    public void testGetMappedValue() {
-        ConcurrentHashMap map = map5();
-        assertNull(map.keySet().getMappedValue());
-        try {
-            map.keySet(null);
-            shouldThrow();
-        } catch (NullPointerException success) {}
-        ConcurrentHashMap.KeySetView set = map.keySet(one);
-        assertFalse(set.add(one));
-        assertTrue(set.add(six));
-        assertTrue(set.add(seven));
-        assertTrue(set.getMappedValue() == one);
-        assertTrue(map.get(one) != one);
-        assertTrue(map.get(six) == one);
-        assertTrue(map.get(seven) == one);
-    }
-
-    void checkSpliteratorCharacteristics(Spliterator<?> sp,
-                                         int requiredCharacteristics) {
-        assertEquals(requiredCharacteristics,
-                     requiredCharacteristics & sp.characteristics());
-    }
-
-    /**
-     * KeySetView.spliterator returns spliterator over the elements in this set
-     */
-    public void testKeySetSpliterator() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap map = map5();
-        Set set = map.keySet();
-        Spliterator<Integer> sp = set.spliterator();
-        checkSpliteratorCharacteristics(sp, CONCURRENT | DISTINCT | NONNULL);
-        assertEquals(sp.estimateSize(), map.size());
-        Spliterator<Integer> sp2 = sp.trySplit();
-        sp.forEachRemaining((Integer x) -> adder.add(x.longValue()));
-        long v = adder.sumThenReset();
-        sp2.forEachRemaining((Integer x) -> adder.add(x.longValue()));
-        long v2 = adder.sum();
-        assertEquals(v + v2, 15);
-    }
-
-    /**
-     * keyset.clear removes all elements from the set
-     */
-    public void testClear() {
-        Set full = populatedSet(3);
-        full.clear();
-        assertEquals(0, full.size());
-    }
-
-    /**
-     * keyset.contains returns true for added elements
-     */
-    public void testContains() {
-        Set full = populatedSet(3);
-        assertTrue(full.contains(one));
-        assertFalse(full.contains(five));
-    }
-
-    /**
-     * KeySets with equal elements are equal
-     */
-    public void testEquals() {
-        Set a = populatedSet(3);
-        Set b = populatedSet(3);
-        assertTrue(a.equals(b));
-        assertTrue(b.equals(a));
-        assertEquals(a.hashCode(), b.hashCode());
-        a.add(m1);
-        assertFalse(a.equals(b));
-        assertFalse(b.equals(a));
-        b.add(m1);
-        assertTrue(a.equals(b));
-        assertTrue(b.equals(a));
-        assertEquals(a.hashCode(), b.hashCode());
-    }
-
-    /**
-     * KeySet.containsAll returns true for collections with subset of elements
-     */
-    public void testContainsAll() {
-        Collection full = populatedSet(3);
-        assertTrue(full.containsAll(Arrays.asList()));
-        assertTrue(full.containsAll(Arrays.asList(one)));
-        assertTrue(full.containsAll(Arrays.asList(one, two)));
-        assertFalse(full.containsAll(Arrays.asList(one, two, six)));
-        assertFalse(full.containsAll(Arrays.asList(six)));
-    }
-
-    /**
-     * KeySet.isEmpty is true when empty, else false
-     */
-    public void testIsEmpty() {
-        assertTrue(populatedSet(0).isEmpty());
-        assertFalse(populatedSet(3).isEmpty());
-    }
-
-    /**
-     * KeySet.iterator() returns an iterator containing the elements of the
-     * set
-     */
-    public void testIterator() {
-        Collection empty = ConcurrentHashMap.newKeySet();
-        int size = 20;
-        assertFalse(empty.iterator().hasNext());
-        try {
-            empty.iterator().next();
-            shouldThrow();
-        } catch (NoSuchElementException success) {}
-
-        Integer[] elements = new Integer[size];
-        for (int i = 0; i < size; i++)
-            elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
-        Collection<Integer> full = populatedSet(elements);
-
-        Iterator it = full.iterator();
-        for (int j = 0; j < size; j++) {
-            assertTrue(it.hasNext());
-            it.next();
-        }
-        assertIteratorExhausted(it);
-    }
-
-    /**
-     * iterator of empty collections has no elements
-     */
-    public void testEmptyIterator() {
-        assertIteratorExhausted(ConcurrentHashMap.newKeySet().iterator());
-        assertIteratorExhausted(new ConcurrentHashMap().entrySet().iterator());
-        assertIteratorExhausted(new ConcurrentHashMap().values().iterator());
-        assertIteratorExhausted(new ConcurrentHashMap().keySet().iterator());
-    }
-
-    /**
-     * KeySet.iterator.remove removes current element
-     */
-    public void testIteratorRemove() {
-        Set q = populatedSet(3);
-        Iterator it = q.iterator();
-        Object removed = it.next();
-        it.remove();
-
-        it = q.iterator();
-        assertFalse(it.next().equals(removed));
-        assertFalse(it.next().equals(removed));
-        assertFalse(it.hasNext());
-    }
-
-    /**
-     * KeySet.toString holds toString of elements
-     */
-    public void testToString() {
-        assertEquals("[]", ConcurrentHashMap.newKeySet().toString());
-        Set full = populatedSet(3);
-        String s = full.toString();
-        for (int i = 0; i < 3; ++i)
-            assertTrue(s.contains(String.valueOf(i)));
-    }
-
-    /**
-     * KeySet.removeAll removes all elements from the given collection
-     */
-    public void testRemoveAll() {
-        Set full = populatedSet(3);
-        assertTrue(full.removeAll(Arrays.asList(one, two)));
-        assertEquals(1, full.size());
-        assertFalse(full.removeAll(Arrays.asList(one, two)));
-        assertEquals(1, full.size());
-    }
-
-    /**
-     * KeySet.remove removes an element
-     */
-    public void testRemove() {
-        Set full = populatedSet(3);
-        full.remove(one);
-        assertFalse(full.contains(one));
-        assertEquals(2, full.size());
-    }
-
-    /**
-     * keySet.size returns the number of elements
-     */
-    public void testSize() {
-        Set empty = ConcurrentHashMap.newKeySet();
-        Set full = populatedSet(3);
-        assertEquals(3, full.size());
-        assertEquals(0, empty.size());
-    }
-
-    /**
-     * KeySet.toArray() returns an Object array containing all elements from
-     * the set
-     */
-    public void testToArray() {
-        Object[] a = ConcurrentHashMap.newKeySet().toArray();
-        assertTrue(Arrays.equals(new Object[0], a));
-        assertSame(Object[].class, a.getClass());
-        int size = 20;
-        Integer[] elements = new Integer[size];
-        for (int i = 0; i < size; i++)
-            elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
-        Collection<Integer> full = populatedSet(elements);
-
-        assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray())));
-        assertTrue(full.containsAll(Arrays.asList(full.toArray())));
-        assertSame(Object[].class, full.toArray().getClass());
-    }
-
-    /**
-     * toArray(Integer array) returns an Integer array containing all
-     * elements from the set
-     */
-    public void testToArray2() {
-        Collection empty = ConcurrentHashMap.newKeySet();
-        Integer[] a;
-        int size = 20;
-
-        a = new Integer[0];
-        assertSame(a, empty.toArray(a));
-
-        a = new Integer[size / 2];
-        Arrays.fill(a, 42);
-        assertSame(a, empty.toArray(a));
-        assertNull(a[0]);
-        for (int i = 1; i < a.length; i++)
-            assertEquals(42, (int) a[i]);
-
-        Integer[] elements = new Integer[size];
-        for (int i = 0; i < size; i++)
-            elements[i] = i;
-        Collections.shuffle(Arrays.asList(elements));
-        Collection<Integer> full = populatedSet(elements);
-
-        Arrays.fill(a, 42);
-        assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray(a))));
-        for (int i = 0; i < a.length; i++)
-            assertEquals(42, (int) a[i]);
-        assertSame(Integer[].class, full.toArray(a).getClass());
-
-        a = new Integer[size];
-        Arrays.fill(a, 42);
-        assertSame(a, full.toArray(a));
-        assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray(a))));
-    }
-
-    /**
-     * A deserialized serialized set is equal
-     */
-    public void testSerialization() throws Exception {
-        int size = 20;
-        Set x = populatedSet(size);
-        Set y = serialClone(x);
-
-        assertNotSame(x, y);
-        assertEquals(x.size(), y.size());
-        assertEquals(x, y);
-        assertEquals(y, x);
-    }
-
-    static final int SIZE = 10000;
-    static ConcurrentHashMap<Long, Long> longMap;
-
-    static ConcurrentHashMap<Long, Long> longMap() {
-        if (longMap == null) {
-            longMap = new ConcurrentHashMap<Long, Long>(SIZE);
-            for (int i = 0; i < SIZE; ++i)
-                longMap.put(Long.valueOf(i), Long.valueOf(2 *i));
-        }
-        return longMap;
-    }
-
-    // explicit function class to avoid type inference problems
-    static class AddKeys implements BiFunction<Map.Entry<Long,Long>, Map.Entry<Long,Long>, Map.Entry<Long,Long>> {
-        public Map.Entry<Long,Long> apply(Map.Entry<Long,Long> x, Map.Entry<Long,Long> y) {
-            return new AbstractMap.SimpleEntry<Long,Long>
-             (Long.valueOf(x.getKey().longValue() + y.getKey().longValue()),
-              Long.valueOf(1L));
-        }
-    }
-
-    /**
-     * forEachKeySequentially traverses all keys
-     */
-    public void testForEachKeySequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachKey(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * forEachValueSequentially traverses all values
-     */
-    public void testForEachValueSequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachValue(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), SIZE * (SIZE - 1));
-    }
-
-    /**
-     * forEachSequentially traverses all mappings
-     */
-    public void testForEachSequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEach(Long.MAX_VALUE, (Long x, Long y) -> adder.add(x.longValue() + y.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * forEachEntrySequentially traverses all entries
-     */
-    public void testForEachEntrySequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachEntry(Long.MAX_VALUE, (Map.Entry<Long,Long> e) -> adder.add(e.getKey().longValue() + e.getValue().longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * forEachKeyInParallel traverses all keys
-     */
-    public void testForEachKeyInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachKey(1L, (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * forEachValueInParallel traverses all values
-     */
-    public void testForEachValueInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachValue(1L, (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), SIZE * (SIZE - 1));
-    }
-
-    /**
-     * forEachInParallel traverses all mappings
-     */
-    public void testForEachInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEach(1L, (Long x, Long y) -> adder.add(x.longValue() + y.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * forEachEntryInParallel traverses all entries
-     */
-    public void testForEachEntryInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachEntry(1L, (Map.Entry<Long,Long> e) -> adder.add(e.getKey().longValue() + e.getValue().longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachKeySequentially traverses the given
-     * transformations of all keys
-     */
-    public void testMappedForEachKeySequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachKey(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                 (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachValueSequentially traverses the given
-     * transformations of all values
-     */
-    public void testMappedForEachValueSequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachValue(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                   (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1));
-    }
-
-    /**
-     * Mapped forEachSequentially traverses the given
-     * transformations of all mappings
-     */
-    public void testMappedForEachSequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEach(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()),
-                              (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachEntrySequentially traverses the given
-     * transformations of all entries
-     */
-    public void testMappedForEachEntrySequentially() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachEntry(Long.MAX_VALUE, (Map.Entry<Long,Long> e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()),
-                                   (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachKeyInParallel traverses the given
-     * transformations of all keys
-     */
-    public void testMappedForEachKeyInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachKey(1L, (Long x) -> Long.valueOf(4 * x.longValue()),
-                               (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachValueInParallel traverses the given
-     * transformations of all values
-     */
-    public void testMappedForEachValueInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachValue(1L, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                 (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1));
-    }
-
-    /**
-     * Mapped forEachInParallel traverses the given
-     * transformations of all mappings
-     */
-    public void testMappedForEachInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEach(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()),
-                            (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped forEachEntryInParallel traverses the given
-     * transformations of all entries
-     */
-    public void testMappedForEachEntryInParallel() {
-        LongAdder adder = new LongAdder();
-        ConcurrentHashMap<Long, Long> m = longMap();
-        m.forEachEntry(1L, (Map.Entry<Long,Long> e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()),
-                                 (Long x) -> adder.add(x.longValue()));
-        assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysSequentially accumulates across all keys,
-     */
-    public void testReduceKeysSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceValuesSequentially accumulates across all values
-     */
-    public void testReduceValuesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceEntriesSequentially accumulates across all entries
-     */
-    public void testReduceEntriesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Map.Entry<Long,Long> r;
-        r = m.reduceEntries(Long.MAX_VALUE, new AddKeys());
-        assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysInParallel accumulates across all keys
-     */
-    public void testReduceKeysInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.reduceKeys(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceValuesInParallel accumulates across all values
-     */
-    public void testReduceValuesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.reduceValues(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceEntriesInParallel accumulate across all entries
-     */
-    public void testReduceEntriesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Map.Entry<Long,Long> r;
-        r = m.reduceEntries(1L, new AddKeys());
-        assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped reduceKeysSequentially accumulates mapped keys
-     */
-    public void testMapReduceKeysSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r = m.reduceKeys(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                     (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)4 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped reduceValuesSequentially accumulates mapped values
-     */
-    public void testMapReduceValuesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r = m.reduceValues(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                       (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)4 * SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceSequentially accumulates across all transformed mappings
-     */
-    public void testMappedReduceSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r = m.reduce(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()),
-                                 (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-
-        assertEquals((long)r, (long)3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped reduceKeysInParallel, accumulates mapped keys
-     */
-    public void testMapReduceKeysInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r = m.reduceKeys(1L, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                   (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)4 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * Mapped reduceValuesInParallel accumulates mapped values
-     */
-    public void testMapReduceValuesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r = m.reduceValues(1L, (Long x) -> Long.valueOf(4 * x.longValue()),
-                                     (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)4 * SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceInParallel accumulate across all transformed mappings
-     */
-    public void testMappedReduceInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.reduce(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()),
-                               (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()));
-        assertEquals((long)r, (long)3 * SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysToLongSequentially accumulates mapped keys
-     */
-    public void testReduceKeysToLongSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceKeysToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysToIntSequentially accumulates mapped keys
-     */
-    public void testReduceKeysToIntSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceKeysToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysToDoubleSequentially accumulates mapped keys
-     */
-    public void testReduceKeysToDoubleSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceKeysToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceValuesToLongSequentially accumulates mapped values
-     */
-    public void testReduceValuesToLongSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceValuesToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceValuesToIntSequentially accumulates mapped values
-     */
-    public void testReduceValuesToIntSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceValuesToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceValuesToDoubleSequentially accumulates mapped values
-     */
-    public void testReduceValuesToDoubleSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceValuesToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceKeysToLongInParallel accumulates mapped keys
-     */
-    public void testReduceKeysToLongInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceKeysToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysToIntInParallel accumulates mapped keys
-     */
-    public void testReduceKeysToIntInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceKeysToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceKeysToDoubleInParallel accumulates mapped values
-     */
-    public void testReduceKeysToDoubleInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceKeysToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1) / 2);
-    }
-
-    /**
-     * reduceValuesToLongInParallel accumulates mapped values
-     */
-    public void testReduceValuesToLongInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        long lr = m.reduceValuesToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum);
-        assertEquals(lr, (long)SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceValuesToIntInParallel accumulates mapped values
-     */
-    public void testReduceValuesToIntInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        int ir = m.reduceValuesToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum);
-        assertEquals(ir, SIZE * (SIZE - 1));
-    }
-
-    /**
-     * reduceValuesToDoubleInParallel accumulates mapped values
-     */
-    public void testReduceValuesToDoubleInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        double dr = m.reduceValuesToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum);
-        assertEquals(dr, (double)SIZE * (SIZE - 1));
-    }
-
-    /**
-     * searchKeysSequentially returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchKeysSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() < 0L ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchValuesSequentially returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchValuesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchValues(Long.MAX_VALUE,
-            (Long x) -> (x.longValue() == (long)(SIZE/2)) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchValues(Long.MAX_VALUE,
-            (Long x) -> (x.longValue() < 0L) ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchSequentially returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() == (long)(SIZE/2) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() < 0L ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchEntriesSequentially returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchEntriesSequentially() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchEntries(Long.MAX_VALUE, (Map.Entry<Long,Long> e) -> e.getKey().longValue() == (long)(SIZE/2) ? e.getKey() : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchEntries(Long.MAX_VALUE, (Map.Entry<Long,Long> e) -> e.getKey().longValue() < 0L ? e.getKey() : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchKeysInParallel returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchKeysInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchKeys(1L, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchKeys(1L, (Long x) -> x.longValue() < 0L ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchValuesInParallel returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchValuesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchValues(1L, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchValues(1L, (Long x) -> x.longValue() < 0L ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchInParallel returns a non-null result of search function,
-     * or null if none
-     */
-    public void testSearchInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.search(1L, (Long x, Long y) -> x.longValue() == (long)(SIZE/2) ? x : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.search(1L, (Long x, Long y) -> x.longValue() < 0L ? x : null);
-        assertNull(r);
-    }
-
-    /**
-     * searchEntriesInParallel returns a non-null result of search
-     * function, or null if none
-     */
-    public void testSearchEntriesInParallel() {
-        ConcurrentHashMap<Long, Long> m = longMap();
-        Long r;
-        r = m.searchEntries(1L, (Map.Entry<Long,Long> e) -> e.getKey().longValue() == (long)(SIZE/2) ? e.getKey() : null);
-        assertEquals((long)r, (long)(SIZE/2));
-        r = m.searchEntries(1L, (Map.Entry<Long,Long> e) -> e.getKey().longValue() < 0L ? e.getKey() : null);
-        assertNull(r);
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
index f427127..4650f41 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentHashMapTest.java
@@ -30,7 +30,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentHashMapTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -50,9 +50,7 @@
     }
 
     /** Re-implement Integer.compare for old java versions */
-    static int compare(int x, int y) {
-        return (x < y) ? -1 : (x > y) ? 1 : 0;
-    }
+    static int compare(int x, int y) { return x < y ? -1 : x > y ? 1 : 0; }
 
     // classes for testing Comparable fallbacks
     static class BI implements Comparable<BI> {
@@ -540,7 +538,7 @@
     /**
      * Constructor (initialCapacity, loadFactor) throws
      * IllegalArgumentException if either argument is negative
-     */
+      */
     public void testConstructor2() {
         try {
             new ConcurrentHashMap(-1, .75f);
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
index 6625e7e..c445957 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentLinkedDequeTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -69,7 +69,8 @@
      */
     public void testConstructor4() {
         try {
-            new ConcurrentLinkedDeque(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new ConcurrentLinkedDeque(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -78,10 +79,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new ConcurrentLinkedDeque(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -119,7 +120,7 @@
     public void testSize() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.remove();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -132,8 +133,8 @@
      * push(null) throws NPE
      */
     public void testPushNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.push(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -167,8 +168,8 @@
      * offer(null) throws NPE
      */
     public void testOfferNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.offer(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -178,8 +179,8 @@
      * offerFirst(null) throws NPE
      */
     public void testOfferFirstNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.offerFirst(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -189,8 +190,8 @@
      * offerLast(null) throws NPE
      */
     public void testOfferLastNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.offerLast(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -233,8 +234,8 @@
      * add(null) throws NPE
      */
     public void testAddNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.add(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -244,8 +245,8 @@
      * addFirst(null) throws NPE
      */
     public void testAddFirstNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.addFirst(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -255,8 +256,8 @@
      * addLast(null) throws NPE
      */
     public void testAddLastNull() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.addLast(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -299,8 +300,8 @@
      * addAll(null) throws NPE
      */
     public void testAddAll1() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
             q.addAll(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -310,8 +311,8 @@
      * addAll(this) throws IAE
      */
     public void testAddAllSelf() {
-        ConcurrentLinkedDeque q = populatedDeque(SIZE);
         try {
+            ConcurrentLinkedDeque q = populatedDeque(SIZE);
             q.addAll(q);
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -321,9 +322,10 @@
      * addAll of a collection with null elements throws NPE
      */
     public void testAddAll2() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
         try {
-            q.addAll(Arrays.asList(new Integer[SIZE]));
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
+            Integer[] ints = new Integer[SIZE];
+            q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -333,11 +335,11 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -374,7 +376,7 @@
      */
     public void testPollLast() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollLast());
@@ -443,14 +445,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -474,7 +476,7 @@
      */
     public void testPeekLast() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.peekLast());
             assertEquals(i, q.pollLast());
             assertTrue(q.peekLast() == null ||
@@ -503,7 +505,7 @@
      */
     public void testLastElement() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.getLast());
             assertEquals(i, q.pollLast());
         }
@@ -554,7 +556,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeFirstOccurrence(new Integer(i)));
-            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -569,7 +571,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeLastOccurrence(new Integer(i)));
-            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeLastOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -628,7 +630,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -641,7 +643,7 @@
             ConcurrentLinkedDeque q = populatedDeque(SIZE);
             ConcurrentLinkedDeque p = populatedDeque(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -757,18 +759,18 @@
         final Random rng = new Random();
         for (int iters = 0; iters < 100; ++iters) {
             int max = rng.nextInt(5) + 2;
-            int split = rng.nextInt(max - 1) + 1;
+            int split = rng.nextInt(max-1) + 1;
             for (int j = 1; j <= max; ++j)
                 q.add(new Integer(j));
             Iterator it = q.iterator();
             for (int j = 1; j <= split; ++j)
                 assertEquals(it.next(), new Integer(j));
             it.remove();
-            assertEquals(it.next(), new Integer(split + 1));
+            assertEquals(it.next(), new Integer(split+1));
             for (int j = 1; j <= split; ++j)
                 q.remove(new Integer(j));
             it = q.iterator();
-            for (int j = split + 1; j <= max; ++j) {
+            for (int j = split+1; j <= max; ++j) {
                 assertEquals(it.next(), new Integer(j));
                 it.remove();
             }
@@ -825,18 +827,18 @@
         final Random rng = new Random();
         for (int iters = 0; iters < 100; ++iters) {
             int max = rng.nextInt(5) + 2;
-            int split = rng.nextInt(max - 1) + 1;
+            int split = rng.nextInt(max-1) + 1;
             for (int j = max; j >= 1; --j)
                 q.add(new Integer(j));
             Iterator it = q.descendingIterator();
             for (int j = 1; j <= split; ++j)
                 assertEquals(it.next(), new Integer(j));
             it.remove();
-            assertEquals(it.next(), new Integer(split + 1));
+            assertEquals(it.next(), new Integer(split+1));
             for (int j = 1; j <= split; ++j)
                 q.remove(new Integer(j));
             it = q.descendingIterator();
-            for (int j = split + 1; j <= max; ++j) {
+            for (int j = split+1; j <= max; ++j) {
                 assertEquals(it.next(), new Integer(j));
                 it.remove();
             }
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
index 70519a4..d3f5b1f 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
@@ -27,7 +27,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentLinkedQueueTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -66,7 +66,8 @@
      */
     public void testConstructor4() {
         try {
-            new ConcurrentLinkedQueue(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new ConcurrentLinkedQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -75,10 +76,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new ConcurrentLinkedQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -116,7 +117,7 @@
     public void testSize() {
         ConcurrentLinkedQueue q = populatedQueue(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.remove();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -129,8 +130,8 @@
      * offer(null) throws NPE
      */
     public void testOfferNull() {
-        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
         try {
+            ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
             q.offer(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -140,8 +141,8 @@
      * add(null) throws NPE
      */
     public void testAddNull() {
-        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
         try {
+            ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
             q.add(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -171,8 +172,8 @@
      * addAll(null) throws NPE
      */
     public void testAddAll1() {
-        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
         try {
+            ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
             q.addAll(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -182,8 +183,8 @@
      * addAll(this) throws IAE
      */
     public void testAddAllSelf() {
-        ConcurrentLinkedQueue q = populatedQueue(SIZE);
         try {
+            ConcurrentLinkedQueue q = populatedQueue(SIZE);
             q.addAll(q);
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -193,9 +194,10 @@
      * addAll of a collection with null elements throws NPE
      */
     public void testAddAll2() {
-        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
         try {
-            q.addAll(Arrays.asList(new Integer[SIZE]));
+            ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+            Integer[] ints = new Integer[SIZE];
+            q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -205,11 +207,11 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -293,14 +295,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -359,7 +361,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -372,7 +374,7 @@
             ConcurrentLinkedQueue q = populatedQueue(SIZE);
             ConcurrentLinkedQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListMapTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListMapTest.java
index f53a446..0aadd23 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListMapTest.java
@@ -30,7 +30,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentSkipListMapTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -1278,7 +1278,7 @@
     }
 
     static boolean eq(Integer i, int j) {
-        return (i == null) ? j == -1 : i == j;
+        return i == null ? j == -1 : i == j;
     }
 
 }
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSetTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSetTest.java
index 959d703..41f8835 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSetTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSetTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentSkipListSetTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyReverseComparator implements Comparator {
@@ -46,7 +46,7 @@
         ConcurrentSkipListSet<Integer> q =
             new ConcurrentSkipListSet<Integer>();
         assertTrue(q.isEmpty());
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.add(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.add(new Integer(i)));
@@ -92,7 +92,8 @@
      */
     public void testConstructor4() {
         try {
-            new ConcurrentSkipListSet(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new ConcurrentSkipListSet(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -101,10 +102,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new ConcurrentSkipListSet(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -133,7 +134,7 @@
         for (int i = 0; i < SIZE; ++i)
             ints[i] = new Integer(i);
         q.addAll(Arrays.asList(ints));
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             assertEquals(ints[i], q.pollFirst());
     }
 
@@ -157,7 +158,7 @@
     public void testSize() {
         ConcurrentSkipListSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -237,7 +238,7 @@
     public void testAddAll3() {
         ConcurrentSkipListSet q = new ConcurrentSkipListSet();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         try {
             q.addAll(Arrays.asList(ints));
@@ -252,7 +253,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1-i);
         ConcurrentSkipListSet q = new ConcurrentSkipListSet();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -276,7 +277,7 @@
      */
     public void testPollLast() {
         ConcurrentSkipListSet q = populatedSet(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollFirst());
@@ -291,14 +292,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -357,7 +358,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -370,7 +371,7 @@
             ConcurrentSkipListSet q = populatedSet(SIZE);
             ConcurrentSkipListSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
@@ -979,7 +980,7 @@
     }
 
     static boolean eq(Integer i, int j) {
-        return (i == null) ? j == -1 : i == j;
+        return i == null ? j == -1 : i == j;
     }
 
 }
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubMapTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubMapTest.java
index a6510f5..5315bcb 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubMapTest.java
@@ -28,7 +28,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentSkipListSubMapTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubSetTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubSetTest.java
index 220a092..f1c4aae 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubSetTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentSkipListSubSetTest.java
@@ -24,7 +24,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ConcurrentSkipListSubSetTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyReverseComparator implements Comparator {
@@ -42,7 +42,7 @@
             new ConcurrentSkipListSet<Integer>();
         assertTrue(q.isEmpty());
 
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.add(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.add(new Integer(i)));
@@ -127,7 +127,7 @@
     public void testSize() {
         NavigableSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -206,8 +206,8 @@
     public void testAddAll3() {
         NavigableSet q = set0();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i + SIZE);
+        for (int i = 0; i < SIZE-1; ++i)
+            ints[i] = new Integer(i+SIZE);
         try {
             q.addAll(Arrays.asList(ints));
             shouldThrow();
@@ -221,7 +221,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1- i);
         NavigableSet q = set0();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -249,14 +249,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -315,7 +315,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -328,7 +328,7 @@
             NavigableSet q = populatedSet(SIZE);
             NavigableSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
@@ -623,7 +623,7 @@
     public void testDescendingSize() {
         NavigableSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -702,8 +702,8 @@
     public void testDescendingAddAll3() {
         NavigableSet q = dset0();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i + SIZE);
+        for (int i = 0; i < SIZE-1; ++i)
+            ints[i] = new Integer(i+SIZE);
         try {
             q.addAll(Arrays.asList(ints));
             shouldThrow();
@@ -717,7 +717,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1- i);
         NavigableSet q = dset0();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -746,7 +746,7 @@
         }
         for (int i = 0; i < SIZE; i += 2 ) {
             assertTrue(q.remove(new Integer(i)));
-            assertFalse(q.remove(new Integer(i + 1)));
+            assertFalse(q.remove(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -805,7 +805,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -818,7 +818,7 @@
             NavigableSet q = populatedSet(SIZE);
             NavigableSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
diff --git a/jsr166-tests/src/test/java/jsr166/CopyOnWriteArrayListTest.java b/jsr166-tests/src/test/java/jsr166/CopyOnWriteArrayListTest.java
index 8a37d03..658268a 100644
--- a/jsr166-tests/src/test/java/jsr166/CopyOnWriteArrayListTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CopyOnWriteArrayListTest.java
@@ -31,7 +31,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(CopyOnWriteArrayListTest.class);
+    //     return new TestSuite(...);
     // }
 
     static CopyOnWriteArrayList<Integer> populatedArray(int n) {
@@ -67,7 +67,7 @@
      */
     public void testConstructor2() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         CopyOnWriteArrayList a = new CopyOnWriteArrayList(ints);
         for (int i = 0; i < SIZE; ++i)
@@ -79,7 +79,7 @@
      */
     public void testConstructor3() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         CopyOnWriteArrayList a = new CopyOnWriteArrayList(Arrays.asList(ints));
         for (int i = 0; i < SIZE; ++i)
@@ -181,26 +181,18 @@
         CopyOnWriteArrayList b = populatedArray(3);
         assertTrue(a.equals(b));
         assertTrue(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertTrue(b.containsAll(a));
         assertEquals(a.hashCode(), b.hashCode());
         a.add(m1);
         assertFalse(a.equals(b));
         assertFalse(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertFalse(b.containsAll(a));
         b.add(m1);
         assertTrue(a.equals(b));
         assertTrue(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertTrue(b.containsAll(a));
         assertEquals(a.hashCode(), b.hashCode());
-
-        assertFalse(a.equals(null));
     }
 
     /**
-     * containsAll returns true for collections with subset of elements
+     * containsAll returns true for collection with subset of elements
      */
     public void testContainsAll() {
         CopyOnWriteArrayList full = populatedArray(3);
@@ -209,11 +201,6 @@
         assertTrue(full.containsAll(Arrays.asList(one, two)));
         assertFalse(full.containsAll(Arrays.asList(one, two, six)));
         assertFalse(full.containsAll(Arrays.asList(six)));
-
-        try {
-            full.containsAll(null);
-            shouldThrow();
-        } catch (NullPointerException success) {}
     }
 
     /**
@@ -355,7 +342,7 @@
         ListIterator i = full.listIterator(1);
         int j;
         for (j = 0; i.hasNext(); j++)
-            assertEquals(j + 1, i.next());
+            assertEquals(j+1, i.next());
         assertEquals(2, j);
     }
 
@@ -454,7 +441,7 @@
         a = new Integer[0];
         assertSame(a, empty.toArray(a));
 
-        a = new Integer[SIZE / 2];
+        a = new Integer[SIZE/2];
         Arrays.fill(a, 42);
         assertSame(a, empty.toArray(a));
         assertNull(a[0]);
@@ -478,7 +465,7 @@
         assertSame(a, full.toArray(a));
         assertTrue(Arrays.equals(elements, a));
 
-        a = new Integer[2 * SIZE];
+        a = new Integer[2*SIZE];
         Arrays.fill(a, 42);
         assertSame(a, full.toArray(a));
         assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE)));
diff --git a/jsr166-tests/src/test/java/jsr166/CopyOnWriteArraySetTest.java b/jsr166-tests/src/test/java/jsr166/CopyOnWriteArraySetTest.java
index a486c6a..2810802 100644
--- a/jsr166-tests/src/test/java/jsr166/CopyOnWriteArraySetTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CopyOnWriteArraySetTest.java
@@ -28,7 +28,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(CopyOnWriteArraySetTest.class);
+    //     return new TestSuite(...);
     // }
 
     static CopyOnWriteArraySet<Integer> populatedSet(int n) {
@@ -64,7 +64,7 @@
      */
     public void testConstructor3() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         CopyOnWriteArraySet a = new CopyOnWriteArraySet(Arrays.asList(ints));
         for (int i = 0; i < SIZE; ++i)
@@ -139,46 +139,14 @@
         CopyOnWriteArraySet b = populatedSet(3);
         assertTrue(a.equals(b));
         assertTrue(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertTrue(b.containsAll(a));
         assertEquals(a.hashCode(), b.hashCode());
-        assertEquals(a.size(), b.size());
-
         a.add(m1);
         assertFalse(a.equals(b));
         assertFalse(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertFalse(b.containsAll(a));
         b.add(m1);
         assertTrue(a.equals(b));
         assertTrue(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertTrue(b.containsAll(a));
         assertEquals(a.hashCode(), b.hashCode());
-
-        Object x = a.iterator().next();
-        a.remove(x);
-        assertFalse(a.equals(b));
-        assertFalse(b.equals(a));
-        assertFalse(a.containsAll(b));
-        assertTrue(b.containsAll(a));
-        a.add(x);
-        assertTrue(a.equals(b));
-        assertTrue(b.equals(a));
-        assertTrue(a.containsAll(b));
-        assertTrue(b.containsAll(a));
-        assertEquals(a.hashCode(), b.hashCode());
-        assertEquals(a.size(), b.size());
-
-        CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList());
-        CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList());
-        assertTrue(empty1.equals(empty1));
-        assertTrue(empty1.equals(empty2));
-
-        assertFalse(empty1.equals(a));
-        assertFalse(a.equals(empty1));
-
-        assertFalse(a.equals(null));
     }
 
     /**
@@ -186,24 +154,11 @@
      */
     public void testContainsAll() {
         Collection full = populatedSet(3);
-        assertTrue(full.containsAll(full));
         assertTrue(full.containsAll(Arrays.asList()));
         assertTrue(full.containsAll(Arrays.asList(one)));
         assertTrue(full.containsAll(Arrays.asList(one, two)));
         assertFalse(full.containsAll(Arrays.asList(one, two, six)));
         assertFalse(full.containsAll(Arrays.asList(six)));
-
-        CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList());
-        CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList());
-        assertTrue(empty1.containsAll(empty2));
-        assertTrue(empty1.containsAll(empty1));
-        assertFalse(empty1.containsAll(full));
-        assertTrue(full.containsAll(empty1));
-
-        try {
-            full.containsAll(null);
-            shouldThrow();
-        } catch (NullPointerException success) {}
     }
 
     /**
@@ -334,7 +289,7 @@
         a = new Integer[0];
         assertSame(a, empty.toArray(a));
 
-        a = new Integer[SIZE / 2];
+        a = new Integer[SIZE/2];
         Arrays.fill(a, 42);
         assertSame(a, empty.toArray(a));
         assertNull(a[0]);
@@ -358,7 +313,7 @@
         assertSame(a, full.toArray(a));
         assertTrue(Arrays.equals(elements, a));
 
-        a = new Integer[2 * SIZE];
+        a = new Integer[2*SIZE];
         Arrays.fill(a, 42);
         assertSame(a, full.toArray(a));
         assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE)));
@@ -372,10 +327,10 @@
      * not store the objects inside the set
      */
     public void testToArray_ArrayStoreException() {
-        CopyOnWriteArraySet c = new CopyOnWriteArraySet();
-        c.add("zfasdfsdf");
-        c.add("asdadasd");
         try {
+            CopyOnWriteArraySet c = new CopyOnWriteArraySet();
+            c.add("zfasdfsdf");
+            c.add("asdadasd");
             c.toArray(new Long[5]);
             shouldThrow();
         } catch (ArrayStoreException success) {}
diff --git a/jsr166-tests/src/test/java/jsr166/CountDownLatchTest.java b/jsr166-tests/src/test/java/jsr166/CountDownLatchTest.java
index e764c9e..da1ebb4 100644
--- a/jsr166-tests/src/test/java/jsr166/CountDownLatchTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CountDownLatchTest.java
@@ -23,7 +23,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(CountDownLatchTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/CountedCompleterTest.java b/jsr166-tests/src/test/java/jsr166/CountedCompleterTest.java
index 8a38eff..80d7b3b 100644
--- a/jsr166-tests/src/test/java/jsr166/CountedCompleterTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CountedCompleterTest.java
@@ -31,7 +31,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(CountedCompleterTest.class);
+    //     return new TestSuite(...);
     // }
 
     // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
@@ -53,7 +53,7 @@
     }
 
     private void testInvokeOnPool(ForkJoinPool pool, ForkJoinTask a) {
-        try (PoolCleaner cleaner = cleaner(pool)) {
+        try {
             assertFalse(a.isDone());
             assertFalse(a.isCompletedNormally());
             assertFalse(a.isCompletedAbnormally());
@@ -69,6 +69,8 @@
             assertFalse(a.isCancelled());
             assertNull(a.getException());
             assertNull(a.getRawResult());
+        } finally {
+            joinPool(pool);
         }
     }
 
@@ -97,17 +99,17 @@
 
         {
             Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             assertNull(a.join());
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
             Thread.interrupted();
         }
 
         {
             Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
             Thread.interrupted();
         }
 
@@ -140,9 +142,9 @@
         Thread.interrupted();
 
         {
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
         }
 
         try {
@@ -178,9 +180,9 @@
         Thread.interrupted();
 
         {
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
         }
 
         try {
@@ -282,9 +284,6 @@
     final class NoopCC extends CheckedCC {
         NoopCC() { super(); }
         NoopCC(CountedCompleter p) { super(p); }
-        NoopCC(CountedCompleter p, int initialPendingCount) {
-            super(p, initialPendingCount);
-        }
         protected void realCompute() {}
     }
 
@@ -303,7 +302,6 @@
     void testComplete(NoopCC cc, Object x, int pendingCount) {
         cc.setPendingCount(pendingCount);
         cc.checkCompletes(x);
-        assertEquals(pendingCount, cc.getPendingCount());
     }
 
     /**
@@ -317,20 +315,14 @@
     }
 
     /**
-     * completeExceptionally(null) surprisingly has the same effect as
-     * completeExceptionally(new RuntimeException())
+     * completeExceptionally(null) throws NullPointerException
      */
     public void testCompleteExceptionally_null() {
-        NoopCC a = new NoopCC();
-        a.completeExceptionally(null);
         try {
-            a.invoke();
+            new NoopCC()
+                .checkCompletesExceptionally(null);
             shouldThrow();
-        } catch (RuntimeException success) {
-            assertSame(success.getClass(), RuntimeException.class);
-            assertNull(success.getCause());
-            a.checkCompletedExceptionally(success);
-        }
+        } catch (NullPointerException success) {}
     }
 
     /**
@@ -339,15 +331,10 @@
     public void testSetPendingCount() {
         NoopCC a = new NoopCC();
         assertEquals(0, a.getPendingCount());
-        int[] vals = {
-             -1, 0, 1,
-             Integer.MIN_VALUE,
-             Integer.MAX_VALUE,
-        };
-        for (int val : vals) {
-            a.setPendingCount(val);
-            assertEquals(val, a.getPendingCount());
-        }
+        a.setPendingCount(1);
+        assertEquals(1, a.getPendingCount());
+        a.setPendingCount(27);
+        assertEquals(27, a.getPendingCount());
     }
 
     /**
@@ -360,26 +347,21 @@
         assertEquals(1, a.getPendingCount());
         a.addToPendingCount(27);
         assertEquals(28, a.getPendingCount());
-        a.addToPendingCount(-28);
-        assertEquals(0, a.getPendingCount());
     }
 
     /**
      * decrementPendingCountUnlessZero decrements reported pending
      * count unless zero
      */
-    public void testDecrementPendingCountUnlessZero() {
-        NoopCC a = new NoopCC(null, 2);
-        assertEquals(2, a.getPendingCount());
-        assertEquals(2, a.decrementPendingCountUnlessZero());
+    public void testDecrementPendingCount() {
+        NoopCC a = new NoopCC();
+        assertEquals(0, a.getPendingCount());
+        a.addToPendingCount(1);
         assertEquals(1, a.getPendingCount());
-        assertEquals(1, a.decrementPendingCountUnlessZero());
+        a.decrementPendingCountUnlessZero();
         assertEquals(0, a.getPendingCount());
-        assertEquals(0, a.decrementPendingCountUnlessZero());
+        a.decrementPendingCountUnlessZero();
         assertEquals(0, a.getPendingCount());
-        a.setPendingCount(-1);
-        assertEquals(-1, a.decrementPendingCountUnlessZero());
-        assertEquals(-2, a.getPendingCount());
     }
 
     /**
@@ -503,7 +485,7 @@
     }
 
     /**
-     * quietlyCompleteRoot completes root task and only root task
+     * quietlyCompleteRoot completes root task
      */
     public void testQuietlyCompleteRoot() {
         NoopCC a = new NoopCC();
diff --git a/jsr166-tests/src/test/java/jsr166/CyclicBarrierTest.java b/jsr166-tests/src/test/java/jsr166/CyclicBarrierTest.java
index 37adcb1..a9d8c54 100644
--- a/jsr166-tests/src/test/java/jsr166/CyclicBarrierTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CyclicBarrierTest.java
@@ -27,7 +27,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(CyclicBarrierTest.class);
+    //     return new TestSuite(...);
     // }
 
     private volatile int countAction;
diff --git a/jsr166-tests/src/test/java/jsr166/DelayQueueTest.java b/jsr166-tests/src/test/java/jsr166/DelayQueueTest.java
index e42ac2d..7619b48 100644
--- a/jsr166-tests/src/test/java/jsr166/DelayQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/DelayQueueTest.java
@@ -25,26 +25,25 @@
 
 import junit.framework.Test;
 
-public class DelayQueueTest extends JSR166TestCase {
+// android-changed: Extend BlockingQueueTest directly.
+public class DelayQueueTest extends BlockingQueueTest {
 
     // android-changed: Extend BlockingQueueTest directly instead of creating
     // an inner class and its associated suite.
     //
     // public static class Generic extends BlockingQueueTest {
-    //     protected BlockingQueue emptyCollection() {
+    //    protected BlockingQueue emptyCollection() {
     //         return new DelayQueue();
     //     }
     //     protected PDelay makeElement(int i) {
     //         return new PDelay(i);
     //     }
     // }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(DelayQueueTest.class,
     //                         new Generic().testSuite());
@@ -139,7 +138,7 @@
     private DelayQueue<PDelay> populatedQueue(int n) {
         DelayQueue<PDelay> q = new DelayQueue<PDelay>();
         assertTrue(q.isEmpty());
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.offer(new PDelay(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.offer(new PDelay(i)));
@@ -171,7 +170,8 @@
      */
     public void testConstructor4() {
         try {
-            new DelayQueue(Arrays.asList(new PDelay[SIZE]));
+            PDelay[] ints = new PDelay[SIZE];
+            new DelayQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -180,11 +180,11 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        PDelay[] a = new PDelay[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            a[i] = new PDelay(i);
         try {
-            new DelayQueue(Arrays.asList(a));
+            PDelay[] ints = new PDelay[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new PDelay(i);
+            new DelayQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -223,7 +223,7 @@
         BlockingQueue q = populatedQueue(SIZE);
         for (int i = 0; i < SIZE; ++i) {
             assertEquals(Integer.MAX_VALUE, q.remainingCapacity());
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             assertTrue(q.remove() instanceof PDelay);
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -257,8 +257,8 @@
      * addAll(this) throws IAE
      */
     public void testAddAllSelf() {
-        DelayQueue q = populatedQueue(SIZE);
         try {
+            DelayQueue q = populatedQueue(SIZE);
             q.addAll(q);
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -269,12 +269,12 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        DelayQueue q = new DelayQueue();
-        PDelay[] a = new PDelay[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            a[i] = new PDelay(i);
         try {
-            q.addAll(Arrays.asList(a));
+            DelayQueue q = new DelayQueue();
+            PDelay[] ints = new PDelay[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new PDelay(i);
+            q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -285,7 +285,7 @@
     public void testAddAll5() {
         PDelay[] empty = new PDelay[0];
         PDelay[] ints = new PDelay[SIZE];
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             ints[i] = new PDelay(i);
         DelayQueue q = new DelayQueue();
         assertFalse(q.addAll(Arrays.asList(empty)));
@@ -427,13 +427,11 @@
      */
     public void testInterruptedTimedPoll() throws InterruptedException {
         final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
-        final DelayQueue q = populatedQueue(SIZE);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
+                DelayQueue q = populatedQueue(SIZE);
                 for (int i = 0; i < SIZE; ++i) {
-                    assertEquals(new PDelay(i),
-                                 ((PDelay)q.poll(LONG_DELAY_MS, MILLISECONDS)));
+                    assertEquals(new PDelay(i), ((PDelay)q.poll(SHORT_DELAY_MS, MILLISECONDS)));
                 }
 
                 Thread.currentThread().interrupt();
@@ -449,14 +447,12 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         await(pleaseInterrupt);
         assertThreadStaysAlive(t);
         t.interrupt();
         awaitTermination(t);
-        checkEmpty(q);
     }
 
     /**
@@ -561,7 +557,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -574,7 +570,7 @@
             DelayQueue q = populatedQueue(SIZE);
             DelayQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 PDelay x = (PDelay)(p.remove());
                 assertFalse(q.contains(x));
@@ -672,22 +668,22 @@
     public void testPollInExecutor() {
         final DelayQueue q = new DelayQueue();
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertNotNull(q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    checkEmpty(q);
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertNotNull(q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(new PDelay(1));
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(new PDelay(1));
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -772,7 +768,7 @@
         final DelayQueue q = populatedQueue(SIZE);
         Thread t = new Thread(new CheckedRunnable() {
             public void realRun() {
-                q.put(new PDelay(SIZE + 1));
+                q.put(new PDelay(SIZE+1));
             }});
 
         t.start();
@@ -792,7 +788,7 @@
             ArrayList l = new ArrayList();
             q.drainTo(l, i);
             int k = (i < SIZE) ? i : SIZE;
-            assertEquals(SIZE - k, q.size());
+            assertEquals(SIZE-k, q.size());
             assertEquals(k, l.size());
         }
     }
diff --git a/jsr166-tests/src/test/java/jsr166/DoubleAccumulatorTest.java b/jsr166-tests/src/test/java/jsr166/DoubleAccumulatorTest.java
deleted file mode 100644
index e061f9a..0000000
--- a/jsr166-tests/src/test/java/jsr166/DoubleAccumulatorTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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 jsr166;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Phaser;
-import java.util.concurrent.atomic.DoubleAccumulator;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class DoubleAccumulatorTest extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(DoubleAccumulatorTest.class);
-    // }
-
-    /**
-     * default constructed initializes to zero
-     */
-    public void testConstructor() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals(0.0, ai.get());
-    }
-
-    /**
-     * accumulate accumulates given value to current, and get returns current value
-     */
-    public void testAccumulateAndGet() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        ai.accumulate(2.0);
-        assertEquals(2.0, ai.get());
-        ai.accumulate(-4.0);
-        assertEquals(2.0, ai.get());
-        ai.accumulate(4.0);
-        assertEquals(4.0, ai.get());
-    }
-
-    /**
-     * reset() causes subsequent get() to return zero
-     */
-    public void testReset() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        ai.accumulate(2.0);
-        assertEquals(2.0, ai.get());
-        ai.reset();
-        assertEquals(0.0, ai.get());
-    }
-
-    /**
-     * getThenReset() returns current value; subsequent get() returns zero
-     */
-    public void testGetThenReset() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        ai.accumulate(2.0);
-        assertEquals(2.0, ai.get());
-        assertEquals(2.0, ai.getThenReset());
-        assertEquals(0.0, ai.get());
-    }
-
-    /**
-     * toString returns current value.
-     */
-    public void testToString() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals("0.0", ai.toString());
-        ai.accumulate(1.0);
-        assertEquals(Double.toString(1.0), ai.toString());
-    }
-
-    /**
-     * intValue returns current value.
-     */
-    public void testIntValue() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals(0, ai.intValue());
-        ai.accumulate(1.0);
-        assertEquals(1, ai.intValue());
-    }
-
-    /**
-     * longValue returns current value.
-     */
-    public void testLongValue() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals(0, ai.longValue());
-        ai.accumulate(1.0);
-        assertEquals(1, ai.longValue());
-    }
-
-    /**
-     * floatValue returns current value.
-     */
-    public void testFloatValue() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals(0.0f, ai.floatValue());
-        ai.accumulate(1.0);
-        assertEquals(1.0f, ai.floatValue());
-    }
-
-    /**
-     * doubleValue returns current value.
-     */
-    public void testDoubleValue() {
-        DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0);
-        assertEquals(0.0, ai.doubleValue());
-        ai.accumulate(1.0);
-        assertEquals(1.0, ai.doubleValue());
-    }
-
-    /**
-     * accumulates by multiple threads produce correct result
-     */
-    public void testAccumulateAndGetMT() {
-        final int incs = 1000000;
-        final int nthreads = 4;
-        final ExecutorService pool = Executors.newCachedThreadPool();
-        DoubleAccumulator a = new DoubleAccumulator(Double::max, 0.0);
-        Phaser phaser = new Phaser(nthreads + 1);
-        for (int i = 0; i < nthreads; ++i)
-            pool.execute(new AccTask(a, phaser, incs));
-        phaser.arriveAndAwaitAdvance();
-        phaser.arriveAndAwaitAdvance();
-        double expected = incs - 1;
-        double result = a.get();
-        assertEquals(expected, result);
-        pool.shutdown();
-    }
-
-    static final class AccTask implements Runnable {
-        final DoubleAccumulator acc;
-        final Phaser phaser;
-        final int incs;
-        volatile double result;
-        AccTask(DoubleAccumulator acc, Phaser phaser, int incs) {
-            this.acc = acc;
-            this.phaser = phaser;
-            this.incs = incs;
-        }
-
-        public void run() {
-            phaser.arriveAndAwaitAdvance();
-            DoubleAccumulator a = acc;
-            for (int i = 0; i < incs; ++i)
-                a.accumulate(i);
-            result = a.get();
-            phaser.arrive();
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/DoubleAdderTest.java b/jsr166-tests/src/test/java/jsr166/DoubleAdderTest.java
deleted file mode 100644
index d02e2a1..0000000
--- a/jsr166-tests/src/test/java/jsr166/DoubleAdderTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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 jsr166;
-
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.DoubleAdder;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class DoubleAdderTest extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(DoubleAdderTest.class);
-    // }
-
-    /**
-     * default constructed initializes to zero
-     */
-    public void testConstructor() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(0.0, ai.sum());
-    }
-
-    /**
-     * add adds given value to current, and sum returns current value
-     */
-    public void testAddAndSum() {
-        DoubleAdder ai = new DoubleAdder();
-        ai.add(2.0);
-        assertEquals(2.0, ai.sum());
-        ai.add(-4.0);
-        assertEquals(-2.0, ai.sum());
-    }
-
-    /**
-     * reset() causes subsequent sum() to return zero
-     */
-    public void testReset() {
-        DoubleAdder ai = new DoubleAdder();
-        ai.add(2.0);
-        assertEquals(2.0, ai.sum());
-        ai.reset();
-        assertEquals(0.0, ai.sum());
-    }
-
-    /**
-     * sumThenReset() returns sum; subsequent sum() returns zero
-     */
-    public void testSumThenReset() {
-        DoubleAdder ai = new DoubleAdder();
-        ai.add(2.0);
-        assertEquals(2.0, ai.sum());
-        assertEquals(2.0, ai.sumThenReset());
-        assertEquals(0.0, ai.sum());
-    }
-
-    /**
-     * a deserialized serialized adder holds same value
-     */
-    public void testSerialization() throws Exception {
-        DoubleAdder x = new DoubleAdder();
-        DoubleAdder y = serialClone(x);
-        assertNotSame(x, y);
-        x.add(-22.0);
-        DoubleAdder z = serialClone(x);
-        assertEquals(-22.0, x.sum());
-        assertEquals(0.0, y.sum());
-        assertEquals(-22.0, z.sum());
-    }
-
-    /**
-     * toString returns current value.
-     */
-    public void testToString() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(Double.toString(0.0), ai.toString());
-        ai.add(1.0);
-        assertEquals(Double.toString(1.0), ai.toString());
-    }
-
-    /**
-     * intValue returns current value.
-     */
-    public void testIntValue() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(0, ai.intValue());
-        ai.add(1.0);
-        assertEquals(1, ai.intValue());
-    }
-
-    /**
-     * longValue returns current value.
-     */
-    public void testLongValue() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(0, ai.longValue());
-        ai.add(1.0);
-        assertEquals(1, ai.longValue());
-    }
-
-    /**
-     * floatValue returns current value.
-     */
-    public void testFloatValue() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(0.0f, ai.floatValue());
-        ai.add(1.0);
-        assertEquals(1.0f, ai.floatValue());
-    }
-
-    /**
-     * doubleValue returns current value.
-     */
-    public void testDoubleValue() {
-        DoubleAdder ai = new DoubleAdder();
-        assertEquals(0.0, ai.doubleValue());
-        ai.add(1.0);
-        assertEquals(1.0, ai.doubleValue());
-    }
-
-    /**
-     * adds by multiple threads produce correct sum
-     */
-    public void testAddAndSumMT() throws Throwable {
-        final int incs = 1000000;
-        final int nthreads = 4;
-        final ExecutorService pool = Executors.newCachedThreadPool();
-        DoubleAdder a = new DoubleAdder();
-        CyclicBarrier barrier = new CyclicBarrier(nthreads + 1);
-        for (int i = 0; i < nthreads; ++i)
-            pool.execute(new AdderTask(a, barrier, incs));
-        barrier.await();
-        barrier.await();
-        double total = (long)nthreads * incs;
-        double sum = a.sum();
-        assertEquals(sum, total);
-        pool.shutdown();
-    }
-
-    static final class AdderTask implements Runnable {
-        final DoubleAdder adder;
-        final CyclicBarrier barrier;
-        final int incs;
-        volatile double result;
-        AdderTask(DoubleAdder adder, CyclicBarrier barrier, int incs) {
-            this.adder = adder;
-            this.barrier = barrier;
-            this.incs = incs;
-        }
-
-        public void run() {
-            try {
-                barrier.await();
-                DoubleAdder a = adder;
-                for (int i = 0; i < incs; ++i)
-                    a.add(1.0);
-                result = a.sum();
-                barrier.await();
-            } catch (Throwable t) { throw new Error(t); }
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/EntryTest.java b/jsr166-tests/src/test/java/jsr166/EntryTest.java
index 72740e3..d141a84 100644
--- a/jsr166-tests/src/test/java/jsr166/EntryTest.java
+++ b/jsr166-tests/src/test/java/jsr166/EntryTest.java
@@ -20,7 +20,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(EntryTest.class);
+    //     return new TestSuite(...);
     // }
 
     static final String k1 = "1";
diff --git a/jsr166-tests/src/test/java/jsr166/ExchangerTest.java b/jsr166-tests/src/test/java/jsr166/ExchangerTest.java
index b111980..172fccd 100644
--- a/jsr166-tests/src/test/java/jsr166/ExchangerTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ExchangerTest.java
@@ -26,7 +26,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ExchangerTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/ExecutorCompletionServiceTest.java b/jsr166-tests/src/test/java/jsr166/ExecutorCompletionServiceTest.java
index 0f58e78..e988cc6 100644
--- a/jsr166-tests/src/test/java/jsr166/ExecutorCompletionServiceTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ExecutorCompletionServiceTest.java
@@ -33,7 +33,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ExecutorCompletionServiceTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -61,14 +61,15 @@
      * Submitting a null callable throws NPE
      */
     public void testSubmitNPE() {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             Callable c = null;
-            try {
-                ecs.submit(c);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+            ecs.submit(c);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -76,14 +77,15 @@
      * Submitting a null runnable throws NPE
      */
     public void testSubmitNPE2() {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             Runnable r = null;
-            try {
-                ecs.submit(r, Boolean.TRUE);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+            ecs.submit(r, Boolean.TRUE);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -91,13 +93,15 @@
      * A taken submitted task is completed
      */
     public void testTake() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             Callable c = new StringTask();
             ecs.submit(c);
             Future f = ecs.take();
             assertTrue(f.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -105,13 +109,15 @@
      * Take returns the same future object returned by submit
      */
     public void testTake2() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             Callable c = new StringTask();
             Future f1 = ecs.submit(c);
             Future f2 = ecs.take();
             assertSame(f1, f2);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -119,9 +125,9 @@
      * If poll returns non-null, the returned task is completed
      */
     public void testPoll1() throws Exception {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             assertNull(ecs.poll());
             Callable c = new StringTask();
             ecs.submit(c);
@@ -135,6 +141,8 @@
             }
             assertTrue(f.isDone());
             assertSame(TEST_STRING, f.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -142,15 +150,17 @@
      * If timed poll returns non-null, the returned task is completed
      */
     public void testPoll2() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = Executors.newCachedThreadPool();
+        ExecutorCompletionService ecs = new ExecutorCompletionService(e);
+        try {
             assertNull(ecs.poll());
             Callable c = new StringTask();
             ecs.submit(c);
             Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS);
             if (f != null)
                 assertTrue(f.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -164,16 +174,15 @@
             MyCallableFuture(Callable<V> c) { super(c); }
             protected void done() { done.set(true); }
         }
-        final ExecutorService e =
-            new ThreadPoolExecutor(1, 1,
-                                   30L, TimeUnit.SECONDS,
-                                   new ArrayBlockingQueue<Runnable>(1)) {
-                protected <T> RunnableFuture<T> newTaskFor(Callable<T> c) {
-                    return new MyCallableFuture<T>(c);
-                }};
+        ExecutorService e = new ThreadPoolExecutor(
+                                 1, 1, 30L, TimeUnit.SECONDS,
+                                 new ArrayBlockingQueue<Runnable>(1)) {
+            protected <T> RunnableFuture<T> newTaskFor(Callable<T> c) {
+                return new MyCallableFuture<T>(c);
+            }};
         ExecutorCompletionService<String> ecs =
             new ExecutorCompletionService<String>(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             assertNull(ecs.poll());
             Callable<String> c = new StringTask();
             Future f1 = ecs.submit(c);
@@ -182,6 +191,8 @@
             Future f2 = ecs.take();
             assertSame("submit and take must return same objects", f1, f2);
             assertTrue("completed task must have set done", done.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -195,16 +206,15 @@
             MyRunnableFuture(Runnable t, V r) { super(t, r); }
             protected void done() { done.set(true); }
         }
-        final ExecutorService e =
-            new ThreadPoolExecutor(1, 1,
-                                   30L, TimeUnit.SECONDS,
-                                   new ArrayBlockingQueue<Runnable>(1)) {
-                protected <T> RunnableFuture<T> newTaskFor(Runnable t, T r) {
-                    return new MyRunnableFuture<T>(t, r);
-                }};
-        final ExecutorCompletionService<String> ecs =
+        ExecutorService e = new ThreadPoolExecutor(
+                                 1, 1, 30L, TimeUnit.SECONDS,
+                                 new ArrayBlockingQueue<Runnable>(1)) {
+            protected <T> RunnableFuture<T> newTaskFor(Runnable t, T r) {
+                return new MyRunnableFuture<T>(t, r);
+            }};
+        ExecutorCompletionService<String> ecs =
             new ExecutorCompletionService<String>(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             assertNull(ecs.poll());
             Runnable r = new NoOpRunnable();
             Future f1 = ecs.submit(r, null);
@@ -213,6 +223,8 @@
             Future f2 = ecs.take();
             assertSame("submit and take must return same objects", f1, f2);
             assertTrue("completed task must have set done", done.get());
+        } finally {
+            joinPool(e);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ExecutorsTest.java b/jsr166-tests/src/test/java/jsr166/ExecutorsTest.java
index d70ae6e..ae475f1 100644
--- a/jsr166-tests/src/test/java/jsr166/ExecutorsTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ExecutorsTest.java
@@ -36,31 +36,29 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ExecutorsTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
      * A newCachedThreadPool can execute runnables
      */
     public void testNewCachedThreadPool1() {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newCachedThreadPool();
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
      * A newCachedThreadPool with given ThreadFactory can execute runnables
      */
     public void testNewCachedThreadPool2() {
-        final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
@@ -77,24 +75,22 @@
      * A new SingleThreadExecutor can execute runnables
      */
     public void testNewSingleThreadExecutor1() {
-        final ExecutorService e = Executors.newSingleThreadExecutor();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newSingleThreadExecutor();
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
      * A new SingleThreadExecutor with given ThreadFactory can execute runnables
      */
     public void testNewSingleThreadExecutor2() {
-        final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
@@ -111,12 +107,13 @@
      * A new SingleThreadExecutor cannot be casted to concrete implementation
      */
     public void testCastNewSingleThreadExecutor() {
-        final ExecutorService e = Executors.newSingleThreadExecutor();
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
-                shouldThrow();
-            } catch (ClassCastException success) {}
+        ExecutorService e = Executors.newSingleThreadExecutor();
+        try {
+            ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
+            shouldThrow();
+        } catch (ClassCastException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -124,24 +121,22 @@
      * A new newFixedThreadPool can execute runnables
      */
     public void testNewFixedThreadPool1() {
-        final ExecutorService e = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newFixedThreadPool(2);
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
      * A new newFixedThreadPool with given ThreadFactory can execute runnables
      */
     public void testNewFixedThreadPool2() {
-        final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
@@ -168,12 +163,11 @@
      * An unconfigurable newFixedThreadPool can execute runnables
      */
     public void testUnconfigurableExecutorService() {
-        final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-            e.execute(new NoOpRunnable());
-        }
+        ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        e.execute(new NoOpRunnable());
+        joinPool(e);
     }
 
     /**
@@ -200,8 +194,8 @@
      * a newSingleThreadScheduledExecutor successfully runs delayed task
      */
     public void testNewSingleThreadScheduledExecutor() throws Exception {
-        final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
-        try (PoolCleaner cleaner = cleaner(p)) {
+        ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
+        try {
             final CountDownLatch proceed = new CountDownLatch(1);
             final Runnable task = new CheckedRunnable() {
                 public void realRun() {
@@ -217,6 +211,8 @@
             assertTrue(f.isDone());
             assertFalse(f.isCancelled());
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -224,8 +220,8 @@
      * a newScheduledThreadPool successfully runs delayed task
      */
     public void testNewScheduledThreadPool() throws Exception {
-        final ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
+        try {
             final CountDownLatch proceed = new CountDownLatch(1);
             final Runnable task = new CheckedRunnable() {
                 public void realRun() {
@@ -241,6 +237,8 @@
             assertTrue(f.isDone());
             assertFalse(f.isCancelled());
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -248,10 +246,10 @@
      * an unconfigurable newScheduledThreadPool successfully runs delayed task
      */
     public void testUnconfigurableScheduledExecutorService() throws Exception {
-        final ScheduledExecutorService p =
+        ScheduledExecutorService p =
             Executors.unconfigurableScheduledExecutorService
             (Executors.newScheduledThreadPool(2));
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             final CountDownLatch proceed = new CountDownLatch(1);
             final Runnable task = new CheckedRunnable() {
                 public void realRun() {
@@ -267,6 +265,8 @@
             assertTrue(f.isDone());
             assertFalse(f.isCancelled());
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -327,10 +327,16 @@
                 done.countDown();
             }};
         ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
-            e.execute(r);
-            await(done);
+
+        e.execute(r);
+        await(done);
+
+        try {
+            e.shutdown();
+        } catch (SecurityException ok) {
         }
+
+        joinPool(e);
     }
 
     /**
@@ -360,14 +366,14 @@
                         String name = current.getName();
                         assertTrue(name.endsWith("thread-1"));
                         assertSame(thisccl, current.getContextClassLoader());
-                        //assertEquals(thisacc, AccessController.getContext());
+                        // assertEquals(thisacc, AccessController.getContext());
                         done.countDown();
                     }};
                 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
-                try (PoolCleaner cleaner = cleaner(e)) {
-                    e.execute(r);
-                    await(done);
-                }
+                e.execute(r);
+                await(done);
+                e.shutdown();
+                joinPool(e);
             }};
 
         runWithPermissions(r,
diff --git a/jsr166-tests/src/test/java/jsr166/ForkJoinPool8Test.java b/jsr166-tests/src/test/java/jsr166/ForkJoinPool8Test.java
deleted file mode 100644
index f9f9239..0000000
--- a/jsr166-tests/src/test/java/jsr166/ForkJoinPool8Test.java
+++ /dev/null
@@ -1,1592 +0,0 @@
-/*
- * 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 jsr166;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import java.util.HashSet;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CountedCompleter;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.RecursiveAction;
-import java.util.concurrent.TimeoutException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class ForkJoinPool8Test extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(ForkJoinPool8Test.class);
-    // }
-
-    /**
-     * Common pool exists and has expected parallelism.
-     */
-    public void testCommonPoolParallelism() {
-        assertEquals(ForkJoinPool.getCommonPoolParallelism(),
-                     ForkJoinPool.commonPool().getParallelism());
-    }
-
-    /**
-     * Common pool cannot be shut down
-     */
-    public void testCommonPoolShutDown() {
-        assertFalse(ForkJoinPool.commonPool().isShutdown());
-        assertFalse(ForkJoinPool.commonPool().isTerminating());
-        assertFalse(ForkJoinPool.commonPool().isTerminated());
-        ForkJoinPool.commonPool().shutdown();
-        assertFalse(ForkJoinPool.commonPool().isShutdown());
-        assertFalse(ForkJoinPool.commonPool().isTerminating());
-        assertFalse(ForkJoinPool.commonPool().isTerminated());
-        ForkJoinPool.commonPool().shutdownNow();
-        assertFalse(ForkJoinPool.commonPool().isShutdown());
-        assertFalse(ForkJoinPool.commonPool().isTerminating());
-        assertFalse(ForkJoinPool.commonPool().isTerminated());
-    }
-
-    /*
-     * All of the following test methods are adaptations of those for
-     * RecursiveAction and CountedCompleter, but with all actions
-     * executed in the common pool, generally implicitly via
-     * checkInvoke.
-     */
-
-    private void checkInvoke(ForkJoinTask a) {
-        checkNotDone(a);
-        assertNull(a.invoke());
-        checkCompletedNormally(a);
-    }
-
-    void checkNotDone(ForkJoinTask a) {
-        assertFalse(a.isDone());
-        assertFalse(a.isCompletedNormally());
-        assertFalse(a.isCompletedAbnormally());
-        assertFalse(a.isCancelled());
-        assertNull(a.getException());
-        assertNull(a.getRawResult());
-
-        if (! ForkJoinTask.inForkJoinPool()) {
-            Thread.currentThread().interrupt();
-            try {
-                a.get();
-                shouldThrow();
-            } catch (InterruptedException success) {
-            } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-            Thread.currentThread().interrupt();
-            try {
-                a.get(5L, SECONDS);
-                shouldThrow();
-            } catch (InterruptedException success) {
-            } catch (Throwable fail) { threadUnexpectedException(fail); }
-        }
-
-        try {
-            a.get(0L, SECONDS);
-            shouldThrow();
-        } catch (TimeoutException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    void checkCompletedNormally(ForkJoinTask a) {
-        assertTrue(a.isDone());
-        assertFalse(a.isCancelled());
-        assertTrue(a.isCompletedNormally());
-        assertFalse(a.isCompletedAbnormally());
-        assertNull(a.getException());
-        assertNull(a.getRawResult());
-        assertNull(a.join());
-        assertFalse(a.cancel(false));
-        assertFalse(a.cancel(true));
-        try {
-            assertNull(a.get());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        try {
-            assertNull(a.get(5L, SECONDS));
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    void checkCancelled(ForkJoinTask a) {
-        assertTrue(a.isDone());
-        assertTrue(a.isCancelled());
-        assertFalse(a.isCompletedNormally());
-        assertTrue(a.isCompletedAbnormally());
-        assertTrue(a.getException() instanceof CancellationException);
-        assertNull(a.getRawResult());
-
-        try {
-            a.join();
-            shouldThrow();
-        } catch (CancellationException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            a.get();
-            shouldThrow();
-        } catch (CancellationException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            a.get(5L, SECONDS);
-            shouldThrow();
-        } catch (CancellationException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
-        assertTrue(a.isDone());
-        assertFalse(a.isCancelled());
-        assertFalse(a.isCompletedNormally());
-        assertTrue(a.isCompletedAbnormally());
-        assertSame(t.getClass(), a.getException().getClass());
-        assertNull(a.getRawResult());
-        assertFalse(a.cancel(false));
-        assertFalse(a.cancel(true));
-
-        try {
-            a.join();
-            shouldThrow();
-        } catch (Throwable expected) {
-            assertSame(expected.getClass(), t.getClass());
-        }
-
-        try {
-            a.get();
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(t.getClass(), success.getCause().getClass());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            a.get(5L, SECONDS);
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(t.getClass(), success.getCause().getClass());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    public static final class FJException extends RuntimeException {
-        public FJException() { super(); }
-        public FJException(Throwable cause) { super(cause); }
-    }
-
-    // A simple recursive action for testing
-    final class FibAction extends CheckedRecursiveAction {
-        final int number;
-        int result;
-        FibAction(int n) { number = n; }
-        protected void realCompute() {
-            int n = number;
-            if (n <= 1)
-                result = n;
-            else {
-                FibAction f1 = new FibAction(n - 1);
-                FibAction f2 = new FibAction(n - 2);
-                invokeAll(f1, f2);
-                result = f1.result + f2.result;
-            }
-        }
-    }
-
-    // A recursive action failing in base case
-    static final class FailingFibAction extends RecursiveAction {
-        final int number;
-        int result;
-        FailingFibAction(int n) { number = n; }
-        public void compute() {
-            int n = number;
-            if (n <= 1)
-                throw new FJException();
-            else {
-                FailingFibAction f1 = new FailingFibAction(n - 1);
-                FailingFibAction f2 = new FailingFibAction(n - 2);
-                invokeAll(f1, f2);
-                result = f1.result + f2.result;
-            }
-        }
-    }
-
-    /**
-     * invoke returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks. getRawResult of a RecursiveAction returns null;
-     */
-    public void testInvoke() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertNull(f.invoke());
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks
-     */
-    public void testQuietlyInvoke() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                f.quietlyInvoke();
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task returns when task completes
-     */
-    public void testForkJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertSame(f, f.fork());
-                assertNull(f.join());
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join/quietlyJoin of a forked task succeeds in the presence of interrupts
-     */
-    public void testJoinIgnoresInterrupts() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                final Thread myself = Thread.currentThread();
-
-                // test join()
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                assertNull(f.join());
-                Thread.interrupted();
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-
-                f = new FibAction(8);
-                f.cancel(true);
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    Thread.interrupted();
-                    checkCancelled(f);
-                }
-
-                f = new FibAction(8);
-                f.completeExceptionally(new FJException());
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (FJException success) {
-                    Thread.interrupted();
-                    checkCompletedAbnormally(f, success);
-                }
-
-                // test quietlyJoin()
-                f = new FibAction(8);
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                f.quietlyJoin();
-                Thread.interrupted();
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-
-                f = new FibAction(8);
-                f.cancel(true);
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                f.quietlyJoin();
-                Thread.interrupted();
-                checkCancelled(f);
-
-                f = new FibAction(8);
-                f.completeExceptionally(new FJException());
-                assertSame(f, f.fork());
-                myself.interrupt();
-                assertTrue(myself.isInterrupted());
-                f.quietlyJoin();
-                Thread.interrupted();
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        checkInvoke(a);
-        a.reinitialize();
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task returns when task completes
-     */
-    public void testForkGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FibAction f = new FibAction(8);
-                assertSame(f, f.fork());
-                assertNull(f.get());
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task returns when task completes
-     */
-    public void testForkTimedGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FibAction f = new FibAction(8);
-                assertSame(f, f.fork());
-                assertNull(f.get(5L, SECONDS));
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get with null time unit throws NPE
-     */
-    public void testForkTimedGetNPE() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FibAction f = new FibAction(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(5L, null);
-                    shouldThrow();
-                } catch (NullPointerException success) {}
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes
-     */
-    public void testForkQuietlyJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                assertEquals(21, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task throws exception when task completes abnormally
-     */
-    public void testAbnormalInvoke() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes abnormally
-     */
-    public void testAbnormalQuietlyInvoke() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                f.quietlyInvoke();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                assertSame(f, f.fork());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingFibAction f = new FailingFibAction(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get();
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkTimedGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingFibAction f = new FailingFibAction(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(5L, SECONDS);
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes abnormally
-     */
-    public void testAbnormalForkQuietlyJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task throws exception when task cancelled
-     */
-    public void testCancelledInvoke() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertTrue(f.cancel(true));
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FibAction f = new FibAction(8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.get();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkTimedGet() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FibAction f = new FibAction(8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.get(5L, SECONDS);
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task cancelled
-     */
-    public void testCancelledForkQuietlyJoin() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                checkCancelled(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * inForkJoinPool of non-FJ task returns false
-     */
-    public void testInForkJoinPool2() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertFalse(inForkJoinPool());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * A reinitialized normally completed task may be re-invoked
-     */
-    public void testReinitialize() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                checkNotDone(f);
-
-                for (int i = 0; i < 3; i++) {
-                    assertNull(f.invoke());
-                    assertEquals(21, f.result);
-                    checkCompletedNormally(f);
-                    f.reinitialize();
-                    checkNotDone(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * A reinitialized abnormally completed task may be re-invoked
-     */
-    public void testReinitializeAbnormal() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                checkNotDone(f);
-
-                for (int i = 0; i < 3; i++) {
-                    try {
-                        f.invoke();
-                        shouldThrow();
-                    } catch (FJException success) {
-                        checkCompletedAbnormally(f, success);
-                    }
-                    f.reinitialize();
-                    checkNotDone(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task throws exception after invoking completeExceptionally
-     */
-    public void testCompleteExceptionally() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                f.completeExceptionally(new FJException());
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task suppresses execution invoking complete
-     */
-    public void testComplete() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                f.complete(null);
-                assertNull(f.invoke());
-                assertEquals(0, f.result);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(t1, t2) invokes all task arguments
-     */
-    public void testInvokeAll2() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FibAction g = new FibAction(9);
-                invokeAll(f, g);
-                checkCompletedNormally(f);
-                assertEquals(21, f.result);
-                checkCompletedNormally(g);
-                assertEquals(34, g.result);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument invokes task
-     */
-    public void testInvokeAll1() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                invokeAll(f);
-                checkCompletedNormally(f);
-                assertEquals(21, f.result);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument invokes tasks
-     */
-    public void testInvokeAll3() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FibAction g = new FibAction(9);
-                FibAction h = new FibAction(7);
-                invokeAll(f, g, h);
-                assertTrue(f.isDone());
-                assertTrue(g.isDone());
-                assertTrue(h.isDone());
-                checkCompletedNormally(f);
-                assertEquals(21, f.result);
-                checkCompletedNormally(g);
-                assertEquals(34, g.result);
-                checkCompletedNormally(g);
-                assertEquals(13, h.result);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(collection) invokes all tasks in the collection
-     */
-    public void testInvokeAllCollection() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FibAction g = new FibAction(9);
-                FibAction h = new FibAction(7);
-                HashSet set = new HashSet();
-                set.add(f);
-                set.add(g);
-                set.add(h);
-                invokeAll(set);
-                assertTrue(f.isDone());
-                assertTrue(g.isDone());
-                assertTrue(h.isDone());
-                checkCompletedNormally(f);
-                assertEquals(21, f.result);
-                checkCompletedNormally(g);
-                assertEquals(34, g.result);
-                checkCompletedNormally(g);
-                assertEquals(13, h.result);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with any null task throws NPE
-     */
-    public void testInvokeAllNPE() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FibAction g = new FibAction(9);
-                FibAction h = null;
-                try {
-                    invokeAll(f, g, h);
-                    shouldThrow();
-                } catch (NullPointerException success) {}
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(t1, t2) throw exception if any task does
-     */
-    public void testAbnormalInvokeAll2() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FailingFibAction g = new FailingFibAction(9);
-                try {
-                    invokeAll(f, g);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument throws exception if task does
-     */
-    public void testAbnormalInvokeAll1() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction g = new FailingFibAction(9);
-                try {
-                    invokeAll(g);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument throws exception if any task does
-     */
-    public void testAbnormalInvokeAll3() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FibAction f = new FibAction(8);
-                FailingFibAction g = new FailingFibAction(9);
-                FibAction h = new FibAction(7);
-                try {
-                    invokeAll(f, g, h);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(collection) throws exception if any task does
-     */
-    public void testAbnormalInvokeAllCollection() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingFibAction f = new FailingFibAction(8);
-                FibAction g = new FibAction(9);
-                FibAction h = new FibAction(7);
-                HashSet set = new HashSet();
-                set.add(f);
-                set.add(g);
-                set.add(h);
-                try {
-                    invokeAll(set);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    // CountedCompleter versions
-
-    abstract static class CCF extends CountedCompleter {
-        int number;
-        int rnumber;
-
-        public CCF(CountedCompleter parent, int n) {
-            super(parent, 1);
-            this.number = n;
-        }
-
-        public final void compute() {
-            CountedCompleter p;
-            CCF f = this;
-            int n = number;
-            while (n >= 2) {
-                new RCCF(f, n - 2).fork();
-                f = new LCCF(f, --n);
-            }
-            f.number = n;
-            f.onCompletion(f);
-            if ((p = f.getCompleter()) != null)
-                p.tryComplete();
-            else
-                f.quietlyComplete();
-        }
-    }
-
-    static final class LCCF extends CCF {
-        public LCCF(CountedCompleter parent, int n) {
-            super(parent, n);
-        }
-        public final void onCompletion(CountedCompleter caller) {
-            CCF p = (CCF)getCompleter();
-            int n = number + rnumber;
-            if (p != null)
-                p.number = n;
-            else
-                number = n;
-        }
-    }
-    static final class RCCF extends CCF {
-        public RCCF(CountedCompleter parent, int n) {
-            super(parent, n);
-        }
-        public final void onCompletion(CountedCompleter caller) {
-            CCF p = (CCF)getCompleter();
-            int n = number + rnumber;
-            if (p != null)
-                p.rnumber = n;
-            else
-                number = n;
-        }
-    }
-
-    // Version of CCF with forced failure in left completions
-    abstract static class FailingCCF extends CountedCompleter {
-        int number;
-        int rnumber;
-
-        public FailingCCF(CountedCompleter parent, int n) {
-            super(parent, 1);
-            this.number = n;
-        }
-
-        public final void compute() {
-            CountedCompleter p;
-            FailingCCF f = this;
-            int n = number;
-            while (n >= 2) {
-                new RFCCF(f, n - 2).fork();
-                f = new LFCCF(f, --n);
-            }
-            f.number = n;
-            f.onCompletion(f);
-            if ((p = f.getCompleter()) != null)
-                p.tryComplete();
-            else
-                f.quietlyComplete();
-        }
-    }
-
-    static final class LFCCF extends FailingCCF {
-        public LFCCF(CountedCompleter parent, int n) {
-            super(parent, n);
-        }
-        public final void onCompletion(CountedCompleter caller) {
-            FailingCCF p = (FailingCCF)getCompleter();
-            int n = number + rnumber;
-            if (p != null)
-                p.number = n;
-            else
-                number = n;
-        }
-    }
-    static final class RFCCF extends FailingCCF {
-        public RFCCF(CountedCompleter parent, int n) {
-            super(parent, n);
-        }
-        public final void onCompletion(CountedCompleter caller) {
-            completeExceptionally(new FJException());
-        }
-    }
-
-    /**
-     * invoke returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks; getRawResult returns null.
-     */
-    public void testInvokeCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertNull(f.invoke());
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks
-     */
-    public void testQuietlyInvokeCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                f.quietlyInvoke();
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task returns when task completes
-     */
-    public void testForkJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertSame(f, f.fork());
-                assertNull(f.join());
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task returns when task completes
-     */
-    public void testForkGetCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                CCF f = new LCCF(null, 8);
-                assertSame(f, f.fork());
-                assertNull(f.get());
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task returns when task completes
-     */
-    public void testForkTimedGetCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                CCF f = new LCCF(null, 8);
-                assertSame(f, f.fork());
-                assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get with null time unit throws NPE
-     */
-    public void testForkTimedGetNPECC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                CCF f = new LCCF(null, 8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(5L, null);
-                    shouldThrow();
-                } catch (NullPointerException success) {}
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes
-     */
-    public void testForkQuietlyJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                assertEquals(21, f.number);
-                checkCompletedNormally(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task throws exception when task completes abnormally
-     */
-    public void testAbnormalInvokeCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF f = new LFCCF(null, 8);
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes abnormally
-     */
-    public void testAbnormalQuietlyInvokeCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF f = new LFCCF(null, 8);
-                f.quietlyInvoke();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF f = new LFCCF(null, 8);
-                assertSame(f, f.fork());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkGetCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingCCF f = new LFCCF(null, 8);
-                assertSame(f, f.fork());
-                try {
-                    f.get();
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkTimedGetCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingCCF f = new LFCCF(null, 8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(LONG_DELAY_MS, MILLISECONDS);
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes abnormally
-     */
-    public void testAbnormalForkQuietlyJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF f = new LFCCF(null, 8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invoke task throws exception when task cancelled
-     */
-    public void testCancelledInvokeCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertTrue(f.cancel(true));
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * join of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * get of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkGetCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                CCF f = new LCCF(null, 8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.get();
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * timed get of a forked task throws exception when task cancelled
-     */
-    public void testCancelledForkTimedGetCC() throws Exception {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                CCF f = new LCCF(null, 8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                try {
-                    f.get(LONG_DELAY_MS, MILLISECONDS);
-                    shouldThrow();
-                } catch (CancellationException success) {
-                    checkCancelled(f);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task cancelled
-     */
-    public void testCancelledForkQuietlyJoinCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                assertTrue(f.cancel(true));
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                checkCancelled(f);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * getPool of non-FJ task returns null
-     */
-    public void testGetPool2CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertNull(getPool());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * inForkJoinPool of non-FJ task returns false
-     */
-    public void testInForkJoinPool2CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertFalse(inForkJoinPool());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * setRawResult(null) succeeds
-     */
-    public void testSetRawResultCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                setRawResult(null);
-                assertNull(getRawResult());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * invoke task throws exception after invoking completeExceptionally
-     */
-    public void testCompleteExceptionally2CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                f.completeExceptionally(new FJException());
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(t1, t2) invokes all task arguments
-     */
-    public void testInvokeAll2CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                CCF g = new LCCF(null, 9);
-                invokeAll(f, g);
-                assertEquals(21, f.number);
-                assertEquals(34, g.number);
-                checkCompletedNormally(f);
-                checkCompletedNormally(g);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument invokes task
-     */
-    public void testInvokeAll1CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                invokeAll(f);
-                checkCompletedNormally(f);
-                assertEquals(21, f.number);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument invokes tasks
-     */
-    public void testInvokeAll3CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                CCF g = new LCCF(null, 9);
-                CCF h = new LCCF(null, 7);
-                invokeAll(f, g, h);
-                assertEquals(21, f.number);
-                assertEquals(34, g.number);
-                assertEquals(13, h.number);
-                checkCompletedNormally(f);
-                checkCompletedNormally(g);
-                checkCompletedNormally(h);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(collection) invokes all tasks in the collection
-     */
-    public void testInvokeAllCollectionCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                CCF g = new LCCF(null, 9);
-                CCF h = new LCCF(null, 7);
-                HashSet set = new HashSet();
-                set.add(f);
-                set.add(g);
-                set.add(h);
-                invokeAll(set);
-                assertEquals(21, f.number);
-                assertEquals(34, g.number);
-                assertEquals(13, h.number);
-                checkCompletedNormally(f);
-                checkCompletedNormally(g);
-                checkCompletedNormally(h);
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with any null task throws NPE
-     */
-    public void testInvokeAllNPECC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                CCF g = new LCCF(null, 9);
-                CCF h = null;
-                try {
-                    invokeAll(f, g, h);
-                    shouldThrow();
-                } catch (NullPointerException success) {}
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(t1, t2) throw exception if any task does
-     */
-    public void testAbnormalInvokeAll2CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                FailingCCF g = new LFCCF(null, 9);
-                try {
-                    invokeAll(f, g);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument throws exception if task does
-     */
-    public void testAbnormalInvokeAll1CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF g = new LFCCF(null, 9);
-                try {
-                    invokeAll(g);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument throws exception if any task does
-     */
-    public void testAbnormalInvokeAll3CC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                CCF f = new LCCF(null, 8);
-                FailingCCF g = new LFCCF(null, 9);
-                CCF h = new LCCF(null, 7);
-                try {
-                    invokeAll(f, g, h);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * invokeAll(collection) throws exception if any task does
-     */
-    public void testAbnormalInvokeAllCollectionCC() {
-        ForkJoinTask a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingCCF f = new LFCCF(null, 8);
-                CCF g = new LCCF(null, 9);
-                CCF h = new LCCF(null, 7);
-                HashSet set = new HashSet();
-                set.add(f);
-                set.add(g);
-                set.add(h);
-                try {
-                    invokeAll(set);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        checkInvoke(a);
-    }
-
-    /**
-     * awaitQuiescence by a worker is equivalent in effect to
-     * ForkJoinTask.helpQuiesce()
-     */
-    public void testAwaitQuiescence1() throws Exception {
-        final ForkJoinPool p = new ForkJoinPool();
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            assertTrue(p.isQuiescent());
-            ForkJoinTask a = new CheckedRecursiveAction() {
-                protected void realCompute() {
-                    FibAction f = new FibAction(8);
-                    assertSame(f, f.fork());
-                    assertSame(p, ForkJoinTask.getPool());
-                    boolean quiescent = p.awaitQuiescence(LONG_DELAY_MS, MILLISECONDS);
-                    assertTrue(quiescent);
-                    assertFalse(p.isQuiescent());
-                    while (!f.isDone()) {
-                        assertFalse(p.getAsyncMode());
-                        assertFalse(p.isShutdown());
-                        assertFalse(p.isTerminating());
-                        assertFalse(p.isTerminated());
-                        Thread.yield();
-                    }
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-                    assertFalse(p.isQuiescent());
-                    assertEquals(0, ForkJoinTask.getQueuedTaskCount());
-                    assertEquals(21, f.result);
-                }};
-            p.execute(a);
-            while (!a.isDone() || !p.isQuiescent()) {
-                assertFalse(p.getAsyncMode());
-                assertFalse(p.isShutdown());
-                assertFalse(p.isTerminating());
-                assertFalse(p.isTerminated());
-                Thread.yield();
-            }
-            assertEquals(0, p.getQueuedTaskCount());
-            assertFalse(p.getAsyncMode());
-            assertEquals(0, p.getQueuedSubmissionCount());
-            assertFalse(p.hasQueuedSubmissions());
-            while (p.getActiveThreadCount() != 0
-                   && millisElapsedSince(startTime) < LONG_DELAY_MS)
-                Thread.yield();
-            assertFalse(p.isShutdown());
-            assertFalse(p.isTerminating());
-            assertFalse(p.isTerminated());
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-        }
-    }
-
-    /**
-     * awaitQuiescence returns when pool isQuiescent() or the indicated
-     * timeout elapsed
-     */
-    public void testAwaitQuiescence2() throws Exception {
-        /**
-         * """It is possible to disable or limit the use of threads in the
-         * common pool by setting the parallelism property to zero. However
-         * doing so may cause unjoined tasks to never be executed."""
-         */
-        if ("0".equals(System.getProperty(
-             "java.util.concurrent.ForkJoinPool.common.parallelism")))
-            return;
-        final ForkJoinPool p = new ForkJoinPool();
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertTrue(p.isQuiescent());
-            final long startTime = System.nanoTime();
-            ForkJoinTask a = new CheckedRecursiveAction() {
-                protected void realCompute() {
-                    FibAction f = new FibAction(8);
-                    assertSame(f, f.fork());
-                    while (!f.isDone()
-                           && millisElapsedSince(startTime) < LONG_DELAY_MS) {
-                        assertFalse(p.getAsyncMode());
-                        assertFalse(p.isShutdown());
-                        assertFalse(p.isTerminating());
-                        assertFalse(p.isTerminated());
-                        Thread.yield();
-                    }
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-                    assertEquals(0, ForkJoinTask.getQueuedTaskCount());
-                    assertEquals(21, f.result);
-                }};
-            p.execute(a);
-            assertTrue(p.awaitQuiescence(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isQuiescent());
-            assertTrue(a.isDone());
-            assertEquals(0, p.getQueuedTaskCount());
-            assertFalse(p.getAsyncMode());
-            assertEquals(0, p.getQueuedSubmissionCount());
-            assertFalse(p.hasQueuedSubmissions());
-            while (p.getActiveThreadCount() != 0
-                   && millisElapsedSince(startTime) < LONG_DELAY_MS)
-                Thread.yield();
-            assertFalse(p.isShutdown());
-            assertFalse(p.isTerminating());
-            assertFalse(p.isTerminated());
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/ForkJoinPoolTest.java b/jsr166-tests/src/test/java/jsr166/ForkJoinPoolTest.java
index e3bb428..09a3511 100644
--- a/jsr166-tests/src/test/java/jsr166/ForkJoinPoolTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ForkJoinPoolTest.java
@@ -40,7 +40,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ForkJoinPoolTest.class);
+    //     return new TestSuite(...);
     // }
 
     /*
@@ -68,12 +68,10 @@
         }
     }
 
-    static class MyError extends Error {}
-
     // to test handlers
     static class FailingFJWSubclass extends ForkJoinWorkerThread {
         public FailingFJWSubclass(ForkJoinPool p) { super(p) ; }
-        protected void onStart() { super.onStart(); throw new MyError(); }
+        protected void onStart() { super.onStart(); throw new Error(); }
     }
 
     static class FailingThreadFactory
@@ -168,7 +166,7 @@
      */
     public void testDefaultInitialState() {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             assertSame(ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                        p.getFactory());
             assertFalse(p.getAsyncMode());
@@ -180,6 +178,8 @@
             assertFalse(p.isShutdown());
             assertFalse(p.isTerminating());
             assertFalse(p.isTerminated());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -208,8 +208,10 @@
      */
     public void testGetParallelism() {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             assertEquals(1, p.getParallelism());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -217,26 +219,14 @@
      * getPoolSize returns number of started workers.
      */
     public void testGetPoolSize() {
-        final CountDownLatch taskStarted = new CountDownLatch(1);
-        final CountDownLatch done = new CountDownLatch(1);
-        final ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        ForkJoinPool p = new ForkJoinPool(1);
+        try {
             assertEquals(0, p.getActiveThreadCount());
-            final Runnable task = new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    taskStarted.countDown();
-                    assertEquals(1, p.getPoolSize());
-                    assertEquals(1, p.getActiveThreadCount());
-                    done.await();
-                }};
-            Future<?> future = p.submit(task);
-            await(taskStarted);
+            Future<String> future = p.submit(new StringTask());
             assertEquals(1, p.getPoolSize());
-            assertEquals(1, p.getActiveThreadCount());
-            done.countDown();
+        } finally {
+            joinPool(p);
         }
-        assertEquals(0, p.getPoolSize());
-        assertEquals(0, p.getActiveThreadCount());
     }
 
     /**
@@ -244,28 +234,26 @@
      */
     public void testAwaitTermination_timesOut() throws InterruptedException {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.isTerminated());
-            assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS));
-            assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
-            assertFalse(p.awaitTermination(-1L, NANOSECONDS));
-            assertFalse(p.awaitTermination(-1L, MILLISECONDS));
-            assertFalse(p.awaitTermination(0L, NANOSECONDS));
-            assertFalse(p.awaitTermination(0L, MILLISECONDS));
-            long timeoutNanos = 999999L;
-            long startTime = System.nanoTime();
-            assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
-            assertTrue(System.nanoTime() - startTime >= timeoutNanos);
-            assertFalse(p.isTerminated());
-            startTime = System.nanoTime();
-            long timeoutMillis = timeoutMillis();
-            assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS));
-            assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            assertFalse(p.isTerminated());
-            p.shutdown();
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-        }
+        assertFalse(p.isTerminated());
+        assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS));
+        assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
+        assertFalse(p.awaitTermination(-1L, NANOSECONDS));
+        assertFalse(p.awaitTermination(-1L, MILLISECONDS));
+        assertFalse(p.awaitTermination(0L, NANOSECONDS));
+        assertFalse(p.awaitTermination(0L, MILLISECONDS));
+        long timeoutNanos = 999999L;
+        long startTime = System.nanoTime();
+        assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
+        assertTrue(System.nanoTime() - startTime >= timeoutNanos);
+        assertFalse(p.isTerminated());
+        startTime = System.nanoTime();
+        long timeoutMillis = timeoutMillis();
+        assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS));
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+        assertFalse(p.isTerminated());
+        p.shutdown();
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
     }
 
     /**
@@ -276,23 +264,23 @@
      */
     public void testSetUncaughtExceptionHandler() throws InterruptedException {
         final CountDownLatch uehInvoked = new CountDownLatch(1);
-        final Thread.UncaughtExceptionHandler ueh =
+        final Thread.UncaughtExceptionHandler eh =
             new Thread.UncaughtExceptionHandler() {
                 public void uncaughtException(Thread t, Throwable e) {
-                    threadAssertTrue(e instanceof MyError);
-                    threadAssertTrue(t instanceof FailingFJWSubclass);
                     uehInvoked.countDown();
                 }};
         ForkJoinPool p = new ForkJoinPool(1, new FailingThreadFactory(),
-                                          ueh, false);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(ueh, p.getUncaughtExceptionHandler());
+                                          eh, false);
+        try {
+            assertSame(eh, p.getUncaughtExceptionHandler());
             try {
                 p.execute(new FibTask(8));
-                await(uehInvoked);
-            } finally {
-                p.shutdownNow(); // failure might have prevented processing task
+                assertTrue(uehInvoked.await(MEDIUM_DELAY_MS, MILLISECONDS));
+            } catch (RejectedExecutionException ok) {
             }
+        } finally {
+            p.shutdownNow(); // failure might have prevented processing task
+            joinPool(p);
         }
     }
 
@@ -304,7 +292,7 @@
      */
     public void testIsQuiescent() throws Exception {
         ForkJoinPool p = new ForkJoinPool(2);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             assertTrue(p.isQuiescent());
             long startTime = System.nanoTime();
             FibTask f = new FibTask(20);
@@ -323,18 +311,17 @@
 
             assertTrue(p.isQuiescent());
             assertFalse(p.getAsyncMode());
+            assertEquals(0, p.getActiveThreadCount());
             assertEquals(0, p.getQueuedTaskCount());
             assertEquals(0, p.getQueuedSubmissionCount());
             assertFalse(p.hasQueuedSubmissions());
-            while (p.getActiveThreadCount() != 0
-                   && millisElapsedSince(startTime) < LONG_DELAY_MS)
-                Thread.yield();
             assertFalse(p.isShutdown());
             assertFalse(p.isTerminating());
             assertFalse(p.isTerminated());
             assertTrue(f.isDone());
             assertEquals(6765, (int) f.get());
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -343,9 +330,11 @@
      */
     public void testSubmitForkJoinTask() throws Throwable {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             ForkJoinTask<Integer> f = p.submit(new FibTask(8));
             assertEquals(21, (int) f.get());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -354,13 +343,15 @@
      */
     public void testSubmitAfterShutdown() {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             p.shutdown();
             assertTrue(p.isShutdown());
             try {
                 ForkJoinTask<Integer> f = p.submit(new FibTask(8));
                 shouldThrow();
             } catch (RejectedExecutionException success) {}
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -386,14 +377,16 @@
     public void testPollSubmission() {
         final CountDownLatch done = new CountDownLatch(1);
         SubFJP p = new SubFJP();
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             ForkJoinTask a = p.submit(awaiter(done));
             ForkJoinTask b = p.submit(awaiter(done));
             ForkJoinTask c = p.submit(awaiter(done));
             ForkJoinTask r = p.pollSubmission();
             assertTrue(r == a || r == b || r == c);
             assertFalse(r.isDone());
+        } finally {
             done.countDown();
+            joinPool(p);
         }
     }
 
@@ -403,7 +396,7 @@
     public void testDrainTasksTo() {
         final CountDownLatch done = new CountDownLatch(1);
         SubFJP p = new SubFJP();
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             ForkJoinTask a = p.submit(awaiter(done));
             ForkJoinTask b = p.submit(awaiter(done));
             ForkJoinTask c = p.submit(awaiter(done));
@@ -414,7 +407,9 @@
                 assertTrue(r == a || r == b || r == c);
                 assertFalse(r.isDone());
             }
+        } finally {
             done.countDown();
+            joinPool(p);
         }
     }
 
@@ -425,7 +420,7 @@
      */
     public void testExecuteRunnable() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             final AtomicBoolean done = new AtomicBoolean(false);
             Future<?> future = e.submit(new CheckedRunnable() {
                 public void realRun() {
@@ -436,6 +431,8 @@
             assertTrue(done.get());
             assertTrue(future.isDone());
             assertFalse(future.isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -444,11 +441,13 @@
      */
     public void testSubmitCallable() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<String> future = e.submit(new StringTask());
             assertSame(TEST_STRING, future.get());
             assertTrue(future.isDone());
             assertFalse(future.isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -457,11 +456,13 @@
      */
     public void testSubmitRunnable() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<?> future = e.submit(new NoOpRunnable());
             assertNull(future.get());
             assertTrue(future.isDone());
             assertFalse(future.isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -470,11 +471,13 @@
      */
     public void testSubmitRunnable2() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
             assertSame(TEST_STRING, future.get());
             assertTrue(future.isDone());
             assertFalse(future.isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -487,9 +490,11 @@
         Runnable r = new CheckedRunnable() {
         public void realRun() throws Exception {
             ExecutorService e = new ForkJoinPool(1);
-            try (PoolCleaner cleaner = cleaner(e)) {
+            try {
                 Future future = e.submit(callable);
                 assertSame(TEST_STRING, future.get());
+            } finally {
+                joinPool(e);
             }
         }};
 
@@ -506,9 +511,11 @@
         Runnable r = new CheckedRunnable() {
         public void realRun() throws Exception {
             ExecutorService e = new ForkJoinPool(1);
-            try (PoolCleaner cleaner = cleaner(e)) {
+            try {
                 Future future = e.submit(callable);
                 assertSame(TEST_STRING, future.get());
+            } finally {
+                joinPool(e);
             }
         }};
 
@@ -525,7 +532,7 @@
         Runnable r = new CheckedRunnable() {
         public void realRun() throws Exception {
             ExecutorService e = new ForkJoinPool(1);
-            try (PoolCleaner cleaner = cleaner(e)) {
+            try {
                 Future future = e.submit(callable);
                 try {
                     future.get();
@@ -533,6 +540,8 @@
                 } catch (ExecutionException success) {
                     assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
                 }
+            } finally {
+                joinPool(e);
             }
         }};
 
@@ -544,11 +553,12 @@
      */
     public void testExecuteNullRunnable() {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                Future<?> future = e.submit((Runnable) null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            Future<?> future = e.submit((Runnable) null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -557,11 +567,12 @@
      */
     public void testSubmitNullCallable() {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                Future<String> future = e.submit((Callable) null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            Future<String> future = e.submit((Callable) null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -571,13 +582,13 @@
     public void testInterruptedSubmit() throws InterruptedException {
         final CountDownLatch submitted    = new CountDownLatch(1);
         final CountDownLatch quittingTime = new CountDownLatch(1);
+        final ExecutorService p = new ForkJoinPool(1);
         final Callable<Void> awaiter = new CheckedCallable<Void>() {
             public Void realCall() throws InterruptedException {
-                assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS));
+                assertTrue(quittingTime.await(MEDIUM_DELAY_MS, MILLISECONDS));
                 return null;
             }};
-        final ExecutorService p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p, quittingTime)) {
+        try {
             Thread t = new Thread(new CheckedInterruptedRunnable() {
                 public void realRun() throws Exception {
                     Future<Void> future = p.submit(awaiter);
@@ -585,9 +596,12 @@
                     future.get();
                 }});
             t.start();
-            await(submitted);
+            assertTrue(submitted.await(MEDIUM_DELAY_MS, MILLISECONDS));
             t.interrupt();
-            awaitTermination(t);
+            t.join();
+        } finally {
+            quittingTime.countDown();
+            joinPool(p);
         }
     }
 
@@ -597,15 +611,15 @@
      */
     public void testSubmitEE() throws Throwable {
         ForkJoinPool p = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.submit(new Callable() {
-                        public Object call() { throw new ArithmeticException(); }})
-                    .get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof ArithmeticException);
-            }
+        try {
+            p.submit(new Callable() {
+                public Object call() { throw new ArithmeticException(); }})
+                .get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof ArithmeticException);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -614,11 +628,12 @@
      */
     public void testInvokeAny1() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -627,11 +642,12 @@
      */
     public void testInvokeAny2() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -640,13 +656,14 @@
      */
     public void testInvokeAny3() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -656,15 +673,16 @@
     public void testInvokeAny4() throws Throwable {
         CountDownLatch latch = new CountDownLatch(1);
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -673,15 +691,15 @@
      */
     public void testInvokeAny5() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -690,12 +708,14 @@
      */
     public void testInvokeAny6() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -704,11 +724,12 @@
      */
     public void testInvokeAll1() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -717,10 +738,12 @@
      */
     public void testInvokeAll2() throws InterruptedException {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Future<String>> r
                 = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -729,14 +752,15 @@
      */
     public void testInvokeAll3() throws InterruptedException {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -746,17 +770,17 @@
      */
     public void testInvokeAll4() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures = e.invokeAll(l);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures = e.invokeAll(l);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -765,7 +789,7 @@
      */
     public void testInvokeAll5() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -773,6 +797,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -781,11 +807,12 @@
      */
     public void testTimedInvokeAny1() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -794,13 +821,14 @@
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -809,12 +837,13 @@
      */
     public void testTimedInvokeAny2() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(),
-                            MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -824,15 +853,16 @@
     public void testTimedInvokeAny3() throws Throwable {
         CountDownLatch latch = new CountDownLatch(1);
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -841,17 +871,15 @@
      */
     public void testTimedInvokeAny4() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -860,14 +888,14 @@
      */
     public void testTimedInvokeAny5() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -876,11 +904,12 @@
      */
     public void testTimedInvokeAll1() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -889,13 +918,14 @@
      */
     public void testTimedInvokeAllNullTimeUnit() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -904,11 +934,13 @@
      */
     public void testTimedInvokeAll2() throws InterruptedException {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Future<String>> r
                 = e.invokeAll(new ArrayList<Callable<String>>(),
                               MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -917,14 +949,15 @@
      */
     public void testTimedInvokeAll3() throws InterruptedException {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -933,18 +966,18 @@
      */
     public void testTimedInvokeAll4() throws Throwable {
         ExecutorService e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures
-                = e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures
+            = e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -952,16 +985,18 @@
      * timed invokeAll(c) returns results of all completed tasks in c
      */
     public void testTimedInvokeAll5() throws Throwable {
-        ForkJoinPool e = new ForkJoinPool(1);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ForkJoinPool(1);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures
-                = e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                = e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ForkJoinTask8Test.java b/jsr166-tests/src/test/java/jsr166/ForkJoinTask8Test.java
deleted file mode 100644
index 6c03348..0000000
--- a/jsr166-tests/src/test/java/jsr166/ForkJoinTask8Test.java
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
- * 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 jsr166;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.ForkJoinWorkerThread;
-import java.util.concurrent.RecursiveAction;
-import java.util.concurrent.TimeoutException;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class ForkJoinTask8Test extends JSR166TestCase {
-
-    /*
-     * Testing notes: This differs from ForkJoinTaskTest mainly by
-     * defining a version of BinaryAsyncAction that uses JDK8 task
-     * tags for control state, thereby testing getForkJoinTaskTag,
-     * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across
-     * various contexts. Most of the test methods using it are
-     * otherwise identical, but omitting retest of those dealing with
-     * cancellation, which is not represented in this tag scheme.
-     */
-
-    static final short INITIAL_STATE = -1;
-    static final short COMPLETE_STATE = 0;
-    static final short EXCEPTION_STATE = 1;
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(ForkJoinTask8Test.class);
-    // }
-
-    // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
-    static final int mainPoolSize =
-        Math.max(2, Runtime.getRuntime().availableProcessors());
-
-    private static ForkJoinPool mainPool() {
-        return new ForkJoinPool(mainPoolSize);
-    }
-
-    private static ForkJoinPool singletonPool() {
-        return new ForkJoinPool(1);
-    }
-
-    private static ForkJoinPool asyncSingletonPool() {
-        return new ForkJoinPool(1,
-                                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
-                                null, true);
-    }
-
-    // Compute fib naively and efficiently
-    final int[] fib;
-    {
-        int[] fib = new int[10];
-        fib[0] = 0;
-        fib[1] = 1;
-        for (int i = 2; i < fib.length; i++)
-            fib[i] = fib[i - 1] + fib[i - 2];
-        this.fib = fib;
-    }
-
-    private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
-        try (PoolCleaner cleaner = cleaner(pool)) {
-            assertFalse(a.isDone());
-            assertFalse(a.isCompletedNormally());
-            assertFalse(a.isCompletedAbnormally());
-            assertFalse(a.isCancelled());
-            assertNull(a.getException());
-            assertNull(a.getRawResult());
-
-            assertNull(pool.invoke(a));
-
-            assertTrue(a.isDone());
-            assertTrue(a.isCompletedNormally());
-            assertFalse(a.isCompletedAbnormally());
-            assertFalse(a.isCancelled());
-            assertNull(a.getException());
-            assertNull(a.getRawResult());
-        }
-    }
-
-    void checkNotDone(ForkJoinTask a) {
-        assertFalse(a.isDone());
-        assertFalse(a.isCompletedNormally());
-        assertFalse(a.isCompletedAbnormally());
-        assertFalse(a.isCancelled());
-        assertNull(a.getException());
-        assertNull(a.getRawResult());
-        if (a instanceof BinaryAsyncAction)
-            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == INITIAL_STATE);
-
-        try {
-            a.get(0L, SECONDS);
-            shouldThrow();
-        } catch (TimeoutException success) {
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    <T> void checkCompletedNormally(ForkJoinTask<T> a) {
-        checkCompletedNormally(a, null);
-    }
-
-    <T> void checkCompletedNormally(ForkJoinTask<T> a, T expected) {
-        assertTrue(a.isDone());
-        assertFalse(a.isCancelled());
-        assertTrue(a.isCompletedNormally());
-        assertFalse(a.isCompletedAbnormally());
-        assertNull(a.getException());
-        assertSame(expected, a.getRawResult());
-        if (a instanceof BinaryAsyncAction)
-            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == COMPLETE_STATE);
-
-        {
-            Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
-            assertSame(expected, a.join());
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
-            Thread.interrupted();
-        }
-
-        {
-            Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
-            a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
-            Thread.interrupted();
-        }
-
-        assertFalse(a.cancel(false));
-        assertFalse(a.cancel(true));
-        try {
-            assertSame(expected, a.get());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-        try {
-            assertSame(expected, a.get(5L, SECONDS));
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
-        assertTrue(a.isDone());
-        assertFalse(a.isCancelled());
-        assertFalse(a.isCompletedNormally());
-        assertTrue(a.isCompletedAbnormally());
-        assertSame(t.getClass(), a.getException().getClass());
-        assertNull(a.getRawResult());
-        assertFalse(a.cancel(false));
-        assertFalse(a.cancel(true));
-        if (a instanceof BinaryAsyncAction)
-            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE);
-
-        try {
-            Thread.currentThread().interrupt();
-            a.join();
-            shouldThrow();
-        } catch (Throwable expected) {
-            assertSame(t.getClass(), expected.getClass());
-        }
-        Thread.interrupted();
-
-        {
-            long startTime = System.nanoTime();
-            a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
-        }
-
-        try {
-            a.get();
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(t.getClass(), success.getCause().getClass());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-
-        try {
-            a.get(5L, SECONDS);
-            shouldThrow();
-        } catch (ExecutionException success) {
-            assertSame(t.getClass(), success.getCause().getClass());
-        } catch (Throwable fail) { threadUnexpectedException(fail); }
-    }
-
-    public static final class FJException extends RuntimeException {
-        FJException() { super(); }
-    }
-
-    abstract static class BinaryAsyncAction extends ForkJoinTask<Void> {
-
-        private volatile BinaryAsyncAction parent;
-
-        private volatile BinaryAsyncAction sibling;
-
-        protected BinaryAsyncAction() {
-            setForkJoinTaskTag(INITIAL_STATE);
-        }
-
-        public final Void getRawResult() { return null; }
-        protected final void setRawResult(Void mustBeNull) { }
-
-        public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
-            x.parent = y.parent = this;
-            x.sibling = y;
-            y.sibling = x;
-        }
-
-        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
-            if (this.getForkJoinTaskTag() != COMPLETE_STATE ||
-                x.getForkJoinTaskTag() != COMPLETE_STATE ||
-                y.getForkJoinTaskTag() != COMPLETE_STATE) {
-                completeThisExceptionally(new FJException());
-            }
-        }
-
-        protected boolean onException() {
-            return true;
-        }
-
-        public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
-            linkSubtasks(x, y);
-            y.fork();
-            x.fork();
-        }
-
-        private void completeThis() {
-            setForkJoinTaskTag(COMPLETE_STATE);
-            super.complete(null);
-        }
-
-        private void completeThisExceptionally(Throwable ex) {
-            setForkJoinTaskTag(EXCEPTION_STATE);
-            super.completeExceptionally(ex);
-        }
-
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            if (super.cancel(mayInterruptIfRunning)) {
-                completeExceptionally(new FJException());
-                return true;
-            }
-            return false;
-        }
-
-        public final void complete() {
-            BinaryAsyncAction a = this;
-            for (;;) {
-                BinaryAsyncAction s = a.sibling;
-                BinaryAsyncAction p = a.parent;
-                a.sibling = null;
-                a.parent = null;
-                a.completeThis();
-                if (p == null ||
-                    p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE))
-                    break;
-                try {
-                    p.onComplete(a, s);
-                } catch (Throwable rex) {
-                    p.completeExceptionally(rex);
-                    return;
-                }
-                a = p;
-            }
-        }
-
-        public final void completeExceptionally(Throwable ex) {
-            for (BinaryAsyncAction a = this;;) {
-                a.completeThisExceptionally(ex);
-                BinaryAsyncAction s = a.sibling;
-                if (s != null && !s.isDone())
-                    s.completeExceptionally(ex);
-                if ((a = a.parent) == null)
-                    break;
-            }
-        }
-
-        public final BinaryAsyncAction getParent() {
-            return parent;
-        }
-
-        public BinaryAsyncAction getSibling() {
-            return sibling;
-        }
-
-        public void reinitialize() {
-            parent = sibling = null;
-            super.reinitialize();
-        }
-
-    }
-
-    final class AsyncFib extends BinaryAsyncAction {
-        int number;
-        int expectedResult;
-        public AsyncFib(int number) {
-            this.number = number;
-            this.expectedResult = fib[number];
-        }
-
-        public final boolean exec() {
-            try {
-                AsyncFib f = this;
-                int n = f.number;
-                while (n > 1) {
-                    AsyncFib p = f;
-                    AsyncFib r = new AsyncFib(n - 2);
-                    f = new AsyncFib(--n);
-                    p.linkSubtasks(r, f);
-                    r.fork();
-                }
-                f.complete();
-            }
-            catch (Throwable ex) {
-                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
-            }
-            if (getForkJoinTaskTag() == EXCEPTION_STATE)
-                throw new FJException();
-            return false;
-        }
-
-        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
-            number = ((AsyncFib)x).number + ((AsyncFib)y).number;
-            super.onComplete(x, y);
-        }
-
-        public void checkCompletedNormally() {
-            assertEquals(expectedResult, number);
-            ForkJoinTask8Test.this.checkCompletedNormally(this);
-        }
-    }
-
-    static final class FailingAsyncFib extends BinaryAsyncAction {
-        int number;
-        public FailingAsyncFib(int n) {
-            this.number = n;
-        }
-
-        public final boolean exec() {
-            try {
-                FailingAsyncFib f = this;
-                int n = f.number;
-                while (n > 1) {
-                    FailingAsyncFib p = f;
-                    FailingAsyncFib r = new FailingAsyncFib(n - 2);
-                    f = new FailingAsyncFib(--n);
-                    p.linkSubtasks(r, f);
-                    r.fork();
-                }
-                f.complete();
-            }
-            catch (Throwable ex) {
-                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
-            }
-            if (getForkJoinTaskTag() == EXCEPTION_STATE)
-                throw new FJException();
-            return false;
-        }
-
-        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
-            completeExceptionally(new FJException());
-        }
-    }
-
-    /**
-     * invoke returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks; getRawResult returns null.
-     */
-    public void testInvoke() {
-        testInvoke(mainPool());
-    }
-    public void testInvoke_Singleton() {
-        testInvoke(singletonPool());
-    }
-    public void testInvoke(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                assertNull(f.invoke());
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes normally.
-     * isCompletedAbnormally and isCancelled return false for normally
-     * completed tasks
-     */
-    public void testQuietlyInvoke() {
-        testQuietlyInvoke(mainPool());
-    }
-    public void testQuietlyInvoke_Singleton() {
-        testQuietlyInvoke(singletonPool());
-    }
-    public void testQuietlyInvoke(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                f.quietlyInvoke();
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * join of a forked task returns when task completes
-     */
-    public void testForkJoin() {
-        testForkJoin(mainPool());
-    }
-    public void testForkJoin_Singleton() {
-        testForkJoin(singletonPool());
-    }
-    public void testForkJoin(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertNull(f.join());
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * get of a forked task returns when task completes
-     */
-    public void testForkGet() {
-        testForkGet(mainPool());
-    }
-    public void testForkGet_Singleton() {
-        testForkGet(singletonPool());
-    }
-    public void testForkGet(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertNull(f.get());
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * timed get of a forked task returns when task completes
-     */
-    public void testForkTimedGet() {
-        testForkTimedGet(mainPool());
-    }
-    public void testForkTimedGet_Singleton() {
-        testForkTimedGet(singletonPool());
-    }
-    public void testForkTimedGet(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * timed get with null time unit throws NullPointerException
-     */
-    public void testForkTimedGetNullTimeUnit() {
-        testForkTimedGetNullTimeUnit(mainPool());
-    }
-    public void testForkTimedGetNullTimeUnit_Singleton() {
-        testForkTimedGet(singletonPool());
-    }
-    public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(5L, null);
-                    shouldThrow();
-                } catch (NullPointerException success) {}
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes
-     */
-    public void testForkQuietlyJoin() {
-        testForkQuietlyJoin(mainPool());
-    }
-    public void testForkQuietlyJoin_Singleton() {
-        testForkQuietlyJoin(singletonPool());
-    }
-    public void testForkQuietlyJoin(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * helpQuiesce returns when tasks are complete.
-     * getQueuedTaskCount returns 0 when quiescent
-     */
-    public void testForkHelpQuiesce() {
-        testForkHelpQuiesce(mainPool());
-    }
-    public void testForkHelpQuiesce_Singleton() {
-        testForkHelpQuiesce(singletonPool());
-    }
-    public void testForkHelpQuiesce(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                helpQuiesce();
-                assertEquals(0, getQueuedTaskCount());
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invoke task throws exception when task completes abnormally
-     */
-    public void testAbnormalInvoke() {
-        testAbnormalInvoke(mainPool());
-    }
-    public void testAbnormalInvoke_Singleton() {
-        testAbnormalInvoke(singletonPool());
-    }
-    public void testAbnormalInvoke(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * quietlyInvoke task returns when task completes abnormally
-     */
-    public void testAbnormalQuietlyInvoke() {
-        testAbnormalQuietlyInvoke(mainPool());
-    }
-    public void testAbnormalQuietlyInvoke_Singleton() {
-        testAbnormalQuietlyInvoke(singletonPool());
-    }
-    public void testAbnormalQuietlyInvoke(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                f.quietlyInvoke();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * join of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkJoin() {
-        testAbnormalForkJoin(mainPool());
-    }
-    public void testAbnormalForkJoin_Singleton() {
-        testAbnormalForkJoin(singletonPool());
-    }
-    public void testAbnormalForkJoin(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                assertSame(f, f.fork());
-                try {
-                    f.join();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkGet() {
-        testAbnormalForkGet(mainPool());
-    }
-    public void testAbnormalForkGet_Singleton() {
-        testAbnormalForkJoin(singletonPool());
-    }
-    public void testAbnormalForkGet(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get();
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * timed get of a forked task throws exception when task completes abnormally
-     */
-    public void testAbnormalForkTimedGet() {
-        testAbnormalForkTimedGet(mainPool());
-    }
-    public void testAbnormalForkTimedGet_Singleton() {
-        testAbnormalForkTimedGet(singletonPool());
-    }
-    public void testAbnormalForkTimedGet(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() throws Exception {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                assertSame(f, f.fork());
-                try {
-                    f.get(LONG_DELAY_MS, MILLISECONDS);
-                    shouldThrow();
-                } catch (ExecutionException success) {
-                    Throwable cause = success.getCause();
-                    assertTrue(cause instanceof FJException);
-                    checkCompletedAbnormally(f, cause);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * quietlyJoin of a forked task returns when task completes abnormally
-     */
-    public void testAbnormalForkQuietlyJoin() {
-        testAbnormalForkQuietlyJoin(mainPool());
-    }
-    public void testAbnormalForkQuietlyJoin_Singleton() {
-        testAbnormalForkQuietlyJoin(singletonPool());
-    }
-    public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                assertSame(f, f.fork());
-                f.quietlyJoin();
-                assertTrue(f.getException() instanceof FJException);
-                checkCompletedAbnormally(f, f.getException());
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * getPool of executing task returns its pool
-     */
-    public void testGetPool() {
-        testGetPool(mainPool());
-    }
-    public void testGetPool_Singleton() {
-        testGetPool(singletonPool());
-    }
-    public void testGetPool(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertSame(pool, getPool());
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * getPool of non-FJ task returns null
-     */
-    public void testGetPool2() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertNull(getPool());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * inForkJoinPool of executing task returns true
-     */
-    public void testInForkJoinPool() {
-        testInForkJoinPool(mainPool());
-    }
-    public void testInForkJoinPool_Singleton() {
-        testInForkJoinPool(singletonPool());
-    }
-    public void testInForkJoinPool(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertTrue(inForkJoinPool());
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * inForkJoinPool of non-FJ task returns false
-     */
-    public void testInForkJoinPool2() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                assertFalse(inForkJoinPool());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * setRawResult(null) succeeds
-     */
-    public void testSetRawResult() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                setRawResult(null);
-                assertNull(getRawResult());
-            }};
-        assertNull(a.invoke());
-    }
-
-    /**
-     * invoke task throws exception after invoking completeExceptionally
-     */
-    public void testCompleteExceptionally() {
-        testCompleteExceptionally(mainPool());
-    }
-    public void testCompleteExceptionally_Singleton() {
-        testCompleteExceptionally(singletonPool());
-    }
-    public void testCompleteExceptionally(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                f.completeExceptionally(new FJException());
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument invokes task
-     */
-    public void testInvokeAll1() {
-        testInvokeAll1(mainPool());
-    }
-    public void testInvokeAll1_Singleton() {
-        testInvokeAll1(singletonPool());
-    }
-    public void testInvokeAll1(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                invokeAll(f);
-                f.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(t1, t2) invokes all task arguments
-     */
-    public void testInvokeAll2() {
-        testInvokeAll2(mainPool());
-    }
-    public void testInvokeAll2_Singleton() {
-        testInvokeAll2(singletonPool());
-    }
-    public void testInvokeAll2(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib[] tasks = {
-                    new AsyncFib(8),
-                    new AsyncFib(9),
-                };
-                invokeAll(tasks[0], tasks[1]);
-                for (AsyncFib task : tasks) assertTrue(task.isDone());
-                for (AsyncFib task : tasks) task.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument invokes tasks
-     */
-    public void testInvokeAll3() {
-        testInvokeAll3(mainPool());
-    }
-    public void testInvokeAll3_Singleton() {
-        testInvokeAll3(singletonPool());
-    }
-    public void testInvokeAll3(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib[] tasks = {
-                    new AsyncFib(8),
-                    new AsyncFib(9),
-                    new AsyncFib(7),
-                };
-                invokeAll(tasks[0], tasks[1], tasks[2]);
-                for (AsyncFib task : tasks) assertTrue(task.isDone());
-                for (AsyncFib task : tasks) task.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(collection) invokes all tasks in the collection
-     */
-    public void testInvokeAllCollection() {
-        testInvokeAllCollection(mainPool());
-    }
-    public void testInvokeAllCollection_Singleton() {
-        testInvokeAllCollection(singletonPool());
-    }
-    public void testInvokeAllCollection(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib[] tasks = {
-                    new AsyncFib(8),
-                    new AsyncFib(9),
-                    new AsyncFib(7),
-                };
-                invokeAll(Arrays.asList(tasks));
-                for (AsyncFib task : tasks) assertTrue(task.isDone());
-                for (AsyncFib task : tasks) task.checkCompletedNormally();
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(tasks) with any null task throws NullPointerException
-     */
-    public void testInvokeAllNullTask() {
-        testInvokeAllNullTask(mainPool());
-    }
-    public void testInvokeAllNullTask_Singleton() {
-        testInvokeAllNullTask(singletonPool());
-    }
-    public void testInvokeAllNullTask(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib nul = null;
-                Runnable[] throwingActions = {
-                    () -> invokeAll(nul),
-                    () -> invokeAll(nul, nul),
-                    () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
-                    () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
-                    () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)),
-                };
-                assertThrows(NullPointerException.class, throwingActions);
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(tasks) with 1 argument throws exception if task does
-     */
-    public void testAbnormalInvokeAll1() {
-        testAbnormalInvokeAll1(mainPool());
-    }
-    public void testAbnormalInvokeAll1_Singleton() {
-        testAbnormalInvokeAll1(singletonPool());
-    }
-    public void testAbnormalInvokeAll1(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib g = new FailingAsyncFib(9);
-                try {
-                    invokeAll(g);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(t1, t2) throw exception if any task does
-     */
-    public void testAbnormalInvokeAll2() {
-        testAbnormalInvokeAll2(mainPool());
-    }
-    public void testAbnormalInvokeAll2_Singleton() {
-        testAbnormalInvokeAll2(singletonPool());
-    }
-    public void testAbnormalInvokeAll2(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                FailingAsyncFib g = new FailingAsyncFib(9);
-                ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
-                try {
-                    invokeAll(tasks[0], tasks[1]);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(tasks) with > 2 argument throws exception if any task does
-     */
-    public void testAbnormalInvokeAll3() {
-        testAbnormalInvokeAll3(mainPool());
-    }
-    public void testAbnormalInvokeAll3_Singleton() {
-        testAbnormalInvokeAll3(singletonPool());
-    }
-    public void testAbnormalInvokeAll3(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                FailingAsyncFib g = new FailingAsyncFib(9);
-                AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
-                try {
-                    invokeAll(tasks[0], tasks[1], tasks[2]);
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(g, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * invokeAll(collection) throws exception if any task does
-     */
-    public void testAbnormalInvokeAllCollection() {
-        testAbnormalInvokeAllCollection(mainPool());
-    }
-    public void testAbnormalInvokeAllCollection_Singleton() {
-        testAbnormalInvokeAllCollection(singletonPool());
-    }
-    public void testAbnormalInvokeAllCollection(ForkJoinPool pool) {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                FailingAsyncFib f = new FailingAsyncFib(8);
-                AsyncFib g = new AsyncFib(9);
-                AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
-                try {
-                    invokeAll(Arrays.asList(tasks));
-                    shouldThrow();
-                } catch (FJException success) {
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        testInvokeOnPool(pool, a);
-    }
-
-    /**
-     * tryUnfork returns true for most recent unexecuted task,
-     * and suppresses execution
-     */
-    public void testTryUnfork() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertTrue(f.tryUnfork());
-                helpQuiesce();
-                checkNotDone(f);
-                g.checkCompletedNormally();
-            }};
-        testInvokeOnPool(singletonPool(), a);
-    }
-
-    /**
-     * getSurplusQueuedTaskCount returns > 0 when
-     * there are more tasks than threads
-     */
-    public void testGetSurplusQueuedTaskCount() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib h = new AsyncFib(7);
-                assertSame(h, h.fork());
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertTrue(getSurplusQueuedTaskCount() > 0);
-                helpQuiesce();
-                assertEquals(0, getSurplusQueuedTaskCount());
-                f.checkCompletedNormally();
-                g.checkCompletedNormally();
-                h.checkCompletedNormally();
-            }};
-        testInvokeOnPool(singletonPool(), a);
-    }
-
-    /**
-     * peekNextLocalTask returns most recent unexecuted task.
-     */
-    public void testPeekNextLocalTask() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(f, peekNextLocalTask());
-                assertNull(f.join());
-                f.checkCompletedNormally();
-                helpQuiesce();
-                g.checkCompletedNormally();
-            }};
-        testInvokeOnPool(singletonPool(), a);
-    }
-
-    /**
-     * pollNextLocalTask returns most recent unexecuted task without
-     * executing it
-     */
-    public void testPollNextLocalTask() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(f, pollNextLocalTask());
-                helpQuiesce();
-                checkNotDone(f);
-                g.checkCompletedNormally();
-            }};
-        testInvokeOnPool(singletonPool(), a);
-    }
-
-    /**
-     * pollTask returns an unexecuted task without executing it
-     */
-    public void testPollTask() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(f, pollTask());
-                helpQuiesce();
-                checkNotDone(f);
-                g.checkCompletedNormally();
-            }};
-        testInvokeOnPool(singletonPool(), a);
-    }
-
-    /**
-     * peekNextLocalTask returns least recent unexecuted task in async mode
-     */
-    public void testPeekNextLocalTaskAsync() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(g, peekNextLocalTask());
-                assertNull(f.join());
-                helpQuiesce();
-                f.checkCompletedNormally();
-                g.checkCompletedNormally();
-            }};
-        testInvokeOnPool(asyncSingletonPool(), a);
-    }
-
-    /**
-     * pollNextLocalTask returns least recent unexecuted task without
-     * executing it, in async mode
-     */
-    public void testPollNextLocalTaskAsync() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(g, pollNextLocalTask());
-                helpQuiesce();
-                f.checkCompletedNormally();
-                checkNotDone(g);
-            }};
-        testInvokeOnPool(asyncSingletonPool(), a);
-    }
-
-    /**
-     * pollTask returns an unexecuted task without executing it, in
-     * async mode
-     */
-    public void testPollTaskAsync() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib g = new AsyncFib(9);
-                assertSame(g, g.fork());
-                AsyncFib f = new AsyncFib(8);
-                assertSame(f, f.fork());
-                assertSame(g, pollTask());
-                helpQuiesce();
-                f.checkCompletedNormally();
-                checkNotDone(g);
-            }};
-        testInvokeOnPool(asyncSingletonPool(), a);
-    }
-
-    /**
-     * ForkJoinTask.quietlyComplete returns when task completes
-     * normally without setting a value. The most recent value
-     * established by setRawResult(V) (or null by default) is returned
-     * from invoke.
-     */
-    public void testQuietlyComplete() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-                protected void realCompute() {
-                    AsyncFib f = new AsyncFib(8);
-                    f.quietlyComplete();
-                    assertEquals(8, f.number);
-                    assertTrue(f.isDone());
-                    assertFalse(f.isCancelled());
-                    assertTrue(f.isCompletedNormally());
-                    assertFalse(f.isCompletedAbnormally());
-                    assertNull(f.getException());
-                }};
-        testInvokeOnPool(mainPool(), a);
-    }
-
-    // jdk9
-
-    /**
-     * pollSubmission returns unexecuted submitted task, if present
-     */
-    public void testPollSubmission() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done));
-        final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done));
-        final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done));
-        final ForkJoinPool p = singletonPool();
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            Thread external = new Thread(new CheckedRunnable() {
-                public void realRun() {
-                    p.execute(a);
-                    p.execute(b);
-                    p.execute(c);
-                }});
-            RecursiveAction s = new CheckedRecursiveAction() {
-                protected void realCompute() {
-                    external.start();
-                    try {
-                        external.join();
-                    } catch (Exception ex) {
-                        threadUnexpectedException(ex);
-                    }
-                    assertTrue(p.hasQueuedSubmissions());
-                    assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread);
-                    ForkJoinTask r = ForkJoinTask.pollSubmission();
-                    assertTrue(r == a || r == b || r == c);
-                    assertFalse(r.isDone());
-                }};
-            p.invoke(s);
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/ForkJoinTaskTest.java b/jsr166-tests/src/test/java/jsr166/ForkJoinTaskTest.java
index 1616d4f..3c1fcb7 100644
--- a/jsr166-tests/src/test/java/jsr166/ForkJoinTaskTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ForkJoinTaskTest.java
@@ -9,10 +9,7 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ForkJoinPool;
@@ -33,7 +30,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ForkJoinTaskTest.class);
+    //     return new TestSuite(...);
     // }
 
     // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
@@ -55,7 +52,7 @@
     }
 
     private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
-        try (PoolCleaner cleaner = cleaner(pool)) {
+        try {
             assertFalse(a.isDone());
             assertFalse(a.isCompletedNormally());
             assertFalse(a.isCompletedAbnormally());
@@ -71,6 +68,8 @@
             assertFalse(a.isCancelled());
             assertNull(a.getException());
             assertNull(a.getRawResult());
+        } finally {
+            joinPool(pool);
         }
     }
 
@@ -103,17 +102,17 @@
 
         {
             Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             assertSame(expected, a.join());
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
             Thread.interrupted();
         }
 
         {
             Thread.currentThread().interrupt();
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
             Thread.interrupted();
         }
 
@@ -146,9 +145,9 @@
         Thread.interrupted();
 
         {
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
         }
 
         try {
@@ -184,9 +183,9 @@
         Thread.interrupted();
 
         {
-            long startTime = System.nanoTime();
+            long t0 = System.nanoTime();
             a.quietlyJoin();        // should be no-op
-            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
+            assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
         }
 
         try {
@@ -223,9 +222,9 @@
             AtomicIntegerFieldUpdater.newUpdater(BinaryAsyncAction.class,
                                                  "controlState");
 
-        private volatile BinaryAsyncAction parent;
+        private BinaryAsyncAction parent;
 
-        private volatile BinaryAsyncAction sibling;
+        private BinaryAsyncAction sibling;
 
         protected BinaryAsyncAction() {
         }
@@ -260,14 +259,6 @@
             super.completeExceptionally(ex);
         }
 
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            if (super.cancel(mayInterruptIfRunning)) {
-                completeExceptionally(new FJException());
-                return true;
-            }
-            return false;
-        }
-
         public final void complete() {
             BinaryAsyncAction a = this;
             for (;;) {
@@ -289,12 +280,13 @@
         }
 
         public final void completeExceptionally(Throwable ex) {
-            for (BinaryAsyncAction a = this;;) {
+            BinaryAsyncAction a = this;
+            while (!a.isCompletedAbnormally()) {
                 a.completeThisExceptionally(ex);
                 BinaryAsyncAction s = a.sibling;
-                if (s != null && !s.isDone())
-                    s.completeExceptionally(ex);
-                if ((a = a.parent) == null)
+                if (s != null)
+                    s.cancel(false);
+                if (!a.onException() || (a = a.parent) == null)
                     break;
             }
         }
@@ -344,12 +336,15 @@
         public final boolean exec() {
             AsyncFib f = this;
             int n = f.number;
-            while (n > 1) {
-                AsyncFib p = f;
-                AsyncFib r = new AsyncFib(n - 2);
-                f = new AsyncFib(--n);
-                p.linkSubtasks(r, f);
-                r.fork();
+            if (n > 1) {
+                while (n > 1) {
+                    AsyncFib p = f;
+                    AsyncFib r = new AsyncFib(n - 2);
+                    f = new AsyncFib(--n);
+                    p.linkSubtasks(r, f);
+                    r.fork();
+                }
+                f.number = n;
             }
             f.complete();
             return false;
@@ -369,12 +364,15 @@
         public final boolean exec() {
             FailingAsyncFib f = this;
             int n = f.number;
-            while (n > 1) {
-                FailingAsyncFib p = f;
-                FailingAsyncFib r = new FailingAsyncFib(n - 2);
-                f = new FailingAsyncFib(--n);
-                p.linkSubtasks(r, f);
-                r.fork();
+            if (n > 1) {
+                while (n > 1) {
+                    FailingAsyncFib p = f;
+                    FailingAsyncFib r = new FailingAsyncFib(n - 2);
+                    f = new FailingAsyncFib(--n);
+                    p.linkSubtasks(r, f);
+                    r.fork();
+                }
+                f.number = n;
             }
             f.complete();
             return false;
@@ -780,27 +778,6 @@
     }
 
     /**
-     * completeExceptionally(null) surprisingly has the same effect as
-     * completeExceptionally(new RuntimeException())
-     */
-    public void testCompleteExceptionally_null() {
-        RecursiveAction a = new CheckedRecursiveAction() {
-            protected void realCompute() {
-                AsyncFib f = new AsyncFib(8);
-                f.completeExceptionally(null);
-                try {
-                    f.invoke();
-                    shouldThrow();
-                } catch (RuntimeException success) {
-                    assertSame(success.getClass(), RuntimeException.class);
-                    assertNull(success.getCause());
-                    checkCompletedAbnormally(f, success);
-                }
-            }};
-        testInvokeOnPool(mainPool(), a);
-    }
-
-    /**
      * invokeAll(t1, t2) invokes all task arguments
      */
     public void testInvokeAll2() {
@@ -900,10 +877,8 @@
             protected void realCompute() {
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
-                ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
                 try {
-                    invokeAll(tasks);
+                    invokeAll(f, g);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(g, success);
@@ -938,10 +913,8 @@
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
                 try {
-                    invokeAll(tasks);
+                    invokeAll(f, g, h);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(g, success);
@@ -959,11 +932,12 @@
                 FailingAsyncFib f = new FailingAsyncFib(8);
                 AsyncFib g = new AsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                List taskList = Arrays.asList(tasks);
-                Collections.shuffle(taskList);
+                HashSet set = new HashSet();
+                set.add(f);
+                set.add(g);
+                set.add(h);
                 try {
-                    invokeAll(taskList);
+                    invokeAll(set);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(f, success);
@@ -1570,10 +1544,8 @@
             protected void realCompute() {
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
-                ForkJoinTask[] tasks = { f, g };
-                Collections.shuffle(Arrays.asList(tasks));
                 try {
-                    invokeAll(tasks);
+                    invokeAll(f, g);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(g, success);
@@ -1608,10 +1580,8 @@
                 AsyncFib f = new AsyncFib(8);
                 FailingAsyncFib g = new FailingAsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                Collections.shuffle(Arrays.asList(tasks));
                 try {
-                    invokeAll(tasks);
+                    invokeAll(f, g, h);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(g, success);
@@ -1629,11 +1599,12 @@
                 FailingAsyncFib f = new FailingAsyncFib(8);
                 AsyncFib g = new AsyncFib(9);
                 AsyncFib h = new AsyncFib(7);
-                ForkJoinTask[] tasks = { f, g, h };
-                List taskList = Arrays.asList(tasks);
-                Collections.shuffle(taskList);
+                HashSet set = new HashSet();
+                set.add(f);
+                set.add(g);
+                set.add(h);
                 try {
-                    invokeAll(taskList);
+                    invokeAll(set);
                     shouldThrow();
                 } catch (FJException success) {
                     checkCompletedAbnormally(f, success);
diff --git a/jsr166-tests/src/test/java/jsr166/FutureTaskTest.java b/jsr166-tests/src/test/java/jsr166/FutureTaskTest.java
index 44d12b3..a5d8c46 100644
--- a/jsr166-tests/src/test/java/jsr166/FutureTaskTest.java
+++ b/jsr166-tests/src/test/java/jsr166/FutureTaskTest.java
@@ -38,7 +38,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(FutureTaskTest.class);
+    //     return new TestSuite(...);
     // }
 
     void checkIsDone(Future<?> f) {
@@ -272,8 +272,8 @@
         for (int i = 0; i < 3; i++) {
             assertTrue(task.runAndReset());
             checkNotDone(task);
-            assertEquals(i + 1, task.runCount());
-            assertEquals(i + 1, task.runAndResetCount());
+            assertEquals(i+1, task.runCount());
+            assertEquals(i+1, task.runAndResetCount());
             assertEquals(0, task.setCount());
             assertEquals(0, task.setExceptionCount());
         }
@@ -289,7 +289,7 @@
             for (int i = 0; i < 3; i++) {
                 assertFalse(task.runAndReset());
                 assertEquals(0, task.runCount());
-                assertEquals(i + 1, task.runAndResetCount());
+                assertEquals(i+1, task.runAndResetCount());
                 assertEquals(0, task.setCount());
                 assertEquals(0, task.setExceptionCount());
             }
diff --git a/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java b/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
index fc1632c..46be906 100644
--- a/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
+++ b/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
@@ -6,21 +6,17 @@
  * Pat Fisher, Mike Judd.
  */
 
-
 package jsr166;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
- import java.security.CodeSource;
+import java.security.CodeSource;
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
@@ -39,10 +35,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.Future;
 import java.util.concurrent.RecursiveAction;
 import java.util.concurrent.RecursiveTask;
@@ -51,15 +44,12 @@
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestResult;
 import junit.framework.TestSuite;
 
 /**
@@ -72,18 +62,18 @@
  *
  * <ol>
  *
- * <li>All assertions in code running in generated threads must use
+ * <li> All assertions in code running in generated threads must use
  * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
  * #threadAssertEquals}, or {@link #threadAssertNull}, (not
  * {@code fail}, {@code assertTrue}, etc.) It is OK (but not
  * particularly recommended) for other code to use these forms too.
  * Only the most typically used JUnit assertion methods are defined
- * this way, but enough to live with.
+ * this way, but enough to live with.</li>
  *
- * <li>If you override {@link #setUp} or {@link #tearDown}, make sure
+ * <li> If you override {@link #setUp} or {@link #tearDown}, make sure
  * to invoke {@code super.setUp} and {@code super.tearDown} within
  * them. These methods are used to clear and check for thread
- * assertion failures.
+ * assertion failures.</li>
  *
  * <li>All delays and timeouts must use one of the constants {@code
  * SHORT_DELAY_MS}, {@code SMALL_DELAY_MS}, {@code MEDIUM_DELAY_MS},
@@ -94,494 +84,63 @@
  * is always discriminable as larger than SHORT and smaller than
  * MEDIUM.  And so on. These constants are set to conservative values,
  * but even so, if there is ever any doubt, they can all be increased
- * in one spot to rerun tests on slower platforms.
+ * in one spot to rerun tests on slower platforms.</li>
  *
- * <li>All threads generated must be joined inside each test case
+ * <li> All threads generated must be joined inside each test case
  * method (or {@code fail} to do so) before returning from the
  * method. The {@code joinPool} method can be used to do this when
- * using Executors.
+ * using Executors.</li>
  *
  * </ol>
  *
  * <p><b>Other notes</b>
  * <ul>
  *
- * <li>Usually, there is one testcase method per JSR166 method
+ * <li> Usually, there is one testcase method per JSR166 method
  * covering "normal" operation, and then as many exception-testing
  * methods as there are exceptions the method can throw. Sometimes
  * there are multiple tests per JSR166 method when the different
  * "normal" behaviors differ significantly. And sometimes testcases
- * cover multiple methods when they cannot be tested in isolation.
+ * cover multiple methods when they cannot be tested in
+ * isolation.</li>
  *
- * <li>The documentation style for testcases is to provide as javadoc
+ * <li> The documentation style for testcases is to provide as javadoc
  * a simple sentence or two describing the property that the testcase
  * method purports to test. The javadocs do not say anything about how
- * the property is tested. To find out, read the code.
+ * the property is tested. To find out, read the code.</li>
  *
- * <li>These tests are "conformance tests", and do not attempt to
+ * <li> These tests are "conformance tests", and do not attempt to
  * test throughput, latency, scalability or other performance factors
  * (see the separate "jtreg" tests for a set intended to check these
  * for the most central aspects of functionality.) So, most tests use
  * the smallest sensible numbers of threads, collection sizes, etc
- * needed to check basic conformance.
+ * needed to check basic conformance.</li>
  *
  * <li>The test classes currently do not declare inclusion in
  * any particular package to simplify things for people integrating
- * them in TCK test suites.
+ * them in TCK test suites.</li>
  *
- * <li>As a convenience, the {@code main} of this class (JSR166TestCase)
- * runs all JSR166 unit tests.
+ * <li> As a convenience, the {@code main} of this class (JSR166TestCase)
+ * runs all JSR166 unit tests.</li>
  *
  * </ul>
  */
 public class JSR166TestCase extends TestCase {
-    private static final boolean useSecurityManager =
-        Boolean.getBoolean("jsr166.useSecurityManager");
-
-    protected static final boolean expensiveTests =
-        Boolean.getBoolean("jsr166.expensiveTests");
-
-    /**
-     * If true, also run tests that are not part of the official tck
-     * because they test unspecified implementation details.
-     */
-    protected static final boolean testImplementationDetails =
-        Boolean.getBoolean("jsr166.testImplementationDetails");
-
-    /**
-     * If true, report on stdout all "slow" tests, that is, ones that
-     * take more than profileThreshold milliseconds to execute.
-     */
-    private static final boolean profileTests =
-        Boolean.getBoolean("jsr166.profileTests");
-
-    /**
-     * The number of milliseconds that tests are permitted for
-     * execution without being reported, when profileTests is set.
-     */
-    private static final long profileThreshold =
-        Long.getLong("jsr166.profileThreshold", 100);
-
-    /**
-     * The number of repetitions per test (for tickling rare bugs).
-     */
-    private static final int runsPerTest =
-        Integer.getInteger("jsr166.runsPerTest", 1);
-
-    /**
-     * The number of repetitions of the test suite (for finding leaks?).
-     */
-    private static final int suiteRuns =
-        Integer.getInteger("jsr166.suiteRuns", 1);
-
-    private static float systemPropertyValue(String name, float defaultValue) {
-        String floatString = System.getProperty(name);
-        if (floatString == null)
-            return defaultValue;
-        try {
-            return Float.parseFloat(floatString);
-        } catch (NumberFormatException ex) {
-            throw new IllegalArgumentException(
-                String.format("Bad float value in system property %s=%s",
-                              name, floatString));
-        }
-    }
-
-    /**
-     * The scaling factor to apply to standard delays used in tests.
-     */
-    private static final float delayFactor =
-        systemPropertyValue("jsr166.delay.factor", 1.0f);
-
-    /**
-     * The timeout factor as used in the jtreg test harness.
-     * See: http://openjdk.java.net/jtreg/tag-spec.html
-     */
-    private static final float jtregTestTimeoutFactor
-        = systemPropertyValue("test.timeout.factor", 1.0f);
-
-    public JSR166TestCase() { super(); }
-    public JSR166TestCase(String name) { super(name); }
-
-    /**
-     * A filter for tests to run, matching strings of the form
-     * methodName(className), e.g. "testInvokeAll5(ForkJoinPoolTest)"
-     * Usefully combined with jsr166.runsPerTest.
-     */
-    private static final Pattern methodFilter = methodFilter();
-
-    private static Pattern methodFilter() {
-        String regex = System.getProperty("jsr166.methodFilter");
-        return (regex == null) ? null : Pattern.compile(regex);
-    }
-
-    // Instrumentation to debug very rare, but very annoying hung test runs.
-    static volatile TestCase currentTestCase;
-    // static volatile int currentRun = 0;
-    static {
-        Runnable checkForWedgedTest = new Runnable() { public void run() {
-            // Avoid spurious reports with enormous runsPerTest.
-            // A single test case run should never take more than 1 second.
-            // But let's cap it at the high end too ...
-            final int timeoutMinutes =
-                Math.min(15, Math.max(runsPerTest / 60, 1));
-            for (TestCase lastTestCase = currentTestCase;;) {
-                try { MINUTES.sleep(timeoutMinutes); }
-                catch (InterruptedException unexpected) { break; }
-                if (lastTestCase == currentTestCase) {
-                    System.err.printf(
-                        "Looks like we're stuck running test: %s%n",
-                        lastTestCase);
-//                     System.err.printf(
-//                         "Looks like we're stuck running test: %s (%d/%d)%n",
-//                         lastTestCase, currentRun, runsPerTest);
-//                     System.err.println("availableProcessors=" +
-//                         Runtime.getRuntime().availableProcessors());
-//                     System.err.printf("cpu model = %s%n", cpuModel());
-                    dumpTestThreads();
-                    // one stack dump is probably enough; more would be spam
-                    break;
-                }
-                lastTestCase = currentTestCase;
-            }}};
-        Thread thread = new Thread(checkForWedgedTest, "checkForWedgedTest");
-        thread.setDaemon(true);
-        thread.start();
-    }
-
-//     public static String cpuModel() {
-//         try {
-//             Matcher matcher = Pattern.compile("model name\\s*: (.*)")
-//                 .matcher(new String(
-//                      Files.readAllBytes(Paths.get("/proc/cpuinfo")), "UTF-8"));
-//             matcher.find();
-//             return matcher.group(1);
-//         } catch (Exception ex) { return null; }
-//     }
-
-    public void runBare() throws Throwable {
-        currentTestCase = this;
-        if (methodFilter == null
-            || methodFilter.matcher(toString()).find())
-            super.runBare();
-    }
-
-    protected void runTest() throws Throwable {
-        for (int i = 0; i < runsPerTest; i++) {
-            // currentRun = i;
-            if (profileTests)
-                runTestProfiled();
-            else
-                super.runTest();
-        }
-    }
-
-    protected void runTestProfiled() throws Throwable {
-        for (int i = 0; i < 2; i++) {
-            long startTime = System.nanoTime();
-            super.runTest();
-            long elapsedMillis = millisElapsedSince(startTime);
-            if (elapsedMillis < profileThreshold)
-                break;
-            // Never report first run of any test; treat it as a
-            // warmup run, notably to trigger all needed classloading,
-            if (i > 0)
-                System.out.printf("%n%s: %d%n", toString(), elapsedMillis);
-        }
-    }
-
-    /**
-     * Runs all JSR166 unit tests using junit.textui.TestRunner.
-     */
-    // android-note: Removed because no junit.textui
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-
-    // static class PithyResultPrinter extends junit.textui.ResultPrinter {
-    //     PithyResultPrinter(java.io.PrintStream writer) { super(writer); }
-    //     long runTime;
-    //     public void startTest(Test test) {}
-    //     protected void printHeader(long runTime) {
-    //         this.runTime = runTime; // defer printing for later
-    //     }
-    //     protected void printFooter(TestResult result) {
-    //         if (result.wasSuccessful()) {
-    //             getWriter().println("OK (" + result.runCount() + " tests)"
-    //                 + "  Time: " + elapsedTimeAsString(runTime));
-    //         } else {
-    //             getWriter().println("Time: " + elapsedTimeAsString(runTime));
-    //             super.printFooter(result);
-    //         }
-    //     }
-    // }
-
-    /**
-     * Returns a TestRunner that doesn't bother with unnecessary
-     * fluff, like printing a "." for each test case.
-     */
-    // static junit.textui.TestRunner newPithyTestRunner() {
-    //     junit.textui.TestRunner runner = new junit.textui.TestRunner();
-    //     runner.setPrinter(new PithyResultPrinter(System.out));
-    //     return runner;
-    // }
-
-    /**
-     * Runs all unit tests in the given test suite.
-     * Actual behavior influenced by jsr166.* system properties.
-     */
-    // static void main(Test suite, String[] args) {
-    //     if (useSecurityManager) {
-    //         System.err.println("Setting a permissive security manager");
-    //         Policy.setPolicy(permissivePolicy());
-    //         System.setSecurityManager(new SecurityManager());
-    //     }
-    //     for (int i = 0; i < suiteRuns; i++) {
-    //         TestResult result = newPithyTestRunner().doRun(suite);
-    //         if (!result.wasSuccessful())
-    //             System.exit(1);
-    //         System.gc();
-    //         System.runFinalization();
-    //     }
-    // }
-
-    public static TestSuite newTestSuite(Object... suiteOrClasses) {
-        TestSuite suite = new TestSuite();
-        for (Object suiteOrClass : suiteOrClasses) {
-            if (suiteOrClass instanceof TestSuite)
-                suite.addTest((TestSuite) suiteOrClass);
-            else if (suiteOrClass instanceof Class)
-                suite.addTest(new TestSuite((Class<?>) suiteOrClass));
-            else
-                throw new ClassCastException("not a test suite or class");
-        }
-        return suite;
-    }
-
-    public static void addNamedTestClasses(TestSuite suite,
-                                           String... testClassNames) {
-        for (String testClassName : testClassNames) {
-            try {
-                Class<?> testClass = Class.forName(testClassName);
-                Method m = testClass.getDeclaredMethod("suite",
-                                                       new Class<?>[0]);
-                suite.addTest(newTestSuite((Test)m.invoke(null)));
-            } catch (Exception e) {
-                throw new Error("Missing test class", e);
-            }
-        }
-    }
-
-    public static final double JAVA_CLASS_VERSION;
-    public static final String JAVA_SPECIFICATION_VERSION;
-    static {
-        try {
-            JAVA_CLASS_VERSION = java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<Double>() {
-                public Double run() {
-                    return Double.valueOf(System.getProperty("java.class.version"));}});
-            JAVA_SPECIFICATION_VERSION = java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<String>() {
-                public String run() {
-                    return System.getProperty("java.specification.version");}});
-        } catch (Throwable t) {
-            throw new Error(t);
-        }
-    }
-
-    public static boolean atLeastJava6() { return JAVA_CLASS_VERSION >= 50.0; }
-    public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; }
-    public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; }
-    public static boolean atLeastJava9() {
-        return JAVA_CLASS_VERSION >= 53.0
-            // As of 2015-09, java9 still uses 52.0 class file version
-            || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?(9|[0-9][0-9])$");
-    }
-    public static boolean atLeastJava10() {
-        return JAVA_CLASS_VERSION >= 54.0
-            || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?[0-9][0-9]$");
-    }
-
-    /**
-     * Collects all JSR166 unit tests as one suite.
-     */
-    // android-note: Removed because the CTS runner does a bad job of
-    // public static Test suite() {
-    //     // Java7+ test classes
-    //     TestSuite suite = newTestSuite(
-    //         ForkJoinPoolTest.suite(),
-    //         ForkJoinTaskTest.suite(),
-    //         RecursiveActionTest.suite(),
-    //         RecursiveTaskTest.suite(),
-    //         LinkedTransferQueueTest.suite(),
-    //         PhaserTest.suite(),
-    //         ThreadLocalRandomTest.suite(),
-    //         AbstractExecutorServiceTest.suite(),
-    //         AbstractQueueTest.suite(),
-    //         AbstractQueuedSynchronizerTest.suite(),
-    //         AbstractQueuedLongSynchronizerTest.suite(),
-    //         ArrayBlockingQueueTest.suite(),
-    //         ArrayDequeTest.suite(),
-    //         AtomicBooleanTest.suite(),
-    //         AtomicIntegerArrayTest.suite(),
-    //         AtomicIntegerFieldUpdaterTest.suite(),
-    //         AtomicIntegerTest.suite(),
-    //         AtomicLongArrayTest.suite(),
-    //         AtomicLongFieldUpdaterTest.suite(),
-    //         AtomicLongTest.suite(),
-    //         AtomicMarkableReferenceTest.suite(),
-    //         AtomicReferenceArrayTest.suite(),
-    //         AtomicReferenceFieldUpdaterTest.suite(),
-    //         AtomicReferenceTest.suite(),
-    //         AtomicStampedReferenceTest.suite(),
-    //         ConcurrentHashMapTest.suite(),
-    //         ConcurrentLinkedDequeTest.suite(),
-    //         ConcurrentLinkedQueueTest.suite(),
-    //         ConcurrentSkipListMapTest.suite(),
-    //         ConcurrentSkipListSubMapTest.suite(),
-    //         ConcurrentSkipListSetTest.suite(),
-    //         ConcurrentSkipListSubSetTest.suite(),
-    //         CopyOnWriteArrayListTest.suite(),
-    //         CopyOnWriteArraySetTest.suite(),
-    //         CountDownLatchTest.suite(),
-    //         CyclicBarrierTest.suite(),
-    //         DelayQueueTest.suite(),
-    //         EntryTest.suite(),
-    //         ExchangerTest.suite(),
-    //         ExecutorsTest.suite(),
-    //         ExecutorCompletionServiceTest.suite(),
-    //         FutureTaskTest.suite(),
-    //         LinkedBlockingDequeTest.suite(),
-    //         LinkedBlockingQueueTest.suite(),
-    //         LinkedListTest.suite(),
-    //         LockSupportTest.suite(),
-    //         PriorityBlockingQueueTest.suite(),
-    //         PriorityQueueTest.suite(),
-    //         ReentrantLockTest.suite(),
-    //         ReentrantReadWriteLockTest.suite(),
-    //         ScheduledExecutorTest.suite(),
-    //         ScheduledExecutorSubclassTest.suite(),
-    //         SemaphoreTest.suite(),
-    //         SynchronousQueueTest.suite(),
-    //         SystemTest.suite(),
-    //         ThreadLocalTest.suite(),
-    //         ThreadPoolExecutorTest.suite(),
-    //         ThreadPoolExecutorSubclassTest.suite(),
-    //         ThreadTest.suite(),
-    //         TimeUnitTest.suite(),
-    //         TreeMapTest.suite(),
-    //         TreeSetTest.suite(),
-    //         TreeSubMapTest.suite(),
-    //         TreeSubSetTest.suite());
-
-    //     // Java8+ test classes
-    //     if (atLeastJava8()) {
-    //         String[] java8TestClassNames = {
-    //             "Atomic8Test",
-    //             "CompletableFutureTest",
-    //             "ConcurrentHashMap8Test",
-    //             "CountedCompleterTest",
-    //             "DoubleAccumulatorTest",
-    //             "DoubleAdderTest",
-    //             "ForkJoinPool8Test",
-    //             "ForkJoinTask8Test",
-    //             "LongAccumulatorTest",
-    //             "LongAdderTest",
-    //             "SplittableRandomTest",
-    //             "StampedLockTest",
-    //             "SubmissionPublisherTest",
-    //             "ThreadLocalRandom8Test",
-    //         };
-    //         addNamedTestClasses(suite, java8TestClassNames);
-    //     }
-
-    //     // Java9+ test classes
-    //     if (atLeastJava9()) {
-    //         String[] java9TestClassNames = {
-    //             // Currently empty, but expecting varhandle tests
-    //         };
-    //         addNamedTestClasses(suite, java9TestClassNames);
-    //     }
-
-    //     return suite;
-    // }
-
-    /** Returns list of junit-style test method names in given class. */
-    public static ArrayList<String> testMethodNames(Class<?> testClass) {
-        Method[] methods = testClass.getDeclaredMethods();
-        ArrayList<String> names = new ArrayList<String>(methods.length);
-        for (Method method : methods) {
-            if (method.getName().startsWith("test")
-                && Modifier.isPublic(method.getModifiers())
-                // method.getParameterCount() requires jdk8+
-                && method.getParameterTypes().length == 0) {
-                names.add(method.getName());
-            }
-        }
-        return names;
-    }
-
-    /**
-     * Returns junit-style testSuite for the given test class, but
-     * parameterized by passing extra data to each test.
-     */
-    public static <ExtraData> Test parameterizedTestSuite
-        (Class<? extends JSR166TestCase> testClass,
-         Class<ExtraData> dataClass,
-         ExtraData data) {
-        try {
-            TestSuite suite = new TestSuite();
-            Constructor c =
-                testClass.getDeclaredConstructor(dataClass, String.class);
-            for (String methodName : testMethodNames(testClass))
-                suite.addTest((Test) c.newInstance(data, methodName));
-            return suite;
-        } catch (Exception e) {
-            throw new Error(e);
-        }
-    }
-
-    /**
-     * Returns junit-style testSuite for the jdk8 extension of the
-     * given test class, but parameterized by passing extra data to
-     * each test.  Uses reflection to allow compilation in jdk7.
-     */
-    public static <ExtraData> Test jdk8ParameterizedTestSuite
-        (Class<? extends JSR166TestCase> testClass,
-         Class<ExtraData> dataClass,
-         ExtraData data) {
-        if (atLeastJava8()) {
-            String name = testClass.getName();
-            String name8 = name.replaceAll("Test$", "8Test");
-            if (name.equals(name8)) throw new Error(name);
-            try {
-                return (Test)
-                    Class.forName(name8)
-                    .getMethod("testSuite", new Class[] { dataClass })
-                    .invoke(null, data);
-            } catch (Exception e) {
-                throw new Error(e);
-            }
-        } else {
-            return new TestSuite();
-        }
-    }
-
     // Delays for timing-dependent tests, in milliseconds.
 
+    protected static final boolean expensiveTests = false;
+
     public static long SHORT_DELAY_MS;
     public static long SMALL_DELAY_MS;
     public static long MEDIUM_DELAY_MS;
     public static long LONG_DELAY_MS;
 
     /**
-     * Returns the shortest timed delay. This can be scaled up for
-     * slow machines using the jsr166.delay.factor system property,
-     * or via jtreg's -timeoutFactor: flag.
-     * http://openjdk.java.net/jtreg/command-help.html
+     * Returns the shortest timed delay. This could
+     * be reimplemented to use for example a Property.
      */
     protected long getShortDelay() {
-        return (long) (50 * delayFactor * jtregTestTimeoutFactor);
+        return 50;
     }
 
     /**
@@ -603,12 +162,11 @@
     }
 
     /**
-     * Returns a new Date instance representing a time at least
-     * delayMillis milliseconds in the future.
+     * Returns a new Date instance representing a time delayMillis
+     * milliseconds in the future.
      */
     Date delayedDate(long delayMillis) {
-        // Add 1 because currentTimeMillis is known to round into the past.
-        return new Date(System.currentTimeMillis() + delayMillis + 1);
+        return new Date(System.currentTimeMillis() + delayMillis);
     }
 
     /**
@@ -624,8 +182,6 @@
      * the same test have no effect.
      */
     public void threadRecordFailure(Throwable t) {
-        System.err.println(t);
-        dumpTestThreads();
         threadFailure.compareAndSet(null, t);
     }
 
@@ -633,13 +189,6 @@
         setDelays();
     }
 
-    void tearDownFail(String format, Object... args) {
-        String msg = toString() + ": " + String.format(format, args);
-        System.err.println(msg);
-        dumpTestThreads();
-        throw new AssertionFailedError(msg);
-    }
-
     /**
      * Extra checks that get done for all test cases.
      *
@@ -667,16 +216,16 @@
         }
 
         if (Thread.interrupted())
-            tearDownFail("interrupt status set in main thread");
+            throw new AssertionFailedError("interrupt status set in main thread");
 
         checkForkJoinPoolThreadLeaks();
     }
 
     /**
-     * Finds missing PoolCleaners
+     * Finds missing try { ... } finally { joinPool(e); }
      */
     void checkForkJoinPoolThreadLeaks() throws InterruptedException {
-        Thread[] survivors = new Thread[7];
+        Thread[] survivors = new Thread[5];
         int count = Thread.enumerate(survivors);
         for (int i = 0; i < count; i++) {
             Thread thread = survivors[i];
@@ -684,15 +233,13 @@
             if (name.startsWith("ForkJoinPool-")) {
                 // give thread some time to terminate
                 thread.join(LONG_DELAY_MS);
-                if (thread.isAlive())
-                    tearDownFail("Found leaked ForkJoinPool thread thread=%s",
-                                 thread);
+                if (!thread.isAlive()) continue;
+                thread.stop();
+                throw new AssertionFailedError
+                    (String.format("Found leaked ForkJoinPool thread test=%s thread=%s%n",
+                                   toString(), name));
             }
         }
-
-        if (!ForkJoinPool.commonPool()
-            .awaitQuiescence(LONG_DELAY_MS, MILLISECONDS))
-            tearDownFail("ForkJoin common pool thread stuck");
     }
 
     /**
@@ -705,7 +252,7 @@
             fail(reason);
         } catch (AssertionFailedError t) {
             threadRecordFailure(t);
-            throw t;
+            fail(reason);
         }
     }
 
@@ -832,148 +379,44 @@
     /**
      * Delays, via Thread.sleep, for the given millisecond delay, but
      * if the sleep is shorter than specified, may re-sleep or yield
-     * until time elapses.  Ensures that the given time, as measured
-     * by System.nanoTime(), has elapsed.
+     * until time elapses.
      */
     static void delay(long millis) throws InterruptedException {
-        long nanos = millis * (1000 * 1000);
-        final long wakeupTime = System.nanoTime() + nanos;
-        do {
+        long startTime = System.nanoTime();
+        long ns = millis * 1000 * 1000;
+        for (;;) {
             if (millis > 0L)
                 Thread.sleep(millis);
             else // too short to sleep
                 Thread.yield();
-            nanos = wakeupTime - System.nanoTime();
-            millis = nanos / (1000 * 1000);
-        } while (nanos >= 0L);
-    }
-
-    /**
-     * Allows use of try-with-resources with per-test thread pools.
-     */
-    class PoolCleaner implements AutoCloseable {
-        private final ExecutorService pool;
-        public PoolCleaner(ExecutorService pool) { this.pool = pool; }
-        public void close() { joinPool(pool); }
-    }
-
-    /**
-     * An extension of PoolCleaner that has an action to release the pool.
-     */
-    class PoolCleanerWithReleaser extends PoolCleaner {
-        private final Runnable releaser;
-        public PoolCleanerWithReleaser(ExecutorService pool, Runnable releaser) {
-            super(pool);
-            this.releaser = releaser;
+            long d = ns - (System.nanoTime() - startTime);
+            if (d > 0L)
+                millis = d / (1000 * 1000);
+            else
+                break;
         }
-        public void close() {
-            try {
-                releaser.run();
-            } finally {
-                super.close();
-            }
-        }
-    }
-
-    PoolCleaner cleaner(ExecutorService pool) {
-        return new PoolCleaner(pool);
-    }
-
-    PoolCleaner cleaner(ExecutorService pool, Runnable releaser) {
-        return new PoolCleanerWithReleaser(pool, releaser);
-    }
-
-    PoolCleaner cleaner(ExecutorService pool, CountDownLatch latch) {
-        return new PoolCleanerWithReleaser(pool, releaser(latch));
-    }
-
-    Runnable releaser(final CountDownLatch latch) {
-        return new Runnable() { public void run() {
-            do { latch.countDown(); }
-            while (latch.getCount() > 0);
-        }};
-    }
-
-    PoolCleaner cleaner(ExecutorService pool, AtomicBoolean flag) {
-        return new PoolCleanerWithReleaser(pool, releaser(flag));
-    }
-
-    Runnable releaser(final AtomicBoolean flag) {
-        return new Runnable() { public void run() { flag.set(true); }};
     }
 
     /**
      * Waits out termination of a thread pool or fails doing so.
      */
-    void joinPool(ExecutorService pool) {
+    void joinPool(ExecutorService exec) {
         try {
-            pool.shutdown();
-            if (!pool.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS)) {
-                try {
-                    threadFail("ExecutorService " + pool +
-                               " did not terminate in a timely manner");
-                } finally {
-                    // last resort, for the benefit of subsequent tests
-                    pool.shutdownNow();
-                    pool.awaitTermination(MEDIUM_DELAY_MS, MILLISECONDS);
-                }
-            }
+            exec.shutdown();
+            if (!exec.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS))
+                fail("ExecutorService " + exec +
+                     " did not terminate in a timely manner");
         } catch (SecurityException ok) {
             // Allowed in case test doesn't have privs
         } catch (InterruptedException fail) {
-            threadFail("Unexpected InterruptedException");
-        }
-    }
-
-    /** Like Runnable, but with the freedom to throw anything */
-    interface Action { public void run() throws Throwable; }
-
-    /**
-     * Runs all the given actions in parallel, failing if any fail.
-     * Useful for running multiple variants of tests that are
-     * necessarily individually slow because they must block.
-     */
-    void testInParallel(Action ... actions) {
-        ExecutorService pool = Executors.newCachedThreadPool();
-        try (PoolCleaner cleaner = cleaner(pool)) {
-            ArrayList<Future<?>> futures = new ArrayList<>(actions.length);
-            for (final Action action : actions)
-                futures.add(pool.submit(new CheckedRunnable() {
-                    public void realRun() throws Throwable { action.run();}}));
-            for (Future<?> future : futures)
-                try {
-                    assertNull(future.get(LONG_DELAY_MS, MILLISECONDS));
-                } catch (ExecutionException ex) {
-                    threadUnexpectedException(ex.getCause());
-                } catch (Exception ex) {
-                    threadUnexpectedException(ex);
-                }
+            fail("Unexpected InterruptedException");
         }
     }
 
     /**
-     * A debugging tool to print stack traces of most threads, as jstack does.
-     * Uninteresting threads are filtered out.
+     * A debugging tool to print all stack traces, as jstack does.
      */
-    static void dumpTestThreads() {
-        // Android-change no ThreadMXBean
-        // 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;
-        //     if ("checkForWedgedTest".equals(name))
-        //         continue;
-        //     System.err.print(info);
-        // }
-        // System.err.println("------ stacktrace dump end ------");
+    static void printAllStackTraces() {
     }
 
     /**
@@ -993,7 +436,7 @@
             delay(millis);
             assertTrue(thread.isAlive());
         } catch (InterruptedException fail) {
-            threadFail("Unexpected InterruptedException");
+            fail("Unexpected InterruptedException");
         }
     }
 
@@ -1015,7 +458,7 @@
             for (Thread thread : threads)
                 assertTrue(thread.isAlive());
         } catch (InterruptedException fail) {
-            threadFail("Unexpected InterruptedException");
+            fail("Unexpected InterruptedException");
         }
     }
 
@@ -1089,12 +532,6 @@
      * getPolicy/setPolicy.
      */
     public void runWithPermissions(Runnable r, Permission... permissions) {
-        // Android-changed - no SecurityManager
-        // SecurityManager sm = System.getSecurityManager();
-        // if (sm == null) {
-        //     r.run();
-        // }
-        // runWithSecurityManagerWithPermissions(r, permissions);
         r.run();
     }
 
@@ -1107,30 +544,6 @@
      */
     public void runWithSecurityManagerWithPermissions(Runnable r,
                                                       Permission... permissions) {
-        // Android-changed - no SecurityManager
-        // SecurityManager sm = System.getSecurityManager();
-        // if (sm == null) {
-        //     Policy savedPolicy = Policy.getPolicy();
-        //     try {
-        //         Policy.setPolicy(permissivePolicy());
-        //         System.setSecurityManager(new SecurityManager());
-        //         runWithSecurityManagerWithPermissions(r, permissions);
-        //     } finally {
-        //         System.setSecurityManager(null);
-        //         Policy.setPolicy(savedPolicy);
-        //     }
-        // } else {
-        //     Policy savedPolicy = Policy.getPolicy();
-        //     AdjustablePolicy policy = new AdjustablePolicy(permissions);
-        //     Policy.setPolicy(policy);
-
-        //     try {
-        //         r.run();
-        //     } finally {
-        //         policy.addPermission(new SecurityPermission("setPolicy"));
-        //         Policy.setPolicy(savedPolicy);
-        //     }
-        // }
         r.run();
     }
 
@@ -1235,6 +648,19 @@
         waitForThreadToEnterWaitState(thread, LONG_DELAY_MS);
     }
 
+    void waitForThreadToEnterWaitStateNoTimeout(Thread thread) {
+        for (;;) {
+            Thread.State s = thread.getState();
+            if (s == Thread.State.BLOCKED ||
+                s == Thread.State.WAITING ||
+                s == Thread.State.TIMED_WAITING)
+                return;
+            else if (s == Thread.State.TERMINATED)
+                fail("Unexpected thread termination");
+            Thread.yield();
+        }
+    }
+
     /**
      * Returns the number of milliseconds since time given by
      * startNanoTime, which must have been previously returned from a
@@ -1297,7 +723,7 @@
         } finally {
             if (t.getState() != Thread.State.TERMINATED) {
                 t.interrupt();
-                threadFail("timed out waiting for thread to terminate");
+                fail("Test timed out");
             }
         }
     }
@@ -1422,10 +848,7 @@
     public static final String TEST_STRING = "a test string";
 
     public static class StringTask implements Callable<String> {
-        final String value;
-        public StringTask() { this(TEST_STRING); }
-        public StringTask(String value) { this.value = value; }
-        public String call() { return value; }
+        public String call() { return TEST_STRING; }
     }
 
     public Callable<String> latchAwaitingStringTask(final CountDownLatch latch) {
@@ -1438,50 +861,24 @@
             }};
     }
 
-    public Runnable countDowner(final CountDownLatch latch) {
+    public Runnable awaiter(final CountDownLatch latch) {
         return new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                latch.countDown();
+                await(latch);
             }};
     }
 
-    class LatchAwaiter extends CheckedRunnable {
-        static final int NEW = 0;
-        static final int RUNNING = 1;
-        static final int DONE = 2;
-        final CountDownLatch latch;
-        int state = NEW;
-        LatchAwaiter(CountDownLatch latch) { this.latch = latch; }
-        public void realRun() throws InterruptedException {
-            state = 1;
-            await(latch);
-            state = 2;
-        }
-    }
-
-    public LatchAwaiter awaiter(CountDownLatch latch) {
-        return new LatchAwaiter(latch);
-    }
-
-    public void await(CountDownLatch latch, long timeoutMillis) {
+    public void await(CountDownLatch latch) {
         try {
-            if (!latch.await(timeoutMillis, MILLISECONDS))
-                fail("timed out waiting for CountDownLatch for "
-                     + (timeoutMillis/1000) + " sec");
+            assertTrue(latch.await(LONG_DELAY_MS, MILLISECONDS));
         } catch (Throwable fail) {
             threadUnexpectedException(fail);
         }
     }
 
-    public void await(CountDownLatch latch) {
-        await(latch, LONG_DELAY_MS);
-    }
-
     public void await(Semaphore semaphore) {
         try {
-            if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS))
-                fail("timed out waiting for Semaphore for "
-                     + (LONG_DELAY_MS/1000) + " sec");
+            assertTrue(semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS));
         } catch (Throwable fail) {
             threadUnexpectedException(fail);
         }
diff --git a/jsr166-tests/src/test/java/jsr166/LinkedBlockingDequeTest.java b/jsr166-tests/src/test/java/jsr166/LinkedBlockingDequeTest.java
index 789373d..62802bb 100644
--- a/jsr166-tests/src/test/java/jsr166/LinkedBlockingDequeTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LinkedBlockingDequeTest.java
@@ -26,24 +26,25 @@
 
 public class LinkedBlockingDequeTest extends JSR166TestCase {
 
-    public static class Unbounded extends BlockingQueueTest {
-        protected BlockingQueue emptyCollection() {
-            return new LinkedBlockingDeque();
-        }
-    }
-
-    public static class Bounded extends BlockingQueueTest {
-        protected BlockingQueue emptyCollection() {
-            return new LinkedBlockingDeque(SIZE);
-        }
-    }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
+    // android-note: These tests have been moved into their own separate
+    // classes to work around CTS issues.
+    //
+    // public static class Unbounded extends BlockingQueueTest {
+    //     protected BlockingQueue emptyCollection() {
+    //         return new LinkedBlockingDeque();
+    //     }
+    // }
+    //
+    // public static class Bounded extends BlockingQueueTest {
+    //     protected BlockingQueue emptyCollection() {
+    //         return new LinkedBlockingDeque(SIZE);
+    //     }
+    // }
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(LinkedBlockingDequeTest.class,
     //                         new Unbounded().testSuite(),
@@ -86,7 +87,7 @@
     public void testSize() {
         LinkedBlockingDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.removeFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -151,7 +152,7 @@
      */
     public void testPollLast() {
         LinkedBlockingDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollLast());
@@ -190,7 +191,7 @@
      */
     public void testPeekLast() {
         LinkedBlockingDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.peekLast());
             assertEquals(i, q.pollLast());
             assertTrue(q.peekLast() == null ||
@@ -220,7 +221,7 @@
      */
     public void testLastElement() {
         LinkedBlockingDeque q = populatedDeque(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.getLast());
             assertEquals(i, q.pollLast());
         }
@@ -285,7 +286,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeFirstOccurrence(new Integer(i)));
-            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -300,7 +301,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeLastOccurrence(new Integer(i)));
-            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeLastOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -371,7 +372,7 @@
      */
     public void testConstructor5() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = i;
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -418,7 +419,7 @@
             assertEquals(i, q.remove());
         }
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.remainingCapacity());
+            assertEquals(SIZE-i, q.remainingCapacity());
             assertEquals(SIZE, q.size() + q.remainingCapacity());
             assertTrue(q.add(i));
         }
@@ -428,8 +429,8 @@
      * push(null) throws NPE
      */
     public void testPushNull() {
-        LinkedBlockingDeque q = new LinkedBlockingDeque(1);
         try {
+            LinkedBlockingDeque q = new LinkedBlockingDeque(1);
             q.push(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -439,14 +440,14 @@
      * push succeeds if not full; throws ISE if full
      */
     public void testPush() {
-        LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
-        for (int i = 0; i < SIZE; ++i) {
-            Integer x = new Integer(i);
-            q.push(x);
-            assertEquals(x, q.peek());
-        }
-        assertEquals(0, q.remainingCapacity());
         try {
+            LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+            for (int i = 0; i < SIZE; ++i) {
+                Integer x = new Integer(i);
+                q.push(x);
+                assertEquals(x, q.peek());
+            }
+            assertEquals(0, q.remainingCapacity());
             q.push(new Integer(SIZE));
             shouldThrow();
         } catch (IllegalStateException success) {}
@@ -517,7 +518,7 @@
     public void testAddAll3() {
         LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -755,23 +756,25 @@
         final CountDownLatch aboutToWait = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
                 }
+                long t0 = System.nanoTime();
                 aboutToWait.countDown();
                 try {
-                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    q.poll(MEDIUM_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                    assertTrue(millisElapsedSince(t0) < MEDIUM_DELAY_MS);
                 }
             }});
 
         aboutToWait.await();
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
         t.interrupt();
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         checkEmpty(q);
     }
 
@@ -1052,18 +1055,17 @@
      * returning timeout status
      */
     public void testInterruptedTimedPollFirst() throws InterruptedException {
-        final LinkedBlockingDeque q = populatedDeque(SIZE);
         final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
+                LinkedBlockingDeque q = populatedDeque(SIZE);
                 for (int i = 0; i < SIZE; ++i) {
                     assertEquals(i, q.pollFirst(LONG_DELAY_MS, MILLISECONDS));
                 }
 
                 Thread.currentThread().interrupt();
                 try {
-                    q.pollFirst(LONG_DELAY_MS, MILLISECONDS);
+                    q.pollFirst(SMALL_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
@@ -1074,7 +1076,6 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         await(pleaseInterrupt);
@@ -1250,7 +1251,7 @@
     public void testTakeLast() throws InterruptedException {
         LinkedBlockingDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i - 1, q.takeLast());
+            assertEquals(SIZE-i-1, q.takeLast());
         }
     }
 
@@ -1263,7 +1264,7 @@
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
                 for (int i = 0; i < SIZE; ++i) {
-                    assertEquals(SIZE - i - 1, q.takeLast());
+                    assertEquals(SIZE-i-1, q.takeLast());
                 }
 
                 Thread.currentThread().interrupt();
@@ -1293,7 +1294,7 @@
     public void testTimedPollLast0() throws InterruptedException {
         LinkedBlockingDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i - 1, q.pollLast(0, MILLISECONDS));
+            assertEquals(SIZE-i-1, q.pollLast(0, MILLISECONDS));
         }
         assertNull(q.pollLast(0, MILLISECONDS));
     }
@@ -1305,7 +1306,7 @@
         LinkedBlockingDeque q = populatedDeque(SIZE);
         for (int i = 0; i < SIZE; ++i) {
             long startTime = System.nanoTime();
-            assertEquals(SIZE - i - 1, q.pollLast(LONG_DELAY_MS, MILLISECONDS));
+            assertEquals(SIZE-i-1, q.pollLast(LONG_DELAY_MS, MILLISECONDS));
             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
         }
         long startTime = System.nanoTime();
@@ -1319,14 +1320,12 @@
      * returning timeout status
      */
     public void testInterruptedTimedPollLast() throws InterruptedException {
-        final LinkedBlockingDeque q = populatedDeque(SIZE);
         final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
+                LinkedBlockingDeque q = populatedDeque(SIZE);
                 for (int i = 0; i < SIZE; ++i) {
-                    assertEquals(SIZE - i - 1,
-                                 q.pollLast(LONG_DELAY_MS, MILLISECONDS));
+                    assertEquals(SIZE-i-1, q.pollLast(LONG_DELAY_MS, MILLISECONDS));
                 }
 
                 Thread.currentThread().interrupt();
@@ -1342,15 +1341,12 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         await(pleaseInterrupt);
         assertThreadStaysAlive(t);
         t.interrupt();
         awaitTermination(t);
-        checkEmpty(q);
     }
 
     /**
@@ -1383,8 +1379,6 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         barrier.await();
@@ -1469,7 +1463,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -1482,7 +1476,7 @@
             LinkedBlockingDeque q = populatedDeque(SIZE);
             LinkedBlockingDeque p = populatedDeque(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -1681,23 +1675,23 @@
         final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
         q.add(one);
         q.add(two);
+        ExecutorService executor = Executors.newFixedThreadPool(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertFalse(q.offer(three));
-                    threadsStarted.await();
-                    assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
-                    assertEquals(0, q.remainingCapacity());
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(q.offer(three));
+                threadsStarted.await();
+                assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
+                assertEquals(0, q.remainingCapacity());
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    assertSame(one, q.take());
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertSame(one, q.take());
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -1706,22 +1700,22 @@
     public void testPollInExecutor() {
         final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    checkEmpty(q);
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -1773,7 +1767,7 @@
         final LinkedBlockingDeque q = populatedDeque(SIZE);
         Thread t = new Thread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                q.put(new Integer(SIZE + 1));
+                q.put(new Integer(SIZE+1));
             }});
 
         t.start();
@@ -1798,7 +1792,7 @@
             q.drainTo(l, i);
             int k = (i < SIZE) ? i : SIZE;
             assertEquals(k, l.size());
-            assertEquals(SIZE - k, q.size());
+            assertEquals(SIZE-k, q.size());
             for (int j = 0; j < k; ++j)
                 assertEquals(l.get(j), new Integer(j));
             do {} while (q.poll() != null);
diff --git a/jsr166-tests/src/test/java/jsr166/LinkedBlockingQueueTest.java b/jsr166-tests/src/test/java/jsr166/LinkedBlockingQueueTest.java
index faf3f18..bd37b2a 100644
--- a/jsr166-tests/src/test/java/jsr166/LinkedBlockingQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LinkedBlockingQueueTest.java
@@ -26,27 +26,25 @@
 
 public class LinkedBlockingQueueTest extends JSR166TestCase {
 
-    // android-note: These tests have been moved into their own separate
+    // android-note: These tests have been moved into their own separate 
     // classes to work around CTS issues.
     //
     // public static class Unbounded extends BlockingQueueTest {
-    //     protected BlockingQueue emptyCollection() {
-    //         return new LinkedBlockingQueue();
+    //    protected BlockingQueue emptyCollection() {
+    //        return new LinkedBlockingQueue();
     //     }
     // }
-
+    //
     // public static class Bounded extends BlockingQueueTest {
-    //     protected BlockingQueue emptyCollection() {
+    //    protected BlockingQueue emptyCollection() {
     //         return new LinkedBlockingQueue(SIZE);
     //     }
     // }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
     //
     // public static void main(String[] args) {
-    //     main(suite(), args);
+    //    main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(LinkedBlockingQueueTest.class,
     //                         new Unbounded().testSuite(),
@@ -115,7 +113,7 @@
      */
     public void testConstructor5() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -162,7 +160,7 @@
             assertEquals(i, q.remove());
         }
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.remainingCapacity());
+            assertEquals(SIZE-i, q.remainingCapacity());
             assertEquals(SIZE, q.size() + q.remainingCapacity());
             assertTrue(q.add(i));
         }
@@ -209,7 +207,7 @@
     public void testAddAll3() {
         LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -447,23 +445,25 @@
         final CountDownLatch aboutToWait = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
                 }
+                long t0 = System.nanoTime();
                 aboutToWait.countDown();
                 try {
-                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    q.poll(MEDIUM_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                    assertTrue(millisElapsedSince(t0) < MEDIUM_DELAY_MS);
                 }
             }});
 
-        await(aboutToWait);
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        aboutToWait.await();
+        waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
         t.interrupt();
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         checkEmpty(q);
     }
 
@@ -579,7 +579,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -592,7 +592,7 @@
             LinkedBlockingQueue q = populatedQueue(SIZE);
             LinkedBlockingQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -727,23 +727,23 @@
         final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
         q.add(one);
         q.add(two);
+        ExecutorService executor = Executors.newFixedThreadPool(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertFalse(q.offer(three));
-                    threadsStarted.await();
-                    assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
-                    assertEquals(0, q.remainingCapacity());
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(q.offer(three));
+                threadsStarted.await();
+                assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
+                assertEquals(0, q.remainingCapacity());
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    assertSame(one, q.take());
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertSame(one, q.take());
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -752,22 +752,22 @@
     public void testPollInExecutor() {
         final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    checkEmpty(q);
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -819,7 +819,7 @@
         final LinkedBlockingQueue q = populatedQueue(SIZE);
         Thread t = new Thread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                q.put(new Integer(SIZE + 1));
+                q.put(new Integer(SIZE+1));
             }});
 
         t.start();
@@ -844,7 +844,7 @@
             q.drainTo(l, i);
             int k = (i < SIZE) ? i : SIZE;
             assertEquals(k, l.size());
-            assertEquals(SIZE - k, q.size());
+            assertEquals(SIZE-k, q.size());
             for (int j = 0; j < k; ++j)
                 assertEquals(l.get(j), new Integer(j));
             do {} while (q.poll() != null);
diff --git a/jsr166-tests/src/test/java/jsr166/LinkedListTest.java b/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
index 9c971b4..9d9481d 100644
--- a/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
@@ -25,7 +25,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(LinkedListTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -91,7 +91,7 @@
     public void testSize() {
         LinkedList q = populatedQueue(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.remove();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -106,8 +106,6 @@
     public void testOfferNull() {
         LinkedList q = new LinkedList();
         q.offer(null);
-        assertNull(q.get(0));
-        assertTrue(q.contains(null));
     }
 
     /**
@@ -134,8 +132,8 @@
      * addAll(null) throws NPE
      */
     public void testAddAll1() {
-        LinkedList q = new LinkedList();
         try {
+            LinkedList q = new LinkedList();
             q.addAll(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -247,14 +245,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove((Integer)i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove((Integer)i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove((Integer)(i + 1)));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove((Integer)(i+1)));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -313,7 +311,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -326,7 +324,7 @@
             LinkedList q = populatedQueue(SIZE);
             LinkedList p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -551,7 +549,7 @@
      */
     public void testPollLast() {
         LinkedList q = populatedQueue(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollLast());
@@ -576,7 +574,7 @@
      */
     public void testPeekLast() {
         LinkedList q = populatedQueue(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.peekLast());
             assertEquals(i, q.pollLast());
             assertTrue(q.peekLast() == null ||
@@ -602,7 +600,7 @@
      */
     public void testLastElement() {
         LinkedList q = populatedQueue(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.getLast());
             assertEquals(i, q.pollLast());
         }
@@ -623,7 +621,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeFirstOccurrence(new Integer(i)));
-            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -638,7 +636,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.removeLastOccurrence(new Integer(i)));
-            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+            assertFalse(q.removeLastOccurrence(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
diff --git a/jsr166-tests/src/test/java/jsr166/LinkedTransferQueueTest.java b/jsr166-tests/src/test/java/jsr166/LinkedTransferQueueTest.java
index c712592..8d3f276 100644
--- a/jsr166-tests/src/test/java/jsr166/LinkedTransferQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LinkedTransferQueueTest.java
@@ -25,33 +25,30 @@
 import junit.framework.Test;
 
 @SuppressWarnings({"unchecked", "rawtypes"})
-public class LinkedTransferQueueTest extends JSR166TestCase {
-    static class Implementation implements CollectionImplementation {
-        public Class<?> klazz() { return LinkedTransferQueue.class; }
-        public Collection emptyCollection() { return new LinkedTransferQueue(); }
-        public Object makeElement(int i) { return i; }
-        public boolean isConcurrent() { return true; }
-        public boolean permitsNulls() { return false; }
-    }
+// android-changed: Extend BlockingQueueTest directly.
+public class LinkedTransferQueueTest extends BlockingQueueTest {
 
-    public static class Generic extends BlockingQueueTest {
-        protected BlockingQueue emptyCollection() {
-            return new LinkedTransferQueue();
-        }
-    }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
+    // android-changed: Extend BlockingQueueTest directly.
+    //
+    // public static class Generic extends BlockingQueueTest {
+    //     protected BlockingQueue emptyCollection() {
+    //         return new LinkedTransferQueue();
+    //     }
+    // }
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(LinkedTransferQueueTest.class,
-    //                         new Generic().testSuite(),
-    //                         CollectionTest.testSuite(new Implementation()));
+    //                         new Generic().testSuite());
     // }
 
+    protected BlockingQueue emptyCollection() {
+        return new LinkedTransferQueue();
+    }
+
     /**
      * Constructor builds new queue with size being zero and empty
      * being true
@@ -90,7 +87,7 @@
      */
     public void testConstructor4() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = i;
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -144,8 +141,8 @@
      * addAll(this) throws IllegalArgumentException
      */
     public void testAddAllSelf() {
-        LinkedTransferQueue q = populatedQueue(SIZE);
         try {
+            LinkedTransferQueue q = populatedQueue(SIZE);
             q.addAll(q);
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -156,11 +153,12 @@
      * NullPointerException after possibly adding some elements
      */
     public void testAddAll3() {
-        LinkedTransferQueue q = new LinkedTransferQueue();
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = i;
         try {
+            LinkedTransferQueue q = new LinkedTransferQueue();
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE - 1; ++i) {
+                ints[i] = i;
+            }
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -267,12 +265,12 @@
      */
     public void testTimedPoll() throws InterruptedException {
         LinkedTransferQueue<Integer> q = populatedQueue(SIZE);
-        long startTime = System.nanoTime();
-        for (int i = 0; i < SIZE; ++i)
+        for (int i = 0; i < SIZE; ++i) {
+            long startTime = System.nanoTime();
             assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-
-        startTime = System.nanoTime();
+            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        }
+        long startTime = System.nanoTime();
         assertNull(q.poll(timeoutMillis(), MILLISECONDS));
         assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
         checkEmpty(q);
@@ -287,21 +285,25 @@
         final CountDownLatch aboutToWait = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
-                for (int i = 0; i < SIZE; ++i)
+                for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
+                }
+                long t0 = System.nanoTime();
                 aboutToWait.countDown();
                 try {
-                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    q.poll(MEDIUM_DELAY_MS, MILLISECONDS);
                     shouldThrow();
-                } catch (InterruptedException success) {}
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                } catch (InterruptedException success) {
+                    assertTrue(millisElapsedSince(t0) < MEDIUM_DELAY_MS);
+                }
             }});
 
         aboutToWait.await();
-        waitForThreadToEnterWaitState(t);
+        waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
         t.interrupt();
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         checkEmpty(q);
     }
 
@@ -313,18 +315,19 @@
         final BlockingQueue<Integer> q = populatedQueue(SIZE);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 Thread.currentThread().interrupt();
-                for (int i = 0; i < SIZE; ++i)
+                for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
+                }
                 try {
-                    q.poll(LONG_DELAY_MS, MILLISECONDS);
+                    q.poll(MEDIUM_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {}
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         checkEmpty(q);
     }
 
@@ -595,24 +598,22 @@
     public void testOfferInExecutor() {
         final LinkedTransferQueue q = new LinkedTransferQueue();
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
+        ExecutorService executor = Executors.newFixedThreadPool(2);
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    long startTime = System.nanoTime();
-                    assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS));
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS));
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    assertSame(one, q.take());
-                    checkEmpty(q);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertSame(one, q.take());
+                checkEmpty(q);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -621,25 +622,23 @@
     public void testPollInExecutor() {
         final LinkedTransferQueue q = new LinkedTransferQueue();
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
+        ExecutorService executor = Executors.newFixedThreadPool(2);
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    long startTime = System.nanoTime();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
-                    checkEmpty(q);
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -700,7 +699,7 @@
         assertTrue(l.size() >= SIZE);
         for (int i = 0; i < SIZE; ++i)
             assertEquals(i, l.get(i));
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
         assertTrue(q.size() + l.size() >= SIZE);
     }
 
@@ -737,15 +736,14 @@
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
                 threadStarted.countDown();
-                long startTime = System.nanoTime();
                 assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
                 assertEquals(0, q.getWaitingConsumerCount());
                 assertFalse(q.hasWaitingConsumer());
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         threadStarted.await();
-        waitForThreadToEnterWaitState(t);
+        // waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
+        waitForThreadToEnterWaitStateNoTimeout(t);
         assertEquals(1, q.getWaitingConsumerCount());
         assertTrue(q.hasWaitingConsumer());
 
@@ -753,7 +751,7 @@
         assertEquals(0, q.getWaitingConsumerCount());
         assertFalse(q.hasWaitingConsumer());
 
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -784,11 +782,12 @@
             }});
 
         threadStarted.await();
-        waitForThreadToEnterWaitState(t);
+        // waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
+        waitForThreadToEnterWaitStateNoTimeout(t);
         assertEquals(1, q.size());
         assertSame(five, q.poll());
         checkEmpty(q);
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -844,7 +843,7 @@
         assertEquals(1, q.size());
         assertTrue(q.offer(three));
         assertSame(four, q.poll());
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -867,15 +866,15 @@
         assertEquals(1, q.size());
         assertSame(four, q.take());
         checkEmpty(q);
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
      * tryTransfer(null) throws NullPointerException
      */
     public void testTryTransfer1() {
-        final LinkedTransferQueue q = new LinkedTransferQueue();
         try {
+            final LinkedTransferQueue q = new LinkedTransferQueue();
             q.tryTransfer(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -909,11 +908,9 @@
                 assertTrue(q.tryTransfer(hotPotato));
             }});
 
-        long startTime = System.nanoTime();
-        assertSame(hotPotato, q.poll(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        assertSame(hotPotato, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
         checkEmpty(q);
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -935,7 +932,7 @@
 
         assertSame(q.take(), hotPotato);
         checkEmpty(q);
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -948,7 +945,6 @@
 
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 Thread.currentThread().interrupt();
                 try {
                     q.tryTransfer(new Object(), LONG_DELAY_MS, MILLISECONDS);
@@ -962,7 +958,6 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         await(pleaseInterrupt);
@@ -980,10 +975,10 @@
 
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
+                long t0 = System.nanoTime();
                 assertFalse(q.tryTransfer(new Object(),
                                           timeoutMillis(), MILLISECONDS));
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+                assertTrue(millisElapsedSince(t0) >= timeoutMillis());
                 checkEmpty(q);
             }});
 
@@ -1001,9 +996,7 @@
 
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
-                assertTrue(q.tryTransfer(five, LONG_DELAY_MS, MILLISECONDS));
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                assertTrue(q.tryTransfer(five, MEDIUM_DELAY_MS, MILLISECONDS));
                 checkEmpty(q);
             }});
 
@@ -1013,7 +1006,7 @@
         assertSame(four, q.poll());
         assertSame(five, q.poll());
         checkEmpty(q);
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -1024,9 +1017,9 @@
         final LinkedTransferQueue q = new LinkedTransferQueue();
         assertTrue(q.offer(four));
         assertEquals(1, q.size());
-        long startTime = System.nanoTime();
+        long t0 = System.nanoTime();
         assertFalse(q.tryTransfer(five, timeoutMillis(), MILLISECONDS));
-        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        assertTrue(millisElapsedSince(t0) >= timeoutMillis());
         assertEquals(1, q.size());
         assertSame(four, q.poll());
         assertNull(q.poll());
diff --git a/jsr166-tests/src/test/java/jsr166/LockSupportTest.java b/jsr166-tests/src/test/java/jsr166/LockSupportTest.java
index b3a8ed8..8347b08 100644
--- a/jsr166-tests/src/test/java/jsr166/LockSupportTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LockSupportTest.java
@@ -26,15 +26,9 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(LockSupportTest.class);
+    //     return new TestSuite(...);
     // }
 
-    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;
-    }
-
     /**
      * Returns the blocker object used by tests in this file.
      * Any old object will do; we'll return a convenient one.
diff --git a/jsr166-tests/src/test/java/jsr166/LongAccumulatorTest.java b/jsr166-tests/src/test/java/jsr166/LongAccumulatorTest.java
deleted file mode 100644
index 5dd52e9..0000000
--- a/jsr166-tests/src/test/java/jsr166/LongAccumulatorTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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 jsr166;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Phaser;
-import java.util.concurrent.atomic.LongAccumulator;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class LongAccumulatorTest extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(LongAccumulatorTest.class);
-    // }
-
-    /**
-     * default constructed initializes to zero
-     */
-    public void testConstructor() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals(0, ai.get());
-    }
-
-    /**
-     * accumulate accumulates given value to current, and get returns current value
-     */
-    public void testAccumulateAndGet() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        ai.accumulate(2);
-        assertEquals(2, ai.get());
-        ai.accumulate(-4);
-        assertEquals(2, ai.get());
-        ai.accumulate(4);
-        assertEquals(4, ai.get());
-    }
-
-    /**
-     * reset() causes subsequent get() to return zero
-     */
-    public void testReset() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        ai.accumulate(2);
-        assertEquals(2, ai.get());
-        ai.reset();
-        assertEquals(0, ai.get());
-    }
-
-    /**
-     * getThenReset() returns current value; subsequent get() returns zero
-     */
-    public void testGetThenReset() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        ai.accumulate(2);
-        assertEquals(2, ai.get());
-        assertEquals(2, ai.getThenReset());
-        assertEquals(0, ai.get());
-    }
-
-    /**
-     * toString returns current value.
-     */
-    public void testToString() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals("0", ai.toString());
-        ai.accumulate(1);
-        assertEquals(Long.toString(1), ai.toString());
-    }
-
-    /**
-     * intValue returns current value.
-     */
-    public void testIntValue() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals(0, ai.intValue());
-        ai.accumulate(1);
-        assertEquals(1, ai.intValue());
-    }
-
-    /**
-     * longValue returns current value.
-     */
-    public void testLongValue() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals(0, ai.longValue());
-        ai.accumulate(1);
-        assertEquals(1, ai.longValue());
-    }
-
-    /**
-     * floatValue returns current value.
-     */
-    public void testFloatValue() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals(0.0f, ai.floatValue());
-        ai.accumulate(1);
-        assertEquals(1.0f, ai.floatValue());
-    }
-
-    /**
-     * doubleValue returns current value.
-     */
-    public void testDoubleValue() {
-        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
-        assertEquals(0.0, ai.doubleValue());
-        ai.accumulate(1);
-        assertEquals(1.0, ai.doubleValue());
-    }
-
-    /**
-     * accumulates by multiple threads produce correct result
-     */
-    public void testAccumulateAndGetMT() {
-        final int incs = 1000000;
-        final int nthreads = 4;
-        final ExecutorService pool = Executors.newCachedThreadPool();
-        LongAccumulator a = new LongAccumulator(Long::max, 0L);
-        Phaser phaser = new Phaser(nthreads + 1);
-        for (int i = 0; i < nthreads; ++i)
-            pool.execute(new AccTask(a, phaser, incs));
-        phaser.arriveAndAwaitAdvance();
-        phaser.arriveAndAwaitAdvance();
-        long expected = incs - 1;
-        long result = a.get();
-        assertEquals(expected, result);
-        pool.shutdown();
-    }
-
-    static final class AccTask implements Runnable {
-        final LongAccumulator acc;
-        final Phaser phaser;
-        final int incs;
-        volatile long result;
-        AccTask(LongAccumulator acc, Phaser phaser, int incs) {
-            this.acc = acc;
-            this.phaser = phaser;
-            this.incs = incs;
-        }
-
-        public void run() {
-            phaser.arriveAndAwaitAdvance();
-            LongAccumulator a = acc;
-            for (int i = 0; i < incs; ++i)
-                a.accumulate(i);
-            result = a.get();
-            phaser.arrive();
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/LongAdderTest.java b/jsr166-tests/src/test/java/jsr166/LongAdderTest.java
deleted file mode 100644
index 800a9c8..0000000
--- a/jsr166-tests/src/test/java/jsr166/LongAdderTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 jsr166;
-
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.LongAdder;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class LongAdderTest extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(LongAdderTest.class);
-    // }
-
-    /**
-     * default constructed initializes to zero
-     */
-    public void testConstructor() {
-        LongAdder ai = new LongAdder();
-        assertEquals(0, ai.sum());
-    }
-
-    /**
-     * add adds given value to current, and sum returns current value
-     */
-    public void testAddAndSum() {
-        LongAdder ai = new LongAdder();
-        ai.add(2);
-        assertEquals(2, ai.sum());
-        ai.add(-4);
-        assertEquals(-2, ai.sum());
-    }
-
-    /**
-     * decrement decrements and sum returns current value
-     */
-    public void testDecrementAndsum() {
-        LongAdder ai = new LongAdder();
-        ai.decrement();
-        assertEquals(-1, ai.sum());
-        ai.decrement();
-        assertEquals(-2, ai.sum());
-    }
-
-    /**
-     * incrementAndGet increments and returns current value
-     */
-    public void testIncrementAndsum() {
-        LongAdder ai = new LongAdder();
-        ai.increment();
-        assertEquals(1, ai.sum());
-        ai.increment();
-        assertEquals(2, ai.sum());
-    }
-
-    /**
-     * reset() causes subsequent sum() to return zero
-     */
-    public void testReset() {
-        LongAdder ai = new LongAdder();
-        ai.add(2);
-        assertEquals(2, ai.sum());
-        ai.reset();
-        assertEquals(0, ai.sum());
-    }
-
-    /**
-     * sumThenReset() returns sum; subsequent sum() returns zero
-     */
-    public void testSumThenReset() {
-        LongAdder ai = new LongAdder();
-        ai.add(2);
-        assertEquals(2, ai.sum());
-        assertEquals(2, ai.sumThenReset());
-        assertEquals(0, ai.sum());
-    }
-
-    /**
-     * a deserialized serialized adder holds same value
-     */
-    public void testSerialization() throws Exception {
-        LongAdder x = new LongAdder();
-        LongAdder y = serialClone(x);
-        assertNotSame(x, y);
-        x.add(-22);
-        LongAdder z = serialClone(x);
-        assertNotSame(y, z);
-        assertEquals(-22, x.sum());
-        assertEquals(0, y.sum());
-        assertEquals(-22, z.sum());
-    }
-
-    /**
-     * toString returns current value.
-     */
-    public void testToString() {
-        LongAdder ai = new LongAdder();
-        assertEquals("0", ai.toString());
-        ai.increment();
-        assertEquals(Long.toString(1), ai.toString());
-    }
-
-    /**
-     * intValue returns current value.
-     */
-    public void testIntValue() {
-        LongAdder ai = new LongAdder();
-        assertEquals(0, ai.intValue());
-        ai.increment();
-        assertEquals(1, ai.intValue());
-    }
-
-    /**
-     * longValue returns current value.
-     */
-    public void testLongValue() {
-        LongAdder ai = new LongAdder();
-        assertEquals(0, ai.longValue());
-        ai.increment();
-        assertEquals(1, ai.longValue());
-    }
-
-    /**
-     * floatValue returns current value.
-     */
-    public void testFloatValue() {
-        LongAdder ai = new LongAdder();
-        assertEquals(0.0f, ai.floatValue());
-        ai.increment();
-        assertEquals(1.0f, ai.floatValue());
-    }
-
-    /**
-     * doubleValue returns current value.
-     */
-    public void testDoubleValue() {
-        LongAdder ai = new LongAdder();
-        assertEquals(0.0, ai.doubleValue());
-        ai.increment();
-        assertEquals(1.0, ai.doubleValue());
-    }
-
-    /**
-     * adds by multiple threads produce correct sum
-     */
-    public void testAddAndSumMT() throws Throwable {
-        final int incs = 1000000;
-        final int nthreads = 4;
-        final ExecutorService pool = Executors.newCachedThreadPool();
-        LongAdder a = new LongAdder();
-        CyclicBarrier barrier = new CyclicBarrier(nthreads + 1);
-        for (int i = 0; i < nthreads; ++i)
-            pool.execute(new AdderTask(a, barrier, incs));
-        barrier.await();
-        barrier.await();
-        long total = (long)nthreads * incs;
-        long sum = a.sum();
-        assertEquals(sum, total);
-        pool.shutdown();
-    }
-
-    static final class AdderTask implements Runnable {
-        final LongAdder adder;
-        final CyclicBarrier barrier;
-        final int incs;
-        volatile long result;
-        AdderTask(LongAdder adder, CyclicBarrier barrier, int incs) {
-            this.adder = adder;
-            this.barrier = barrier;
-            this.incs = incs;
-        }
-
-        public void run() {
-            try {
-                barrier.await();
-                LongAdder a = adder;
-                for (int i = 0; i < incs; ++i)
-                    a.add(1L);
-                result = a.sum();
-                barrier.await();
-            } catch (Throwable t) { throw new Error(t); }
-        }
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/PhaserTest.java b/jsr166-tests/src/test/java/jsr166/PhaserTest.java
index 673e556..42d72f4 100644
--- a/jsr166-tests/src/test/java/jsr166/PhaserTest.java
+++ b/jsr166-tests/src/test/java/jsr166/PhaserTest.java
@@ -28,7 +28,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(PhaserTest.class);
+    //     return new TestSuite(...);
     // }
 
     private static final int maxParties = 65535;
@@ -342,8 +342,8 @@
      * registered or unarrived parties would become negative
      */
     public void testArriveAndDeregister1() {
-        Phaser phaser = new Phaser();
         try {
+            Phaser phaser = new Phaser();
             phaser.arriveAndDeregister();
             shouldThrow();
         } catch (IllegalStateException success) {}
@@ -629,11 +629,11 @@
             threads.add(newStartedThread(new CheckedRunnable() {
                 public void realRun() {
                     for (int k = 0; k < 3; k++) {
-                        assertEquals(2 * k + 1, phaser.arriveAndAwaitAdvance());
+                        assertEquals(2*k+1, phaser.arriveAndAwaitAdvance());
                         count.incrementAndGet();
-                        assertEquals(2 * k + 1, phaser.arrive());
-                        assertEquals(2 * k + 2, phaser.awaitAdvance(2 * k + 1));
-                        assertEquals(4 * (k + 1), count.get());
+                        assertEquals(2*k+1, phaser.arrive());
+                        assertEquals(2*k+2, phaser.awaitAdvance(2*k+1));
+                        assertEquals(4*(k+1), count.get());
                     }}}));
 
         for (Thread thread : threads)
@@ -689,7 +689,7 @@
         for (Phaser phaser : phasers) {
             assertEquals(-42, phaser.awaitAdvance(-42));
             assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42));
-            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS));
         }
 
         for (Phaser child : onePartyChildren)
@@ -697,10 +697,10 @@
         for (Phaser phaser : phasers) {
             assertEquals(-42, phaser.awaitAdvance(-42));
             assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42));
-            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, phaser.awaitAdvance(0));
             assertEquals(1, phaser.awaitAdvanceInterruptibly(0));
-            assertEquals(1, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(1, phaser.awaitAdvanceInterruptibly(0, SMALL_DELAY_MS, MILLISECONDS));
         }
 
         for (Phaser child : onePartyChildren)
@@ -708,13 +708,13 @@
         for (Phaser phaser : phasers) {
             assertEquals(-42, phaser.awaitAdvance(-42));
             assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42));
-            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(2, phaser.awaitAdvance(0));
             assertEquals(2, phaser.awaitAdvanceInterruptibly(0));
-            assertEquals(2, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(2, phaser.awaitAdvanceInterruptibly(0, SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(2, phaser.awaitAdvance(1));
             assertEquals(2, phaser.awaitAdvanceInterruptibly(1));
-            assertEquals(2, phaser.awaitAdvanceInterruptibly(1, MEDIUM_DELAY_MS, MILLISECONDS));
+            assertEquals(2, phaser.awaitAdvanceInterruptibly(1, SMALL_DELAY_MS, MILLISECONDS));
         }
     }
 
@@ -752,8 +752,8 @@
      * unarrived parties
      */
     public void testArriveAndAwaitAdvance1() {
-        Phaser phaser = new Phaser();
         try {
+            Phaser phaser = new Phaser();
             phaser.arriveAndAwaitAdvance();
             shouldThrow();
         } catch (IllegalStateException success) {}
diff --git a/jsr166-tests/src/test/java/jsr166/PriorityBlockingQueueTest.java b/jsr166-tests/src/test/java/jsr166/PriorityBlockingQueueTest.java
index 41b06f5..64c3b3a 100644
--- a/jsr166-tests/src/test/java/jsr166/PriorityBlockingQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/PriorityBlockingQueueTest.java
@@ -27,7 +27,7 @@
 
 public class PriorityBlockingQueueTest extends JSR166TestCase {
 
-    // android-note: These tests have been moved into their own separate
+    // android-note: These tests have been moved into their own separate 
     // classes to work around CTS issues.
     //
     // public static class Generic extends BlockingQueueTest {
@@ -35,19 +35,17 @@
     //         return new PriorityBlockingQueue();
     //     }
     // }
-
+    //
     // public static class InitialCapacity extends BlockingQueueTest {
     //     protected BlockingQueue emptyCollection() {
     //         return new PriorityBlockingQueue(SIZE);
     //     }
     // }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(PriorityBlockingQueueTest.class,
     //                         new Generic().testSuite(),
@@ -69,7 +67,7 @@
         PriorityBlockingQueue<Integer> q =
             new PriorityBlockingQueue<Integer>(n);
         assertTrue(q.isEmpty());
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.offer(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.offer(new Integer(i)));
@@ -123,7 +121,7 @@
      */
     public void testConstructor5() {
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = i;
         Collection<Integer> elements = Arrays.asList(ints);
         try {
@@ -155,7 +153,7 @@
         for (int i = 0; i < SIZE; ++i)
             ints[i] = new Integer(i);
         q.addAll(Arrays.asList(ints));
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             assertEquals(ints[i], q.poll());
     }
 
@@ -227,8 +225,8 @@
      * addAll(this) throws IAE
      */
     public void testAddAllSelf() {
-        PriorityBlockingQueue q = populatedQueue(SIZE);
         try {
+            PriorityBlockingQueue q = populatedQueue(SIZE);
             q.addAll(q);
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -239,11 +237,11 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -255,7 +253,7 @@
     public void testAddAll5() {
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             ints[i] = new Integer(i);
         PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
         assertFalse(q.addAll(Arrays.asList(empty)));
@@ -400,23 +398,25 @@
         final CountDownLatch aboutToWait = new CountDownLatch(1);
         Thread t = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
                 for (int i = 0; i < SIZE; ++i) {
+                    long t0 = System.nanoTime();
                     assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+                    assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS);
                 }
+                long t0 = System.nanoTime();
                 aboutToWait.countDown();
                 try {
                     q.poll(LONG_DELAY_MS, MILLISECONDS);
                     shouldThrow();
                 } catch (InterruptedException success) {
-                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+                    assertTrue(millisElapsedSince(t0) < MEDIUM_DELAY_MS);
                 }
             }});
 
         aboutToWait.await();
-        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+        waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
         t.interrupt();
-        awaitTermination(t);
+        awaitTermination(t, MEDIUM_DELAY_MS);
     }
 
     /**
@@ -517,7 +517,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -530,7 +530,7 @@
             PriorityBlockingQueue q = populatedQueue(SIZE);
             PriorityBlockingQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
@@ -629,22 +629,22 @@
     public void testPollInExecutor() {
         final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    checkEmpty(q);
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                checkEmpty(q);
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -694,7 +694,7 @@
         final PriorityBlockingQueue q = populatedQueue(SIZE);
         Thread t = new Thread(new CheckedRunnable() {
             public void realRun() {
-                q.put(new Integer(SIZE + 1));
+                q.put(new Integer(SIZE+1));
             }});
 
         t.start();
@@ -711,7 +711,7 @@
      * drainTo(c, n) empties first min(n, size) elements of queue into c
      */
     public void testDrainToN() {
-        PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE * 2);
+        PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE*2);
         for (int i = 0; i < SIZE + 2; ++i) {
             for (int j = 0; j < SIZE; j++)
                 assertTrue(q.offer(new Integer(j)));
@@ -719,7 +719,7 @@
             q.drainTo(l, i);
             int k = (i < SIZE) ? i : SIZE;
             assertEquals(k, l.size());
-            assertEquals(SIZE - k, q.size());
+            assertEquals(SIZE-k, q.size());
             for (int j = 0; j < k; ++j)
                 assertEquals(l.get(j), new Integer(j));
             do {} while (q.poll() != null);
diff --git a/jsr166-tests/src/test/java/jsr166/PriorityQueueTest.java b/jsr166-tests/src/test/java/jsr166/PriorityQueueTest.java
index f64ef68..88cdd37 100644
--- a/jsr166-tests/src/test/java/jsr166/PriorityQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/PriorityQueueTest.java
@@ -27,7 +27,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(PriorityQueueTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyReverseComparator implements Comparator {
@@ -43,7 +43,7 @@
     private PriorityQueue<Integer> populatedQueue(int n) {
         PriorityQueue<Integer> q = new PriorityQueue<Integer>(n);
         assertTrue(q.isEmpty());
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.offer(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.offer(new Integer(i)));
@@ -84,7 +84,8 @@
      */
     public void testConstructor4() {
         try {
-            new PriorityQueue(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new PriorityQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -93,10 +94,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new PriorityQueue(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -125,7 +126,7 @@
         for (int i = 0; i < SIZE; ++i)
             ints[i] = new Integer(i);
         q.addAll(Arrays.asList(ints));
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             assertEquals(ints[i], q.poll());
     }
 
@@ -149,7 +150,7 @@
     public void testSize() {
         PriorityQueue q = populatedQueue(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.remove();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -162,8 +163,8 @@
      * offer(null) throws NPE
      */
     public void testOfferNull() {
-        PriorityQueue q = new PriorityQueue(1);
         try {
+            PriorityQueue q = new PriorityQueue(1);
             q.offer(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -173,8 +174,8 @@
      * add(null) throws NPE
      */
     public void testAddNull() {
-        PriorityQueue q = new PriorityQueue(1);
         try {
+            PriorityQueue q = new PriorityQueue(1);
             q.add(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -216,8 +217,8 @@
      * addAll(null) throws NPE
      */
     public void testAddAll1() {
-        PriorityQueue q = new PriorityQueue(1);
         try {
+            PriorityQueue q = new PriorityQueue(1);
             q.addAll(null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -227,9 +228,10 @@
      * addAll of a collection with null elements throws NPE
      */
     public void testAddAll2() {
-        PriorityQueue q = new PriorityQueue(SIZE);
         try {
-            q.addAll(Arrays.asList(new Integer[SIZE]));
+            PriorityQueue q = new PriorityQueue(SIZE);
+            Integer[] ints = new Integer[SIZE];
+            q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -239,11 +241,11 @@
      * possibly adding some elements
      */
     public void testAddAll3() {
-        PriorityQueue q = new PriorityQueue(SIZE);
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            PriorityQueue q = new PriorityQueue(SIZE);
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             q.addAll(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -256,7 +258,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1-i);
         PriorityQueue q = new PriorityQueue(SIZE);
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -327,14 +329,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -393,7 +395,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.remove();
         }
     }
@@ -406,7 +408,7 @@
             PriorityQueue q = populatedQueue(SIZE);
             PriorityQueue p = populatedQueue(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.remove());
                 assertFalse(q.contains(x));
diff --git a/jsr166-tests/src/test/java/jsr166/RecursiveActionTest.java b/jsr166-tests/src/test/java/jsr166/RecursiveActionTest.java
index c8e33be..1c3bba8 100644
--- a/jsr166-tests/src/test/java/jsr166/RecursiveActionTest.java
+++ b/jsr166-tests/src/test/java/jsr166/RecursiveActionTest.java
@@ -32,7 +32,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(RecursiveActionTest.class);
+    //     return new TestSuite(...);
     // }
 
     private static ForkJoinPool mainPool() {
@@ -50,12 +50,14 @@
     }
 
     private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
-        try (PoolCleaner cleaner = cleaner(pool)) {
+        try {
             checkNotDone(a);
 
             assertNull(pool.invoke(a));
 
             checkCompletedNormally(a);
+        } finally {
+            joinPool(pool);
         }
     }
 
@@ -427,12 +429,12 @@
 
         t = newStartedThread(r);
         testInvokeOnPool(mainPool(), a);
-        awaitTermination(t);
+        awaitTermination(t, LONG_DELAY_MS);
 
         a.reinitialize();
         t = newStartedThread(r);
         testInvokeOnPool(singletonPool(), a);
-        awaitTermination(t);
+        awaitTermination(t, LONG_DELAY_MS);
     }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/RecursiveTaskTest.java b/jsr166-tests/src/test/java/jsr166/RecursiveTaskTest.java
index 2c07c2a..7783370 100644
--- a/jsr166-tests/src/test/java/jsr166/RecursiveTaskTest.java
+++ b/jsr166-tests/src/test/java/jsr166/RecursiveTaskTest.java
@@ -28,7 +28,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(RecursiveTaskTest.class);
+    //     return new TestSuite(...);
     // }
 
     private static ForkJoinPool mainPool() {
@@ -46,13 +46,15 @@
     }
 
     private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
-        try (PoolCleaner cleaner = cleaner(pool)) {
+        try {
             checkNotDone(a);
 
             T result = pool.invoke(a);
 
             checkCompletedNormally(a, result);
             return result;
+        } finally {
+            joinPool(pool);
         }
     }
 
@@ -333,8 +335,6 @@
                 FibTask f = new FibTask(8);
                 assertSame(f, f.fork());
                 helpQuiesce();
-                while (!f.isDone()) // wait out race
-                    ;
                 assertEquals(0, getQueuedTaskCount());
                 checkCompletedNormally(f, 21);
                 return NoResult;
diff --git a/jsr166-tests/src/test/java/jsr166/ReentrantLockTest.java b/jsr166-tests/src/test/java/jsr166/ReentrantLockTest.java
index 0024ff3..17eaf76 100644
--- a/jsr166-tests/src/test/java/jsr166/ReentrantLockTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ReentrantLockTest.java
@@ -30,9 +30,8 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ReentrantLockTest.class);
+    //     return new TestSuite(...);
     // }
-
     /**
      * A checked runnable calling lockInterruptibly
      */
@@ -151,7 +150,7 @@
     enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
 
     /**
-     * Awaits condition "indefinitely" using the specified AwaitMethod.
+     * Awaits condition using the specified AwaitMethod.
      */
     void await(Condition c, AwaitMethod awaitMethod)
             throws InterruptedException {
@@ -164,10 +163,9 @@
             assertTrue(c.await(timeoutMillis, MILLISECONDS));
             break;
         case awaitNanos:
-            long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
-            long nanosRemaining = c.awaitNanos(timeoutNanos);
-            assertTrue(nanosRemaining > timeoutNanos / 2);
-            assertTrue(nanosRemaining <= timeoutNanos);
+            long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+            long nanosRemaining = c.awaitNanos(nanosTimeout);
+            assertTrue(nanosRemaining > 0);
             break;
         case awaitUntil:
             assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
@@ -430,7 +428,7 @@
         }
         for (int i = SIZE; i > 0; i--) {
             lock.unlock();
-            assertEquals(i - 1, lock.getHoldCount());
+            assertEquals(i-1, lock.getHoldCount());
         }
     }
 
@@ -570,11 +568,11 @@
             final ReentrantLock lock = new ReentrantLock(fair);
             final Condition c = lock.newCondition();
             lock.lock();
-            // We shouldn't assume that nanoTime and currentTimeMillis
-            // use the same time source, so don't use nanoTime here.
-            java.util.Date delayedDate = delayedDate(timeoutMillis());
-            assertFalse(c.awaitUntil(delayedDate));
-            assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+            long startTime = System.nanoTime();
+            long timeoutMillis = 10;
+            java.util.Date d = new java.util.Date();
+            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + timeoutMillis)));
+            assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
             lock.unlock();
         } catch (InterruptedException fail) { threadUnexpectedException(fail); }
     }
diff --git a/jsr166-tests/src/test/java/jsr166/ReentrantReadWriteLockTest.java b/jsr166-tests/src/test/java/jsr166/ReentrantReadWriteLockTest.java
index 918f45d..7ef8ea3 100644
--- a/jsr166-tests/src/test/java/jsr166/ReentrantReadWriteLockTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ReentrantReadWriteLockTest.java
@@ -31,7 +31,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ReentrantReadWriteLockTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
@@ -160,26 +160,24 @@
     enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
 
     /**
-     * Awaits condition "indefinitely" using the specified AwaitMethod.
+     * Awaits condition using the specified AwaitMethod.
      */
     void await(Condition c, AwaitMethod awaitMethod)
             throws InterruptedException {
-        long timeoutMillis = 2 * LONG_DELAY_MS;
         switch (awaitMethod) {
         case await:
             c.await();
             break;
         case awaitTimed:
-            assertTrue(c.await(timeoutMillis, MILLISECONDS));
+            assertTrue(c.await(2 * LONG_DELAY_MS, MILLISECONDS));
             break;
         case awaitNanos:
-            long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
-            long nanosRemaining = c.awaitNanos(timeoutNanos);
-            assertTrue(nanosRemaining > timeoutNanos / 2);
-            assertTrue(nanosRemaining <= timeoutNanos);
+            long nanosRemaining = c.awaitNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
+            assertTrue(nanosRemaining > 0);
             break;
         case awaitUntil:
-            assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
+            java.util.Date d = new java.util.Date();
+            assertTrue(c.awaitUntil(new java.util.Date(d.getTime() + 2 * LONG_DELAY_MS)));
             break;
         default:
             throw new AssertionError();
@@ -243,7 +241,7 @@
         }
         for (int i = SIZE; i > 0; i--) {
             lock.writeLock().unlock();
-            assertEquals(i - 1,lock.getWriteHoldCount());
+            assertEquals(i-1,lock.getWriteHoldCount());
         }
     }
 
@@ -260,7 +258,7 @@
         }
         for (int i = SIZE; i > 0; i--) {
             lock.writeLock().unlock();
-            assertEquals(i - 1,lock.writeLock().getHoldCount());
+            assertEquals(i-1,lock.writeLock().getHoldCount());
         }
     }
 
@@ -277,7 +275,7 @@
         }
         for (int i = SIZE; i > 0; i--) {
             lock.readLock().unlock();
-            assertEquals(i - 1,lock.getReadHoldCount());
+            assertEquals(i-1,lock.getReadHoldCount());
         }
     }
 
@@ -974,11 +972,11 @@
                 new ReentrantReadWriteLock(fair);
             final Condition c = lock.writeLock().newCondition();
             lock.writeLock().lock();
-            // We shouldn't assume that nanoTime and currentTimeMillis
-            // use the same time source, so don't use nanoTime here.
-            java.util.Date delayedDate = delayedDate(timeoutMillis());
-            assertFalse(c.awaitUntil(delayedDate));
-            assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+            long startTime = System.nanoTime();
+            long timeoutMillis = 10;
+            java.util.Date d = new java.util.Date();
+            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + timeoutMillis)));
+            assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
             lock.writeLock().unlock();
         } catch (InterruptedException fail) { threadUnexpectedException(fail); }
     }
diff --git a/jsr166-tests/src/test/java/jsr166/ScheduledExecutorSubclassTest.java b/jsr166-tests/src/test/java/jsr166/ScheduledExecutorSubclassTest.java
index 194dd58..a93feea 100644
--- a/jsr166-tests/src/test/java/jsr166/ScheduledExecutorSubclassTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ScheduledExecutorSubclassTest.java
@@ -7,15 +7,11 @@
 package jsr166;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Delayed;
 import java.util.concurrent.ExecutionException;
@@ -31,9 +27,7 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -46,7 +40,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ScheduledExecutorSubclassTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class CustomTask<V> implements RunnableScheduledFuture<V> {
@@ -107,13 +101,17 @@
      * execute successfully executes a runnable
      */
     public void testExecute() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Runnable task = new CheckedRunnable() {
-                public void realRun() { done.countDown(); }};
+        CustomExecutor p = new CustomExecutor(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        final Runnable task = new CheckedRunnable() {
+            public void realRun() {
+                done.countDown();
+            }};
+        try {
             p.execute(task);
-            await(done);
+            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -121,10 +119,10 @@
      * delayed schedule of callable successfully executes after delay
      */
     public void testSchedule1() throws Exception {
+        CustomExecutor p = new CustomExecutor(1);
+        final long startTime = System.nanoTime();
         final CountDownLatch done = new CountDownLatch(1);
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final long startTime = System.nanoTime();
+        try {
             Callable task = new CheckedCallable<Boolean>() {
                 public Boolean realCall() {
                     done.countDown();
@@ -134,6 +132,9 @@
             Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
             assertSame(Boolean.TRUE, f.get());
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+            assertTrue(done.await(0L, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -141,10 +142,10 @@
      * delayed schedule of runnable successfully executes after delay
      */
     public void testSchedule3() throws Exception {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        CustomExecutor p = new CustomExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -154,6 +155,8 @@
             await(done);
             assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -161,10 +164,10 @@
      * scheduleAtFixedRate executes runnable after given initial delay
      */
     public void testSchedule4() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        CustomExecutor p = new CustomExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -176,6 +179,8 @@
             await(done);
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
             f.cancel(true);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -183,10 +188,10 @@
      * scheduleWithFixedDelay executes runnable after given initial delay
      */
     public void testSchedule5() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        CustomExecutor p = new CustomExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -198,6 +203,8 @@
             await(done);
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
             f.cancel(true);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -207,77 +214,58 @@
     }
 
     /**
-     * scheduleAtFixedRate executes series of tasks at given rate.
-     * Eventually, it must hold that:
-     *   cycles - 1 <= elapsedMillis/delay < cycles
+     * scheduleAtFixedRate executes series of tasks at given rate
      */
     public void testFixedRateSequence() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        CustomExecutor p = new CustomExecutor(1);
+        try {
             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
-                final long startTime = System.nanoTime();
-                final int cycles = 8;
+                long startTime = System.nanoTime();
+                int cycles = 10;
                 final CountDownLatch done = new CountDownLatch(cycles);
-                final Runnable task = new CheckedRunnable() {
+                Runnable task = new CheckedRunnable() {
                     public void realRun() { done.countDown(); }};
-                final ScheduledFuture periodicTask =
+                ScheduledFuture h =
                     p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
-                final int totalDelayMillis = (cycles - 1) * delay;
-                await(done, totalDelayMillis + LONG_DELAY_MS);
-                periodicTask.cancel(true);
-                final long elapsedMillis = millisElapsedSince(startTime);
-                assertTrue(elapsedMillis >= totalDelayMillis);
-                if (elapsedMillis <= cycles * delay)
+                done.await();
+                h.cancel(true);
+                double normalizedTime =
+                    (double) millisElapsedSince(startTime) / delay;
+                if (normalizedTime >= cycles - 1 &&
+                    normalizedTime <= cycles)
                     return;
-                // else retry with longer delay
             }
-            fail("unexpected execution rate");
+            throw new AssertionError("unexpected execution rate");
+        } finally {
+            joinPool(p);
         }
     }
 
     /**
-     * scheduleWithFixedDelay executes series of tasks with given period.
-     * Eventually, it must hold that each task starts at least delay and at
-     * most 2 * delay after the termination of the previous task.
+     * scheduleWithFixedDelay executes series of tasks with given period
      */
     public void testFixedDelaySequence() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        CustomExecutor p = new CustomExecutor(1);
+        try {
             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
-                final long startTime = System.nanoTime();
-                final AtomicLong previous = new AtomicLong(startTime);
-                final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
-                final int cycles = 8;
+                long startTime = System.nanoTime();
+                int cycles = 10;
                 final CountDownLatch done = new CountDownLatch(cycles);
-                final int d = delay;
-                final Runnable task = new CheckedRunnable() {
-                    public void realRun() {
-                        long now = System.nanoTime();
-                        long elapsedMillis
-                            = NANOSECONDS.toMillis(now - previous.get());
-                        if (done.getCount() == cycles) { // first execution
-                            if (elapsedMillis >= d)
-                                tryLongerDelay.set(true);
-                        } else {
-                            assertTrue(elapsedMillis >= d);
-                            if (elapsedMillis >= 2 * d)
-                                tryLongerDelay.set(true);
-                        }
-                        previous.set(now);
-                        done.countDown();
-                    }};
-                final ScheduledFuture periodicTask =
+                Runnable task = new CheckedRunnable() {
+                    public void realRun() { done.countDown(); }};
+                ScheduledFuture h =
                     p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
-                final int totalDelayMillis = (cycles - 1) * delay;
-                await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
-                periodicTask.cancel(true);
-                final long elapsedMillis = millisElapsedSince(startTime);
-                assertTrue(elapsedMillis >= totalDelayMillis);
-                if (!tryLongerDelay.get())
+                done.await();
+                h.cancel(true);
+                double normalizedTime =
+                    (double) millisElapsedSince(startTime) / delay;
+                if (normalizedTime >= cycles - 1 &&
+                    normalizedTime <= cycles)
                     return;
-                // else retry with longer delay
             }
-            fail("unexpected execution rate");
+            throw new AssertionError("unexpected execution rate");
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -285,107 +273,106 @@
      * execute(null) throws NPE
      */
     public void testExecuteNull() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.execute(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        joinPool(se);
     }
 
     /**
      * schedule(null) throws NPE
      */
     public void testScheduleNull() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                TrackedCallable callable = null;
-                Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            TrackedCallable callable = null;
+            Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        joinPool(se);
     }
 
     /**
      * execute throws RejectedExecutionException if shutdown
      */
     public void testSchedule1_RejectedExecutionException() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpRunnable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpRunnable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+
+        joinPool(se);
     }
 
     /**
      * schedule throws RejectedExecutionException if shutdown
      */
     public void testSchedule2_RejectedExecutionException() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpCallable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpCallable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * schedule callable throws RejectedExecutionException if shutdown
      */
     public void testSchedule3_RejectedExecutionException() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpCallable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpCallable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * scheduleAtFixedRate throws RejectedExecutionException if shutdown
      */
     public void testScheduleAtFixedRate1_RejectedExecutionException() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.scheduleAtFixedRate(new NoOpRunnable(),
-                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.shutdown();
+            se.scheduleAtFixedRate(new NoOpRunnable(),
+                                   MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
      */
     public void testScheduleWithFixedDelay1_RejectedExecutionException() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.scheduleWithFixedDelay(new NoOpRunnable(),
-                                         MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        CustomExecutor se = new CustomExecutor(1);
+        try {
+            se.shutdown();
+            se.scheduleWithFixedDelay(new NoOpRunnable(),
+                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
@@ -393,19 +380,22 @@
      * thread becomes active
      */
     public void testGetActiveCount() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getActiveCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getActiveCount());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getActiveCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -415,10 +405,10 @@
      */
     public void testGetCompletedTaskCount() throws InterruptedException {
         final ThreadPoolExecutor p = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch threadProceed = new CountDownLatch(1);
-            final CountDownLatch threadDone = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadProceed = new CountDownLatch(1);
+        final CountDownLatch threadDone = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
@@ -437,6 +427,8 @@
                     fail("timed out");
                 Thread.yield();
             }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -444,10 +436,9 @@
      * getCorePoolSize returns size given in constructor if not otherwise set
      */
     public void testGetCorePoolSize() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getCorePoolSize());
-        }
+        CustomExecutor p = new CustomExecutor(1);
+        assertEquals(1, p.getCorePoolSize());
+        joinPool(p);
     }
 
     /**
@@ -456,22 +447,25 @@
      */
     public void testGetLargestPoolSize() throws InterruptedException {
         final int THREADS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(THREADS);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getLargestPoolSize());
             for (int i = 0; i < THREADS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadsStarted.countDown();
-                        await(done);
+                        done.await();
                         assertEquals(THREADS, p.getLargestPoolSize());
                     }});
-            await(threadsStarted);
+            assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(THREADS, p.getLargestPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
             assertEquals(THREADS, p.getLargestPoolSize());
         }
-        assertEquals(THREADS, p.getLargestPoolSize());
     }
 
     /**
@@ -479,19 +473,22 @@
      * become active
      */
     public void testGetPoolSize() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getPoolSize());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getPoolSize());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -500,70 +497,58 @@
      * submitted
      */
     public void testGetTaskCount() throws InterruptedException {
-        final int TASKS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        final int TASKS = 5;
+        try {
             assertEquals(0, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            p.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadStarted.countDown();
-                    await(done);
-                }});
-            await(threadStarted);
-            assertEquals(1, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            for (int i = 0; i < TASKS; i++) {
-                assertEquals(1 + i, p.getTaskCount());
+            for (int i = 0; i < TASKS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        assertEquals(1 + TASKS, p.getTaskCount());
-                        await(done);
+                        done.await();
                     }});
-            }
-            assertEquals(1 + TASKS, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(TASKS, p.getTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
-        assertEquals(1 + TASKS, p.getTaskCount());
-        assertEquals(1 + TASKS, p.getCompletedTaskCount());
     }
 
     /**
      * getThreadFactory returns factory in constructor if not set
      */
     public void testGetThreadFactory() {
-        final ThreadFactory threadFactory = new SimpleThreadFactory();
-        final CustomExecutor p = new CustomExecutor(1, threadFactory);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        CustomExecutor p = new CustomExecutor(1, tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory sets the thread factory returned by getThreadFactory
      */
     public void testSetThreadFactory() {
-        final ThreadFactory threadFactory = new SimpleThreadFactory();
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            p.setThreadFactory(threadFactory);
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        CustomExecutor p = new CustomExecutor(1);
+        p.setThreadFactory(tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory(null) throws NPE
      */
     public void testSetThreadFactoryNull() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setThreadFactory(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        CustomExecutor p = new CustomExecutor(1);
+        try {
+            p.setThreadFactory(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -571,84 +556,91 @@
      * isShutdown is false before shutdown, true after
      */
     public void testIsShutdown() {
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        CustomExecutor p = new CustomExecutor(1);
+        try {
             assertFalse(p.isShutdown());
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.isShutdown());
         }
+        finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
+        }
+        assertTrue(p.isShutdown());
     }
 
     /**
      * isTerminated is false before termination, true after
      */
     public void testIsTerminated() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        assertFalse(p.isTerminated());
+        try {
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminated());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
-            assertFalse(p.isTerminated());
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
     }
 
     /**
      * isTerminating is not true when running or when terminated
      */
     public void testIsTerminating() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertFalse(p.isTerminating());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminating());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
+        assertFalse(p.isTerminating());
     }
 
     /**
      * getQueue returns the work queue, which contains queued tasks
      */
     public void testGetQueue() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new CustomExecutor(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
         final CountDownLatch done = new CountDownLatch(1);
-        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             ScheduledFuture[] tasks = new ScheduledFuture[5];
             for (int i = 0; i < tasks.length; i++) {
                 Runnable r = new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                     }};
                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             BlockingQueue<Runnable> q = p.getQueue();
             assertTrue(q.contains(tasks[tasks.length - 1]));
             assertFalse(q.contains(tasks[0]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -656,20 +648,20 @@
      * remove(task) removes queued task, and fails to remove active task
      */
     public void testRemove() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            ScheduledFuture[] tasks = new ScheduledFuture[5];
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 Runnable r = new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                     }};
                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             BlockingQueue<Runnable> q = p.getQueue();
             assertFalse(p.remove((Runnable)tasks[0]));
             assertTrue(q.contains((Runnable)tasks[4]));
@@ -680,6 +672,9 @@
             assertTrue(q.contains((Runnable)tasks[3]));
             assertTrue(p.remove((Runnable)tasks[3]));
             assertFalse(q.contains((Runnable)tasks[3]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -687,15 +682,12 @@
      * purge removes cancelled tasks from the queue
      */
     public void testPurge() throws InterruptedException {
-        final ScheduledFuture[] tasks = new ScheduledFuture[5];
-        final Runnable releaser = new Runnable() { public void run() {
-            for (ScheduledFuture task : tasks)
-                if (task != null) task.cancel(true); }};
-        final CustomExecutor p = new CustomExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, releaser)) {
-            for (int i = 0; i < tasks.length; i++)
-                tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
-                                      LONG_DELAY_MS, MILLISECONDS);
+        CustomExecutor p = new CustomExecutor(1);
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
+                                  LONG_DELAY_MS, MILLISECONDS);
+        try {
             int max = tasks.length;
             if (tasks[4].cancel(true)) --max;
             if (tasks[3].cancel(true)) --max;
@@ -707,185 +699,159 @@
                 long count = p.getTaskCount();
                 if (count == max)
                     return;
-            } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
+            } while (millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
             fail("Purge failed to remove cancelled tasks");
+        } finally {
+            for (ScheduledFuture task : tasks)
+                task.cancel(true);
+            joinPool(p);
         }
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * shutdownNow returns a list containing tasks that were not run
      */
-    public void testShutdownNow() throws InterruptedException {
-        final int poolSize = 2;
-        final int count = 5;
-        final AtomicInteger ran = new AtomicInteger(0);
-        final CustomExecutor p = new CustomExecutor(poolSize);
-        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
-        Runnable waiter = new CheckedRunnable() { public void realRun() {
-            threadsStarted.countDown();
-            try {
-                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
-            } catch (InterruptedException success) {}
-            ran.getAndIncrement();
-        }};
-        for (int i = 0; i < count; i++)
-            p.execute(waiter);
-        await(threadsStarted);
-        assertEquals(poolSize, p.getActiveCount());
-        assertEquals(0, p.getCompletedTaskCount());
-        final List<Runnable> queuedTasks;
+    public void testShutdownNow() {
+        CustomExecutor p = new CustomExecutor(1);
+        for (int i = 0; i < 5; i++)
+            p.schedule(new SmallPossiblyInterruptedRunnable(),
+                       LONG_DELAY_MS, MILLISECONDS);
         try {
-            queuedTasks = p.shutdownNow();
+            List<Runnable> l = p.shutdownNow();
+            assertTrue(p.isShutdown());
+            assertEquals(5, l.size());
         } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
+            // Allowed in case test doesn't have privs
+        } finally {
+            joinPool(p);
         }
-        assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        assertEquals(count - poolSize, queuedTasks.size());
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(p.isTerminated());
-        assertEquals(poolSize, ran.get());
-        assertEquals(poolSize, p.getCompletedTaskCount());
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * In default setting, shutdown cancels periodic but not delayed
+     * tasks at shutdown
      */
-    public void testShutdownNow_delayedTasks() throws InterruptedException {
-        final CustomExecutor p = new CustomExecutor(1);
-        List<ScheduledFuture> tasks = new ArrayList<>();
-        for (int i = 0; i < 3; i++) {
-            Runnable r = new NoOpRunnable();
-            tasks.add(p.schedule(r, 9, SECONDS));
-            tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
-            tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
-        }
-        if (testImplementationDetails)
-            assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
-        final List<Runnable> queuedTasks;
-        try {
-            queuedTasks = p.shutdownNow();
-        } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
-        }
-        assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        if (testImplementationDetails)
-            assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
-        assertEquals(tasks.size(), queuedTasks.size());
+    public void testShutdown1() throws InterruptedException {
+        CustomExecutor p = new CustomExecutor(1);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new NoOpRunnable(),
+                                  SHORT_DELAY_MS, MILLISECONDS);
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        BlockingQueue<Runnable> q = p.getQueue();
         for (ScheduledFuture task : tasks) {
-            assertFalse(((CustomTask)task).ran);
             assertFalse(task.isDone());
             assertFalse(task.isCancelled());
+            assertTrue(q.contains(task));
         }
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isShutdown());
+        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
         assertTrue(p.isTerminated());
+        for (ScheduledFuture task : tasks) {
+            assertTrue(task.isDone());
+            assertFalse(task.isCancelled());
+        }
     }
 
     /**
-     * By default, periodic tasks are cancelled at shutdown.
-     * By default, delayed tasks keep running after shutdown.
-     * Check that changing the default values work:
-     * - setExecuteExistingDelayedTasksAfterShutdownPolicy
-     * - setContinueExistingPeriodicTasksAfterShutdownPolicy
+     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
+     * delayed tasks are cancelled at shutdown
      */
-    public void testShutdown_cancellation() throws Exception {
-        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
-        for (Boolean policy : allBooleans)
-    {
-        final int poolSize = 2;
-        final CustomExecutor p = new CustomExecutor(poolSize);
-        final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE);
-        final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE);
-        final boolean effectiveRemovePolicy = (policy == Boolean.TRUE);
-        if (policy != null) {
-            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy);
-            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy);
-            p.setRemoveOnCancelPolicy(policy);
-        }
-        assertEquals(effectiveDelayedPolicy,
-                     p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
-        assertEquals(effectivePeriodicPolicy,
-                     p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
-        assertEquals(effectiveRemovePolicy,
-                     p.getRemoveOnCancelPolicy());
-        // Strategy: Wedge the pool with poolSize "blocker" threads
-        final AtomicInteger ran = new AtomicInteger(0);
-        final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
-        final CountDownLatch unblock = new CountDownLatch(1);
-        final CountDownLatch periodicLatch1 = new CountDownLatch(2);
-        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
-        Runnable task = new CheckedRunnable() { public void realRun()
-                                                    throws InterruptedException {
-            poolBlocked.countDown();
-            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
-            ran.getAndIncrement();
-        }};
-        List<Future<?>> blockers = new ArrayList<>();
-        List<Future<?>> periodics = new ArrayList<>();
-        List<Future<?>> delayeds = new ArrayList<>();
-        for (int i = 0; i < poolSize; i++)
-            blockers.add(p.submit(task));
-        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
-
-        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
-                                            1, 1, MILLISECONDS));
-        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
-                                               1, 1, MILLISECONDS));
-        delayeds.add(p.schedule(task, 1, MILLISECONDS));
-
-        assertTrue(p.getQueue().containsAll(periodics));
-        assertTrue(p.getQueue().containsAll(delayeds));
+    public void testShutdown2() throws InterruptedException {
+        CustomExecutor p = new CustomExecutor(1);
+        p.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+        assertFalse(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new NoOpRunnable(),
+                                  SHORT_DELAY_MS, MILLISECONDS);
+        BlockingQueue q = p.getQueue();
+        assertEquals(tasks.length, q.size());
         try { p.shutdown(); } catch (SecurityException ok) { return; }
         assertTrue(p.isShutdown());
-        assertFalse(p.isTerminated());
-        for (Future<?> periodic : periodics) {
-            assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
-            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
-        }
-        for (Future<?> delayed : delayeds) {
-            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
-            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
-        }
-        if (testImplementationDetails) {
-            assertEquals(effectivePeriodicPolicy,
-                         p.getQueue().containsAll(periodics));
-            assertEquals(effectiveDelayedPolicy,
-                         p.getQueue().containsAll(delayeds));
-        }
-        // Release all pool threads
-        unblock.countDown();
-
-        for (Future<?> delayed : delayeds) {
-            if (effectiveDelayedPolicy) {
-                assertNull(delayed.get());
-            }
-        }
-        if (effectivePeriodicPolicy) {
-            assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS));
-            for (Future<?> periodic : periodics) {
-                assertTrue(periodic.cancel(false));
-                assertTrue(periodic.isCancelled());
-                assertTrue(periodic.isDone());
-            }
-        }
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(q.isEmpty());
+        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
         assertTrue(p.isTerminated());
-        assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
-    }}
+        for (ScheduledFuture task : tasks) {
+            assertTrue(task.isDone());
+            assertTrue(task.isCancelled());
+        }
+    }
+
+    /**
+     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
+     * periodic tasks are cancelled at shutdown
+     */
+    public void testShutdown3() throws InterruptedException {
+        CustomExecutor p = new CustomExecutor(1);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        p.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        long initialDelay = LONG_DELAY_MS;
+        ScheduledFuture task =
+            p.scheduleAtFixedRate(new NoOpRunnable(), initialDelay,
+                                  5, MILLISECONDS);
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.isShutdown());
+        assertTrue(p.getQueue().isEmpty());
+        assertTrue(task.isDone());
+        assertTrue(task.isCancelled());
+        joinPool(p);
+    }
+
+    /**
+     * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
+     * periodic tasks are not cancelled at shutdown
+     */
+    public void testShutdown4() throws InterruptedException {
+        CustomExecutor p = new CustomExecutor(1);
+        final CountDownLatch counter = new CountDownLatch(2);
+        try {
+            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
+            assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+            assertTrue(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+            final Runnable r = new CheckedRunnable() {
+                public void realRun() {
+                    counter.countDown();
+                }};
+            ScheduledFuture task =
+                p.scheduleAtFixedRate(r, 1, 1, MILLISECONDS);
+            assertFalse(task.isDone());
+            assertFalse(task.isCancelled());
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
+            assertFalse(task.isCancelled());
+            assertFalse(p.isTerminated());
+            assertTrue(p.isShutdown());
+            assertTrue(counter.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertFalse(task.isCancelled());
+            assertTrue(task.cancel(false));
+            assertTrue(task.isDone());
+            assertTrue(task.isCancelled());
+            assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
+            assertTrue(p.isTerminated());
+        }
+        finally {
+            joinPool(p);
+        }
+    }
 
     /**
      * completed submit of callable returns result
      */
     public void testSubmitCallable() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             Future<String> future = e.submit(new StringTask());
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -893,11 +859,13 @@
      * completed submit of runnable returns successfully
      */
     public void testSubmitRunnable() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             Future<?> future = e.submit(new NoOpRunnable());
             future.get();
             assertTrue(future.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -905,11 +873,13 @@
      * completed submit of (runnable, result) returns result
      */
     public void testSubmitRunnable2() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -917,12 +887,13 @@
      * invokeAny(null) throws NPE
      */
     public void testInvokeAny1() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -930,12 +901,13 @@
      * invokeAny(empty collection) throws IAE
      */
     public void testInvokeAny2() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -943,17 +915,18 @@
      * invokeAny(c) throws NPE if c has null elements
      */
     public void testInvokeAny3() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        CountDownLatch latch = new CountDownLatch(1);
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -961,16 +934,16 @@
      * invokeAny(c) throws ExecutionException if no task completes
      */
     public void testInvokeAny4() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -978,13 +951,15 @@
      * invokeAny(c) returns result of some task
      */
     public void testInvokeAny5() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -992,12 +967,13 @@
      * invokeAll(null) throws NPE
      */
     public void testInvokeAll1() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1005,10 +981,12 @@
      * invokeAll(empty collection) returns empty collection
      */
     public void testInvokeAll2() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1016,15 +994,16 @@
      * invokeAll(c) throws NPE if c has null elements
      */
     public void testInvokeAll3() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1032,18 +1011,18 @@
      * get of invokeAll(c) throws exception on failed task
      */
     public void testInvokeAll4() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures = e.invokeAll(l);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures = e.invokeAll(l);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1051,8 +1030,8 @@
      * invokeAll(c) returns results of all completed tasks
      */
     public void testInvokeAll5() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -1060,6 +1039,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1067,12 +1048,13 @@
      * timed invokeAny(null) throws NPE
      */
     public void testTimedInvokeAny1() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1080,14 +1062,15 @@
      * timed invokeAny(,,null) throws NPE
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1095,12 +1078,13 @@
      * timed invokeAny(empty collection) throws IAE
      */
     public void testTimedInvokeAny2() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1109,16 +1093,17 @@
      */
     public void testTimedInvokeAny3() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1126,18 +1111,16 @@
      * timed invokeAny(c) throws ExecutionException if no task completes
      */
     public void testTimedInvokeAny4() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1145,15 +1128,15 @@
      * timed invokeAny(c) returns result of some task
      */
     public void testTimedInvokeAny5() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1161,12 +1144,13 @@
      * timed invokeAll(null) throws NPE
      */
     public void testTimedInvokeAll1() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1174,14 +1158,15 @@
      * timed invokeAll(,,null) throws NPE
      */
     public void testTimedInvokeAllNullTimeUnit() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1189,10 +1174,12 @@
      * timed invokeAll(empty collection) returns empty collection
      */
     public void testTimedInvokeAll2() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1200,15 +1187,16 @@
      * timed invokeAll(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAll3() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1216,19 +1204,19 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testTimedInvokeAll4() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures =
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures =
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1236,16 +1224,18 @@
      * timed invokeAll(c) returns results of all completed tasks
      */
     public void testTimedInvokeAll5() throws Exception {
-        final ExecutorService e = new CustomExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1253,37 +1243,21 @@
      * timed invokeAll(c) cancels tasks not completed by timeout
      */
     public void testTimedInvokeAll6() throws Exception {
-        for (long timeout = timeoutMillis();;) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Callable<String> waiter = new CheckedCallable<String>() {
-                public String realCall() {
-                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
-                    catch (InterruptedException ok) {}
-                    return "1"; }};
-            final ExecutorService p = new CustomExecutor(2);
-            try (PoolCleaner cleaner = cleaner(p, done)) {
-                List<Callable<String>> tasks = new ArrayList<>();
-                tasks.add(new StringTask("0"));
-                tasks.add(waiter);
-                tasks.add(new StringTask("2"));
-                long startTime = System.nanoTime();
-                List<Future<String>> futures =
-                    p.invokeAll(tasks, timeout, MILLISECONDS);
-                assertEquals(tasks.size(), futures.size());
-                assertTrue(millisElapsedSince(startTime) >= timeout);
-                for (Future future : futures)
-                    assertTrue(future.isDone());
-                assertTrue(futures.get(1).isCancelled());
-                try {
-                    assertEquals("0", futures.get(0).get());
-                    assertEquals("2", futures.get(2).get());
-                    break;
-                } catch (CancellationException retryWithLongerTimeout) {
-                    timeout *= 2;
-                    if (timeout >= LONG_DELAY_MS / 2)
-                        fail("expected exactly one task to be cancelled");
-                }
-            }
+        ExecutorService e = new CustomExecutor(2);
+        try {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+            assertEquals(l.size(), futures.size());
+            for (Future future : futures)
+                assertTrue(future.isDone());
+            assertFalse(futures.get(0).isCancelled());
+            assertTrue(futures.get(1).isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ScheduledExecutorTest.java b/jsr166-tests/src/test/java/jsr166/ScheduledExecutorTest.java
index 81f7370..a2e83d0 100644
--- a/jsr166-tests/src/test/java/jsr166/ScheduledExecutorTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ScheduledExecutorTest.java
@@ -9,15 +9,11 @@
 package jsr166;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
@@ -28,9 +24,7 @@
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -43,20 +37,24 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ScheduledExecutorTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
      * execute successfully executes a runnable
      */
     public void testExecute() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Runnable task = new CheckedRunnable() {
-                public void realRun() { done.countDown(); }};
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        final Runnable task = new CheckedRunnable() {
+            public void realRun() {
+                done.countDown();
+            }};
+        try {
             p.execute(task);
-            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
+            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -64,10 +62,10 @@
      * delayed schedule of callable successfully executes after delay
      */
     public void testSchedule1() throws Exception {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Callable task = new CheckedCallable<Boolean>() {
                 public Boolean realCall() {
                     done.countDown();
@@ -78,6 +76,8 @@
             assertSame(Boolean.TRUE, f.get());
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
             assertTrue(done.await(0L, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -85,10 +85,10 @@
      * delayed schedule of runnable successfully executes after delay
      */
     public void testSchedule3() throws Exception {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -98,6 +98,8 @@
             await(done);
             assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -105,10 +107,10 @@
      * scheduleAtFixedRate executes runnable after given initial delay
      */
     public void testSchedule4() throws Exception {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -120,6 +122,8 @@
             await(done);
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
             f.cancel(true);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -127,10 +131,10 @@
      * scheduleWithFixedDelay executes runnable after given initial delay
      */
     public void testSchedule5() throws Exception {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final long startTime = System.nanoTime();
-            final CountDownLatch done = new CountDownLatch(1);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final long startTime = System.nanoTime();
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() {
                     done.countDown();
@@ -142,6 +146,8 @@
             await(done);
             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
             f.cancel(true);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -151,77 +157,58 @@
     }
 
     /**
-     * scheduleAtFixedRate executes series of tasks at given rate.
-     * Eventually, it must hold that:
-     *   cycles - 1 <= elapsedMillis/delay < cycles
+     * scheduleAtFixedRate executes series of tasks at given rate
      */
     public void testFixedRateSequence() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        try {
             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
-                final long startTime = System.nanoTime();
-                final int cycles = 8;
+                long startTime = System.nanoTime();
+                int cycles = 10;
                 final CountDownLatch done = new CountDownLatch(cycles);
-                final Runnable task = new CheckedRunnable() {
+                Runnable task = new CheckedRunnable() {
                     public void realRun() { done.countDown(); }};
-                final ScheduledFuture periodicTask =
+                ScheduledFuture h =
                     p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
-                final int totalDelayMillis = (cycles - 1) * delay;
-                await(done, totalDelayMillis + LONG_DELAY_MS);
-                periodicTask.cancel(true);
-                final long elapsedMillis = millisElapsedSince(startTime);
-                assertTrue(elapsedMillis >= totalDelayMillis);
-                if (elapsedMillis <= cycles * delay)
+                done.await();
+                h.cancel(true);
+                double normalizedTime =
+                    (double) millisElapsedSince(startTime) / delay;
+                if (normalizedTime >= cycles - 1 &&
+                    normalizedTime <= cycles)
                     return;
-                // else retry with longer delay
             }
-            fail("unexpected execution rate");
+            throw new AssertionError("unexpected execution rate");
+        } finally {
+            joinPool(p);
         }
     }
 
     /**
-     * scheduleWithFixedDelay executes series of tasks with given period.
-     * Eventually, it must hold that each task starts at least delay and at
-     * most 2 * delay after the termination of the previous task.
+     * scheduleWithFixedDelay executes series of tasks with given period
      */
     public void testFixedDelaySequence() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        try {
             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
-                final long startTime = System.nanoTime();
-                final AtomicLong previous = new AtomicLong(startTime);
-                final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
-                final int cycles = 8;
+                long startTime = System.nanoTime();
+                int cycles = 10;
                 final CountDownLatch done = new CountDownLatch(cycles);
-                final int d = delay;
-                final Runnable task = new CheckedRunnable() {
-                    public void realRun() {
-                        long now = System.nanoTime();
-                        long elapsedMillis
-                            = NANOSECONDS.toMillis(now - previous.get());
-                        if (done.getCount() == cycles) { // first execution
-                            if (elapsedMillis >= d)
-                                tryLongerDelay.set(true);
-                        } else {
-                            assertTrue(elapsedMillis >= d);
-                            if (elapsedMillis >= 2 * d)
-                                tryLongerDelay.set(true);
-                        }
-                        previous.set(now);
-                        done.countDown();
-                    }};
-                final ScheduledFuture periodicTask =
+                Runnable task = new CheckedRunnable() {
+                    public void realRun() { done.countDown(); }};
+                ScheduledFuture h =
                     p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
-                final int totalDelayMillis = (cycles - 1) * delay;
-                await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
-                periodicTask.cancel(true);
-                final long elapsedMillis = millisElapsedSince(startTime);
-                assertTrue(elapsedMillis >= totalDelayMillis);
-                if (!tryLongerDelay.get())
+                done.await();
+                h.cancel(true);
+                double normalizedTime =
+                    (double) millisElapsedSince(startTime) / delay;
+                if (normalizedTime >= cycles - 1 &&
+                    normalizedTime <= cycles)
                     return;
-                // else retry with longer delay
             }
-            fail("unexpected execution rate");
+            throw new AssertionError("unexpected execution rate");
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -229,107 +216,108 @@
      * execute(null) throws NPE
      */
     public void testExecuteNull() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        ScheduledThreadPoolExecutor se = null;
+        try {
+            se = new ScheduledThreadPoolExecutor(1);
+            se.execute(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+
+        joinPool(se);
     }
 
     /**
      * schedule(null) throws NPE
      */
     public void testScheduleNull() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                TrackedCallable callable = null;
-                Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            TrackedCallable callable = null;
+            Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        joinPool(se);
     }
 
     /**
      * execute throws RejectedExecutionException if shutdown
      */
     public void testSchedule1_RejectedExecutionException() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpRunnable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpRunnable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+
+        joinPool(se);
     }
 
     /**
      * schedule throws RejectedExecutionException if shutdown
      */
     public void testSchedule2_RejectedExecutionException() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpCallable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpCallable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * schedule callable throws RejectedExecutionException if shutdown
      */
     public void testSchedule3_RejectedExecutionException() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.schedule(new NoOpCallable(),
-                           MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            se.shutdown();
+            se.schedule(new NoOpCallable(),
+                        MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * scheduleAtFixedRate throws RejectedExecutionException if shutdown
      */
     public void testScheduleAtFixedRate1_RejectedExecutionException() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.scheduleAtFixedRate(new NoOpRunnable(),
-                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            se.shutdown();
+            se.scheduleAtFixedRate(new NoOpRunnable(),
+                                   MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
      * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
      */
     public void testScheduleWithFixedDelay1_RejectedExecutionException() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.shutdown();
-                p.scheduleWithFixedDelay(new NoOpRunnable(),
-                                         MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (RejectedExecutionException success) {
-            } catch (SecurityException ok) {}
+        ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
+        try {
+            se.shutdown();
+            se.scheduleWithFixedDelay(new NoOpRunnable(),
+                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (RejectedExecutionException success) {
+        } catch (SecurityException ok) {
         }
+        joinPool(se);
     }
 
     /**
@@ -337,19 +325,22 @@
      * thread becomes active
      */
     public void testGetActiveCount() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getActiveCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getActiveCount());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getActiveCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -359,10 +350,10 @@
      */
     public void testGetCompletedTaskCount() throws InterruptedException {
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch threadProceed = new CountDownLatch(1);
-            final CountDownLatch threadDone = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadProceed = new CountDownLatch(1);
+        final CountDownLatch threadDone = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
@@ -381,6 +372,8 @@
                     fail("timed out");
                 Thread.yield();
             }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -389,9 +382,8 @@
      */
     public void testGetCorePoolSize() throws InterruptedException {
         ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getCorePoolSize());
-        }
+        assertEquals(1, p.getCorePoolSize());
+        joinPool(p);
     }
 
     /**
@@ -403,19 +395,22 @@
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(THREADS);
         final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
         final CountDownLatch done = new CountDownLatch(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        try {
             assertEquals(0, p.getLargestPoolSize());
             for (int i = 0; i < THREADS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadsStarted.countDown();
-                        await(done);
+                        done.await();
                         assertEquals(THREADS, p.getLargestPoolSize());
                     }});
-            await(threadsStarted);
+            assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(THREADS, p.getLargestPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
             assertEquals(THREADS, p.getLargestPoolSize());
         }
-        assertEquals(THREADS, p.getLargestPoolSize());
     }
 
     /**
@@ -426,16 +421,19 @@
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
         final CountDownLatch threadStarted = new CountDownLatch(1);
         final CountDownLatch done = new CountDownLatch(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        try {
             assertEquals(0, p.getPoolSize());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getPoolSize());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -444,71 +442,58 @@
      * submitted
      */
     public void testGetTaskCount() throws InterruptedException {
-        final int TASKS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        final int TASKS = 5;
+        try {
             assertEquals(0, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            p.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadStarted.countDown();
-                    await(done);
-                }});
-            await(threadStarted);
-            assertEquals(1, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            for (int i = 0; i < TASKS; i++) {
-                assertEquals(1 + i, p.getTaskCount());
+            for (int i = 0; i < TASKS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        assertEquals(1 + TASKS, p.getTaskCount());
-                        await(done);
+                        done.await();
                     }});
-            }
-            assertEquals(1 + TASKS, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(TASKS, p.getTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
-        assertEquals(1 + TASKS, p.getTaskCount());
-        assertEquals(1 + TASKS, p.getCompletedTaskCount());
     }
 
     /**
      * getThreadFactory returns factory in constructor if not set
      */
     public void testGetThreadFactory() throws InterruptedException {
-        final ThreadFactory threadFactory = new SimpleThreadFactory();
-        final ScheduledThreadPoolExecutor p =
-            new ScheduledThreadPoolExecutor(1, threadFactory);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1, tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory sets the thread factory returned by getThreadFactory
      */
     public void testSetThreadFactory() throws InterruptedException {
-        ThreadFactory threadFactory = new SimpleThreadFactory();
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            p.setThreadFactory(threadFactory);
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        p.setThreadFactory(tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory(null) throws NPE
      */
     public void testSetThreadFactoryNull() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setThreadFactory(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        try {
+            p.setThreadFactory(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -517,7 +502,7 @@
      */
     public void testIsShutdown() {
 
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
         try {
             assertFalse(p.isShutdown());
         }
@@ -532,23 +517,24 @@
      */
     public void testIsTerminated() throws InterruptedException {
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch done = new CountDownLatch(1);
-            assertFalse(p.isTerminated());
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        assertFalse(p.isTerminated());
+        try {
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminated());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
     }
 
     /**
@@ -558,45 +544,49 @@
         final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
         final CountDownLatch threadStarted = new CountDownLatch(1);
         final CountDownLatch done = new CountDownLatch(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             assertFalse(p.isTerminating());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminating());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
+        assertFalse(p.isTerminating());
     }
 
     /**
      * getQueue returns the work queue, which contains queued tasks
      */
     public void testGetQueue() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
         final CountDownLatch done = new CountDownLatch(1);
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             ScheduledFuture[] tasks = new ScheduledFuture[5];
             for (int i = 0; i < tasks.length; i++) {
                 Runnable r = new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                     }};
                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             BlockingQueue<Runnable> q = p.getQueue();
             assertTrue(q.contains(tasks[tasks.length - 1]));
             assertFalse(q.contains(tasks[0]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -604,20 +594,20 @@
      * remove(task) removes queued task, and fails to remove active task
      */
     public void testRemove() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            ScheduledFuture[] tasks = new ScheduledFuture[5];
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 Runnable r = new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                     }};
                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             BlockingQueue<Runnable> q = p.getQueue();
             assertFalse(p.remove((Runnable)tasks[0]));
             assertTrue(q.contains((Runnable)tasks[4]));
@@ -628,6 +618,9 @@
             assertTrue(q.contains((Runnable)tasks[3]));
             assertTrue(p.remove((Runnable)tasks[3]));
             assertFalse(q.contains((Runnable)tasks[3]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -635,15 +628,12 @@
      * purge eventually removes cancelled tasks from the queue
      */
     public void testPurge() throws InterruptedException {
-        final ScheduledFuture[] tasks = new ScheduledFuture[5];
-        final Runnable releaser = new Runnable() { public void run() {
-            for (ScheduledFuture task : tasks)
-                if (task != null) task.cancel(true); }};
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p, releaser)) {
-            for (int i = 0; i < tasks.length; i++)
-                tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
-                                      LONG_DELAY_MS, MILLISECONDS);
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
+                                  LONG_DELAY_MS, MILLISECONDS);
+        try {
             int max = tasks.length;
             if (tasks[4].cancel(true)) --max;
             if (tasks[3].cancel(true)) --max;
@@ -655,186 +645,159 @@
                 long count = p.getTaskCount();
                 if (count == max)
                     return;
-            } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
+            } while (millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
             fail("Purge failed to remove cancelled tasks");
+        } finally {
+            for (ScheduledFuture task : tasks)
+                task.cancel(true);
+            joinPool(p);
         }
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * shutdownNow returns a list containing tasks that were not run
      */
-    public void testShutdownNow() throws InterruptedException {
-        final int poolSize = 2;
-        final int count = 5;
-        final AtomicInteger ran = new AtomicInteger(0);
-        final ScheduledThreadPoolExecutor p =
-            new ScheduledThreadPoolExecutor(poolSize);
-        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
-        Runnable waiter = new CheckedRunnable() { public void realRun() {
-            threadsStarted.countDown();
-            try {
-                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
-            } catch (InterruptedException success) {}
-            ran.getAndIncrement();
-        }};
-        for (int i = 0; i < count; i++)
-            p.execute(waiter);
-        await(threadsStarted);
-        assertEquals(poolSize, p.getActiveCount());
-        assertEquals(0, p.getCompletedTaskCount());
-        final List<Runnable> queuedTasks;
+    public void testShutdownNow() {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        for (int i = 0; i < 5; i++)
+            p.schedule(new SmallPossiblyInterruptedRunnable(),
+                       LONG_DELAY_MS, MILLISECONDS);
         try {
-            queuedTasks = p.shutdownNow();
+            List<Runnable> l = p.shutdownNow();
+            assertTrue(p.isShutdown());
+            assertEquals(5, l.size());
         } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
+            // Allowed in case test doesn't have privs
+        } finally {
+            joinPool(p);
         }
-        assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        assertEquals(count - poolSize, queuedTasks.size());
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(p.isTerminated());
-        assertEquals(poolSize, ran.get());
-        assertEquals(poolSize, p.getCompletedTaskCount());
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * In default setting, shutdown cancels periodic but not delayed
+     * tasks at shutdown
      */
-    public void testShutdownNow_delayedTasks() throws InterruptedException {
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        List<ScheduledFuture> tasks = new ArrayList<>();
-        for (int i = 0; i < 3; i++) {
-            Runnable r = new NoOpRunnable();
-            tasks.add(p.schedule(r, 9, SECONDS));
-            tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
-            tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
-        }
-        if (testImplementationDetails)
-            assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
-        final List<Runnable> queuedTasks;
-        try {
-            queuedTasks = p.shutdownNow();
-        } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
-        }
-        assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        if (testImplementationDetails)
-            assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
-        assertEquals(tasks.size(), queuedTasks.size());
+    public void testShutdown1() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new NoOpRunnable(),
+                                  SHORT_DELAY_MS, MILLISECONDS);
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        BlockingQueue<Runnable> q = p.getQueue();
         for (ScheduledFuture task : tasks) {
             assertFalse(task.isDone());
             assertFalse(task.isCancelled());
+            assertTrue(q.contains(task));
         }
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isShutdown());
+        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
         assertTrue(p.isTerminated());
+        for (ScheduledFuture task : tasks) {
+            assertTrue(task.isDone());
+            assertFalse(task.isCancelled());
+        }
     }
 
     /**
-     * By default, periodic tasks are cancelled at shutdown.
-     * By default, delayed tasks keep running after shutdown.
-     * Check that changing the default values work:
-     * - setExecuteExistingDelayedTasksAfterShutdownPolicy
-     * - setContinueExistingPeriodicTasksAfterShutdownPolicy
+     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
+     * delayed tasks are cancelled at shutdown
      */
-    public void testShutdown_cancellation() throws Exception {
-        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
-        for (Boolean policy : allBooleans)
-    {
-        final int poolSize = 2;
-        final ScheduledThreadPoolExecutor p
-            = new ScheduledThreadPoolExecutor(poolSize);
-        final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE);
-        final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE);
-        final boolean effectiveRemovePolicy = (policy == Boolean.TRUE);
-        if (policy != null) {
-            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy);
-            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy);
-            p.setRemoveOnCancelPolicy(policy);
-        }
-        assertEquals(effectiveDelayedPolicy,
-                     p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
-        assertEquals(effectivePeriodicPolicy,
-                     p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
-        assertEquals(effectiveRemovePolicy,
-                     p.getRemoveOnCancelPolicy());
-        // Strategy: Wedge the pool with poolSize "blocker" threads
-        final AtomicInteger ran = new AtomicInteger(0);
-        final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
-        final CountDownLatch unblock = new CountDownLatch(1);
-        final CountDownLatch periodicLatch1 = new CountDownLatch(2);
-        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
-        Runnable task = new CheckedRunnable() { public void realRun()
-                                                    throws InterruptedException {
-            poolBlocked.countDown();
-            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
-            ran.getAndIncrement();
-        }};
-        List<Future<?>> blockers = new ArrayList<>();
-        List<Future<?>> periodics = new ArrayList<>();
-        List<Future<?>> delayeds = new ArrayList<>();
-        for (int i = 0; i < poolSize; i++)
-            blockers.add(p.submit(task));
-        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
-
-        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
-                                            1, 1, MILLISECONDS));
-        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
-                                               1, 1, MILLISECONDS));
-        delayeds.add(p.schedule(task, 1, MILLISECONDS));
-
-        assertTrue(p.getQueue().containsAll(periodics));
-        assertTrue(p.getQueue().containsAll(delayeds));
+    public void testShutdown2() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        p.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+        assertFalse(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        ScheduledFuture[] tasks = new ScheduledFuture[5];
+        for (int i = 0; i < tasks.length; i++)
+            tasks[i] = p.schedule(new NoOpRunnable(),
+                                  SHORT_DELAY_MS, MILLISECONDS);
+        BlockingQueue q = p.getQueue();
+        assertEquals(tasks.length, q.size());
         try { p.shutdown(); } catch (SecurityException ok) { return; }
         assertTrue(p.isShutdown());
-        assertFalse(p.isTerminated());
-        for (Future<?> periodic : periodics) {
-            assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
-            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
-        }
-        for (Future<?> delayed : delayeds) {
-            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
-            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
-        }
-        if (testImplementationDetails) {
-            assertEquals(effectivePeriodicPolicy,
-                         p.getQueue().containsAll(periodics));
-            assertEquals(effectiveDelayedPolicy,
-                         p.getQueue().containsAll(delayeds));
-        }
-        // Release all pool threads
-        unblock.countDown();
-
-        for (Future<?> delayed : delayeds) {
-            if (effectiveDelayedPolicy) {
-                assertNull(delayed.get());
-            }
-        }
-        if (effectivePeriodicPolicy) {
-            assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS));
-            for (Future<?> periodic : periodics) {
-                assertTrue(periodic.cancel(false));
-                assertTrue(periodic.isCancelled());
-                assertTrue(periodic.isDone());
-            }
-        }
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(q.isEmpty());
+        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
         assertTrue(p.isTerminated());
-        assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
-    }}
+        for (ScheduledFuture task : tasks) {
+            assertTrue(task.isDone());
+            assertTrue(task.isCancelled());
+        }
+    }
+
+    /**
+     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
+     * periodic tasks are cancelled at shutdown
+     */
+    public void testShutdown3() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        p.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+        long initialDelay = LONG_DELAY_MS;
+        ScheduledFuture task =
+            p.scheduleAtFixedRate(new NoOpRunnable(), initialDelay,
+                                  5, MILLISECONDS);
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.isShutdown());
+        assertTrue(p.getQueue().isEmpty());
+        assertTrue(task.isDone());
+        assertTrue(task.isCancelled());
+        joinPool(p);
+    }
+
+    /**
+     * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
+     * periodic tasks are not cancelled at shutdown
+     */
+    public void testShutdown4() throws InterruptedException {
+        ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
+        final CountDownLatch counter = new CountDownLatch(2);
+        try {
+            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
+            assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+            assertTrue(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+            final Runnable r = new CheckedRunnable() {
+                public void realRun() {
+                    counter.countDown();
+                }};
+            ScheduledFuture task =
+                p.scheduleAtFixedRate(r, 1, 1, MILLISECONDS);
+            assertFalse(task.isDone());
+            assertFalse(task.isCancelled());
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
+            assertFalse(task.isCancelled());
+            assertFalse(p.isTerminated());
+            assertTrue(p.isShutdown());
+            assertTrue(counter.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertFalse(task.isCancelled());
+            assertTrue(task.cancel(false));
+            assertTrue(task.isDone());
+            assertTrue(task.isCancelled());
+            assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
+            assertTrue(p.isTerminated());
+        }
+        finally {
+            joinPool(p);
+        }
+    }
 
     /**
      * completed submit of callable returns result
      */
     public void testSubmitCallable() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             Future<String> future = e.submit(new StringTask());
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -842,11 +805,13 @@
      * completed submit of runnable returns successfully
      */
     public void testSubmitRunnable() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             Future<?> future = e.submit(new NoOpRunnable());
             future.get();
             assertTrue(future.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -854,11 +819,13 @@
      * completed submit of (runnable, result) returns result
      */
     public void testSubmitRunnable2() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -866,12 +833,13 @@
      * invokeAny(null) throws NPE
      */
     public void testInvokeAny1() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -879,12 +847,13 @@
      * invokeAny(empty collection) throws IAE
      */
     public void testInvokeAny2() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -893,16 +862,17 @@
      */
     public void testInvokeAny3() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -910,16 +880,16 @@
      * invokeAny(c) throws ExecutionException if no task completes
      */
     public void testInvokeAny4() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -927,13 +897,15 @@
      * invokeAny(c) returns result of some task
      */
     public void testInvokeAny5() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -941,12 +913,13 @@
      * invokeAll(null) throws NPE
      */
     public void testInvokeAll1() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -954,10 +927,12 @@
      * invokeAll(empty collection) returns empty collection
      */
     public void testInvokeAll2() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -965,15 +940,16 @@
      * invokeAll(c) throws NPE if c has null elements
      */
     public void testInvokeAll3() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -981,18 +957,18 @@
      * get of invokeAll(c) throws exception on failed task
      */
     public void testInvokeAll4() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures = e.invokeAll(l);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures = e.invokeAll(l);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1000,8 +976,8 @@
      * invokeAll(c) returns results of all completed tasks
      */
     public void testInvokeAll5() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -1009,6 +985,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1016,12 +994,13 @@
      * timed invokeAny(null) throws NPE
      */
     public void testTimedInvokeAny1() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1029,14 +1008,15 @@
      * timed invokeAny(,,null) throws NPE
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1044,12 +1024,13 @@
      * timed invokeAny(empty collection) throws IAE
      */
     public void testTimedInvokeAny2() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1058,16 +1039,17 @@
      */
     public void testTimedInvokeAny3() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1075,18 +1057,16 @@
      * timed invokeAny(c) throws ExecutionException if no task completes
      */
     public void testTimedInvokeAny4() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1094,15 +1074,15 @@
      * timed invokeAny(c) returns result of some task
      */
     public void testTimedInvokeAny5() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1110,12 +1090,13 @@
      * timed invokeAll(null) throws NPE
      */
     public void testTimedInvokeAll1() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1123,14 +1104,15 @@
      * timed invokeAll(,,null) throws NPE
      */
     public void testTimedInvokeAllNullTimeUnit() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1138,11 +1120,12 @@
      * timed invokeAll(empty collection) returns empty collection
      */
     public void testTimedInvokeAll2() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(),
-                                                 MEDIUM_DELAY_MS, MILLISECONDS);
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1150,15 +1133,16 @@
      * timed invokeAll(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAll3() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1166,19 +1150,19 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testTimedInvokeAll4() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures =
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1186,16 +1170,18 @@
      * timed invokeAll(c) returns results of all completed tasks
      */
     public void testTimedInvokeAll5() throws Exception {
-        final ExecutorService e = new ScheduledThreadPoolExecutor(2);
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1203,60 +1189,21 @@
      * timed invokeAll(c) cancels tasks not completed by timeout
      */
     public void testTimedInvokeAll6() throws Exception {
-        for (long timeout = timeoutMillis();;) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Callable<String> waiter = new CheckedCallable<String>() {
-                public String realCall() {
-                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
-                    catch (InterruptedException ok) {}
-                    return "1"; }};
-            final ExecutorService p = new ScheduledThreadPoolExecutor(2);
-            try (PoolCleaner cleaner = cleaner(p, done)) {
-                List<Callable<String>> tasks = new ArrayList<>();
-                tasks.add(new StringTask("0"));
-                tasks.add(waiter);
-                tasks.add(new StringTask("2"));
-                long startTime = System.nanoTime();
-                List<Future<String>> futures =
-                    p.invokeAll(tasks, timeout, MILLISECONDS);
-                assertEquals(tasks.size(), futures.size());
-                assertTrue(millisElapsedSince(startTime) >= timeout);
-                for (Future future : futures)
-                    assertTrue(future.isDone());
-                assertTrue(futures.get(1).isCancelled());
-                try {
-                    assertEquals("0", futures.get(0).get());
-                    assertEquals("2", futures.get(2).get());
-                    break;
-                } catch (CancellationException retryWithLongerTimeout) {
-                    timeout *= 2;
-                    if (timeout >= LONG_DELAY_MS / 2)
-                        fail("expected exactly one task to be cancelled");
-                }
-            }
-        }
-    }
-
-    /**
-     * A fixed delay task with overflowing period should not prevent a
-     * one-shot task from executing.
-     * https://bugs.openjdk.java.net/browse/JDK-8051859
-     */
-    public void testScheduleWithFixedDelay_overflow() throws Exception {
-        final CountDownLatch delayedDone = new CountDownLatch(1);
-        final CountDownLatch immediateDone = new CountDownLatch(1);
-        final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final Runnable immediate = new Runnable() { public void run() {
-                immediateDone.countDown();
-            }};
-            final Runnable delayed = new Runnable() { public void run() {
-                delayedDone.countDown();
-                p.submit(immediate);
-            }};
-            p.scheduleWithFixedDelay(delayed, 0L, Long.MAX_VALUE, SECONDS);
-            await(delayedDone);
-            await(immediateDone);
+        ExecutorService e = new ScheduledThreadPoolExecutor(2);
+        try {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+            assertEquals(l.size(), futures.size());
+            for (Future future : futures)
+                assertTrue(future.isDone());
+            assertFalse(futures.get(0).isCancelled());
+            assertTrue(futures.get(1).isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/SemaphoreTest.java b/jsr166-tests/src/test/java/jsr166/SemaphoreTest.java
index 09c82c8..db4f4b4 100644
--- a/jsr166-tests/src/test/java/jsr166/SemaphoreTest.java
+++ b/jsr166-tests/src/test/java/jsr166/SemaphoreTest.java
@@ -26,9 +26,8 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(SemaphoreTest.class);
+    //     return new TestSuite(...);
     // }
-
     /**
      * Subclass to expose protected methods
      */
@@ -472,16 +471,11 @@
             clone.release();
             assertEquals(2, s.availablePermits());
             assertEquals(1, clone.availablePermits());
-            assertFalse(s.hasQueuedThreads());
-            assertFalse(clone.hasQueuedThreads());
-        } catch (InterruptedException e) { threadUnexpectedException(e); }
 
-        {
-            PublicSemaphore s = new PublicSemaphore(0, fair);
+            s = new Semaphore(0, fair);
             Thread t = newStartedThread(new InterruptibleLockRunnable(s));
-            // waitForQueuedThreads(s); // suffers from "flicker", so ...
-            waitForQueuedThread(s, t);  // ... we use this instead
-            PublicSemaphore clone = serialClone(s);
+            waitForQueuedThreads(s);
+            clone = serialClone(s);
             assertEquals(fair, s.isFair());
             assertEquals(fair, clone.isFair());
             assertEquals(0, s.availablePermits());
@@ -492,7 +486,7 @@
             awaitTermination(t);
             assertFalse(s.hasQueuedThreads());
             assertFalse(clone.hasQueuedThreads());
-        }
+        } catch (InterruptedException e) { threadUnexpectedException(e); }
     }
 
     /**
@@ -600,7 +594,7 @@
                 s.acquire(3);
             }});
 
-        waitForQueuedThread(s, t1);
+        waitForQueuedThreads(s);
 
         Thread t2 = newStartedThread(new CheckedRunnable() {
             public void realRun() throws InterruptedException {
diff --git a/jsr166-tests/src/test/java/jsr166/StampedLockTest.java b/jsr166-tests/src/test/java/jsr166/StampedLockTest.java
deleted file mode 100644
index d347c7d..0000000
--- a/jsr166-tests/src/test/java/jsr166/StampedLockTest.java
+++ /dev/null
@@ -1,884 +0,0 @@
-/*
- * 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/
- */
-
-package jsr166;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.StampedLock;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class StampedLockTest extends JSR166TestCase {
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(StampedLockTest.class);
-    // }
-
-    /**
-     * A runnable calling writeLockInterruptibly
-     */
-    class InterruptibleLockRunnable extends CheckedRunnable {
-        final StampedLock lock;
-        InterruptibleLockRunnable(StampedLock l) { lock = l; }
-        public void realRun() throws InterruptedException {
-            lock.writeLockInterruptibly();
-        }
-    }
-
-    /**
-     * A runnable calling writeLockInterruptibly that expects to be
-     * interrupted
-     */
-    class InterruptedLockRunnable extends CheckedInterruptedRunnable {
-        final StampedLock lock;
-        InterruptedLockRunnable(StampedLock l) { lock = l; }
-        public void realRun() throws InterruptedException {
-            lock.writeLockInterruptibly();
-        }
-    }
-
-    /**
-     * Releases write lock, checking isWriteLocked before and after
-     */
-    void releaseWriteLock(StampedLock lock, long s) {
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
-        assertFalse(lock.isWriteLocked());
-    }
-
-    /**
-     * Constructed StampedLock is in unlocked state
-     */
-    public void testConstructor() {
-        StampedLock lock;
-        lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-    }
-
-    /**
-     * write-locking and read-locking an unlocked lock succeed
-     */
-    public void testLock() {
-        StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        lock.unlockWrite(s);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        lock.unlockRead(rs);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-    }
-
-    /**
-     * unlock releases either a read or write lock
-     */
-    public void testUnlock() {
-        StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        lock.unlock(s);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        lock.unlock(rs);
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-    }
-
-    /**
-     * tryUnlockRead/Write succeeds if locked in associated mode else
-     * returns false
-     */
-    public void testTryUnlock() {
-        StampedLock lock = new StampedLock();
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long s = lock.writeLock();
-        assertTrue(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        assertFalse(lock.tryUnlockRead());
-        assertTrue(lock.tryUnlockWrite());
-        assertFalse(lock.tryUnlockWrite());
-        assertFalse(lock.tryUnlockRead());
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-        long rs = lock.readLock();
-        assertFalse(lock.isWriteLocked());
-        assertTrue(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 1);
-        assertFalse(lock.tryUnlockWrite());
-        assertTrue(lock.tryUnlockRead());
-        assertFalse(lock.tryUnlockRead());
-        assertFalse(lock.tryUnlockWrite());
-        assertFalse(lock.isWriteLocked());
-        assertFalse(lock.isReadLocked());
-        assertEquals(lock.getReadLockCount(), 0);
-    }
-
-    /**
-     * write-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testWriteUnlock_IMSE() {
-        StampedLock lock = new StampedLock();
-        try {
-            lock.unlockWrite(0L);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * write-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testWriteUnlock_IMSE2() {
-        StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        lock.unlockWrite(s);
-        try {
-            lock.unlockWrite(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * write-unlocking after readlock throws IllegalMonitorStateException
-     */
-    public void testWriteUnlock_IMSE3() {
-        StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        try {
-            lock.unlockWrite(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE() {
-        StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        lock.unlockRead(s);
-        try {
-            lock.unlockRead(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking an unlocked lock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE2() {
-        StampedLock lock = new StampedLock();
-        try {
-            lock.unlockRead(0L);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * read-unlocking after writeLock throws IllegalMonitorStateException
-     */
-    public void testReadUnlock_IMSE3() {
-        StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        try {
-            lock.unlockRead(s);
-            shouldThrow();
-        } catch (IllegalMonitorStateException success) {}
-    }
-
-    /**
-     * validate(0) fails
-     */
-    public void testValidate0() {
-        StampedLock lock = new StampedLock();
-        assertFalse(lock.validate(0L));
-    }
-
-    /**
-     * A stamp obtained from a successful lock operation validates
-     */
-    public void testValidate() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        s = lock.readLock();
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-    }
-
-    /**
-     * A stamp obtained from an unsuccessful lock operation does not validate
-     */
-    public void testValidate2() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s;
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertFalse(lock.validate(lock.tryWriteLock()));
-        assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS)));
-        assertFalse(lock.validate(lock.tryReadLock()));
-        assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS)));
-        assertFalse(lock.validate(lock.tryOptimisticRead()));
-        lock.unlockWrite(s);
-    }
-
-    /**
-     * writeLockInterruptibly is interruptible
-     */
-    public void testWriteLockInterruptibly_Interruptible()
-            throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.writeLockInterruptibly();
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * timed tryWriteLock is interruptible
-     */
-    public void testWriteTryLock_Interruptible() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS);
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * readLockInterruptibly is interruptible
-     */
-    public void testReadLockInterruptibly_Interruptible()
-            throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.readLockInterruptibly();
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * timed tryReadLock is interruptible
-     */
-    public void testReadTryLock_Interruptible() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS);
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * tryWriteLock on an unlocked lock succeeds
-     */
-    public void testWriteTryLock() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.tryWriteLock();
-        assertTrue(s != 0L);
-        assertTrue(lock.isWriteLocked());
-        long s2 = lock.tryWriteLock();
-        assertEquals(s2, 0L);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * tryWriteLock fails if locked
-     */
-    public void testWriteTryLockWhenLocked() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long ws = lock.tryWriteLock();
-                assertTrue(ws == 0L);
-            }});
-
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * tryReadLock fails if write-locked
-     */
-    public void testReadTryLockWhenLocked() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long rs = lock.tryReadLock();
-                assertEquals(rs, 0L);
-            }});
-
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * Multiple threads can hold a read lock when not write-locked
-     */
-    public void testMultipleReadLocks() {
-        final StampedLock lock = new StampedLock();
-        final long s = lock.readLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() throws InterruptedException {
-                long s2 = lock.tryReadLock();
-                assertTrue(s2 != 0L);
-                lock.unlockRead(s2);
-                long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
-                assertTrue(s3 != 0L);
-                lock.unlockRead(s3);
-                long s4 = lock.readLock();
-                lock.unlockRead(s4);
-            }});
-
-        awaitTermination(t);
-        lock.unlockRead(s);
-    }
-
-    /**
-     * A writelock succeeds only after a reading thread unlocks
-     */
-    public void testWriteAfterReadLock() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long rs = lock.readLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                running.countDown();
-                long s = lock.writeLock();
-                lock.unlockWrite(s);
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        assertFalse(lock.isWriteLocked());
-        lock.unlockRead(rs);
-        awaitTermination(t);
-        assertFalse(lock.isWriteLocked());
-    }
-
-    /**
-     * A writelock succeeds only after reading threads unlock
-     */
-    public void testWriteAfterMultipleReadLocks() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        Thread t1 = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long rs = lock.readLock();
-                lock.unlockRead(rs);
-            }});
-
-        awaitTermination(t1);
-
-        Thread t2 = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long ws = lock.writeLock();
-                lock.unlockWrite(ws);
-            }});
-
-        assertFalse(lock.isWriteLocked());
-        lock.unlockRead(s);
-        awaitTermination(t2);
-        assertFalse(lock.isWriteLocked());
-    }
-
-    /**
-     * Readlocks succeed only after a writing thread unlocks
-     */
-    public void testReadAfterWriteLock() {
-        final StampedLock lock = new StampedLock();
-        final long s = lock.writeLock();
-        Thread t1 = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long rs = lock.readLock();
-                lock.unlockRead(rs);
-            }});
-        Thread t2 = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long rs = lock.readLock();
-                lock.unlockRead(rs);
-            }});
-
-        releaseWriteLock(lock, s);
-        awaitTermination(t1);
-        awaitTermination(t2);
-    }
-
-    /**
-     * tryReadLock succeeds if readlocked but not writelocked
-     */
-    public void testTryLockWhenReadLocked() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long rs = lock.tryReadLock();
-                threadAssertTrue(rs != 0L);
-                lock.unlockRead(rs);
-            }});
-
-        awaitTermination(t);
-        lock.unlockRead(s);
-    }
-
-    /**
-     * tryWriteLock fails when readlocked
-     */
-    public void testWriteTryLockWhenReadLocked() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.readLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() {
-                long ws = lock.tryWriteLock();
-                threadAssertEquals(ws, 0L);
-            }});
-
-        awaitTermination(t);
-        lock.unlockRead(s);
-    }
-
-    /**
-     * timed tryWriteLock times out if locked
-     */
-    public void testWriteTryLock_Timeout() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
-                long timeoutMillis = 10;
-                long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS);
-                assertEquals(ws, 0L);
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            }});
-
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * timed tryReadLock times out if write-locked
-     */
-    public void testReadTryLock_Timeout() {
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLock();
-        Thread t = newStartedThread(new CheckedRunnable() {
-            public void realRun() throws InterruptedException {
-                long startTime = System.nanoTime();
-                long timeoutMillis = 10;
-                long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS);
-                assertEquals(rs, 0L);
-                assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            }});
-
-        awaitTermination(t);
-        assertTrue(lock.isWriteLocked());
-        lock.unlockWrite(s);
-    }
-
-    /**
-     * writeLockInterruptibly succeeds if unlocked, else is interruptible
-     */
-    public void testWriteLockInterruptibly() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s = lock.writeLockInterruptibly();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.writeLockInterruptibly();
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        assertTrue(lock.isWriteLocked());
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * readLockInterruptibly succeeds if lock free else is interruptible
-     */
-    public void testReadLockInterruptibly() throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s;
-        s = lock.readLockInterruptibly();
-        lock.unlockRead(s);
-        s = lock.writeLockInterruptibly();
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                running.countDown();
-                lock.readLockInterruptibly();
-            }});
-
-        running.await();
-        waitForThreadToEnterWaitState(t, 100);
-        t.interrupt();
-        awaitTermination(t);
-        releaseWriteLock(lock, s);
-    }
-
-    /**
-     * A serialized lock deserializes as unlocked
-     */
-    public void testSerialization() {
-        StampedLock lock = new StampedLock();
-        lock.writeLock();
-        StampedLock clone = serialClone(lock);
-        assertTrue(lock.isWriteLocked());
-        assertFalse(clone.isWriteLocked());
-        long s = clone.writeLock();
-        assertTrue(clone.isWriteLocked());
-        clone.unlockWrite(s);
-        assertFalse(clone.isWriteLocked());
-    }
-
-    /**
-     * toString indicates current lock state
-     */
-    public void testToString() {
-        StampedLock lock = new StampedLock();
-        assertTrue(lock.toString().contains("Unlocked"));
-        long s = lock.writeLock();
-        assertTrue(lock.toString().contains("Write-locked"));
-        lock.unlockWrite(s);
-        s = lock.readLock();
-        assertTrue(lock.toString().contains("Read-locks"));
-    }
-
-    /**
-     * tryOptimisticRead succeeds and validates if unlocked, fails if locked
-     */
-    public void testValidateOptimistic() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(s);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockRead(s);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        lock.unlockRead(s);
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-    }
-
-    /**
-     * tryOptimisticRead stamp does not validate if a write lock intervenes
-     */
-    public void testValidateOptimisticWriteLocked() {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertFalse(lock.validate(p));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        assertTrue(lock.validate(s));
-        lock.unlockWrite(s);
-    }
-
-    /**
-     * tryOptimisticRead stamp does not validate if a write lock
-     * intervenes in another thread
-     */
-    public void testValidateOptimisticWriteLocked2()
-            throws InterruptedException {
-        final CountDownLatch running = new CountDownLatch(1);
-        final StampedLock lock = new StampedLock();
-        long s, p;
-        assertTrue((p = lock.tryOptimisticRead()) != 0L);
-        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
-            public void realRun() throws InterruptedException {
-                lock.writeLockInterruptibly();
-                running.countDown();
-                lock.writeLockInterruptibly();
-            }});
-
-        running.await();
-        assertFalse(lock.validate(p));
-        assertFalse((p = lock.tryOptimisticRead()) != 0L);
-        t.interrupt();
-        awaitTermination(t);
-    }
-
-    /**
-     * tryConvertToOptimisticRead succeeds and validates if successfully locked,
-     */
-    public void testTryConvertToOptimisticRead() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
-        assertTrue(lock.validate(p));
-    }
-
-    /**
-     * tryConvertToReadLock succeeds and validates if successfully locked
-     * or lock free;
-     */
-    public void testTryConvertToReadLock() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        lock.unlockRead(p);
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
-    }
-
-    /**
-     * tryConvertToWriteLock succeeds and validates if successfully locked
-     * or lock free;
-     */
-    public void testTryConvertToWriteLock() throws InterruptedException {
-        StampedLock lock = new StampedLock();
-        long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        lock.unlockWrite(p);
-        assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-        assertTrue((s = lock.readLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-        assertTrue((s = lock.tryWriteLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-        assertTrue((s = lock.tryReadLock()) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-        assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-        assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
-        assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
-    }
-
-    /**
-     * asWriteLock can be locked and unlocked
-     */
-    public void testAsWriteLock() {
-        StampedLock sl = new StampedLock();
-        Lock lock = sl.asWriteLock();
-        lock.lock();
-        assertFalse(lock.tryLock());
-        lock.unlock();
-        assertTrue(lock.tryLock());
-    }
-
-    /**
-     * asReadLock can be locked and unlocked
-     */
-    public void testAsReadLock() {
-        StampedLock sl = new StampedLock();
-        Lock lock = sl.asReadLock();
-        lock.lock();
-        lock.unlock();
-        assertTrue(lock.tryLock());
-    }
-
-    /**
-     * asReadWriteLock.writeLock can be locked and unlocked
-     */
-    public void testAsReadWriteLockWriteLock() {
-        StampedLock sl = new StampedLock();
-        Lock lock = sl.asReadWriteLock().writeLock();
-        lock.lock();
-        assertFalse(lock.tryLock());
-        lock.unlock();
-        assertTrue(lock.tryLock());
-    }
-
-    /**
-     * asReadWriteLock.readLock can be locked and unlocked
-     */
-    public void testAsReadWriteLockReadLock() {
-        StampedLock sl = new StampedLock();
-        Lock lock = sl.asReadWriteLock().readLock();
-        lock.lock();
-        lock.unlock();
-        assertTrue(lock.tryLock());
-    }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java b/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
index 9d3f212..605a955 100644
--- a/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
@@ -25,7 +25,7 @@
 
 public class SynchronousQueueTest extends JSR166TestCase {
 
-    // android-note: These tests have been moved into their own separate
+    // android-note: These tests have been moved into their own separate 
     // classes to work around CTS issues.
     //
     // public static class Fair extends BlockingQueueTest {
@@ -33,19 +33,17 @@
     //         return new SynchronousQueue(true);
     //     }
     // }
-
+    //
     // public static class NonFair extends BlockingQueueTest {
     //     protected BlockingQueue emptyCollection() {
     //         return new SynchronousQueue(false);
     //     }
     // }
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
     //
     // public static void main(String[] args) {
     //     main(suite(), args);
     // }
+    //
     // public static Test suite() {
     //     return newTestSuite(SynchronousQueueTest.class,
     //                         new Fair().testSuite(),
@@ -264,6 +262,7 @@
                 pleaseOffer.countDown();
                 startTime = System.nanoTime();
                 assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                assertTrue(millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
 
                 Thread.currentThread().interrupt();
                 try {
@@ -278,15 +277,13 @@
                     shouldThrow();
                 } catch (InterruptedException success) {}
                 assertFalse(Thread.interrupted());
-
-                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             }});
 
         await(pleaseOffer);
         long startTime = System.nanoTime();
         try { assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS)); }
         catch (InterruptedException e) { threadUnexpectedException(e); }
-        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        assertTrue(millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
 
         await(pleaseInterrupt);
         assertThreadStaysAlive(t);
@@ -477,24 +474,24 @@
     public void testOfferInExecutor_fair() { testOfferInExecutor(true); }
     public void testOfferInExecutor(boolean fair) {
         final SynchronousQueue q = new SynchronousQueue(fair);
+        ExecutorService executor = Executors.newFixedThreadPool(2);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertFalse(q.offer(one));
-                    threadsStarted.await();
-                    assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS));
-                    assertEquals(0, q.remainingCapacity());
-                }});
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertFalse(q.offer(one));
+                threadsStarted.await();
+                assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS));
+                assertEquals(0, q.remainingCapacity());
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    assertSame(one, q.take());
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                assertSame(one, q.take());
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -505,22 +502,22 @@
     public void testPollInExecutor(boolean fair) {
         final SynchronousQueue q = new SynchronousQueue(fair);
         final CheckedBarrier threadsStarted = new CheckedBarrier(2);
-        final ExecutorService executor = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(executor)) {
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    assertNull(q.poll());
-                    threadsStarted.await();
-                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
-                    assertTrue(q.isEmpty());
-                }});
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                assertNull(q.poll());
+                threadsStarted.await();
+                assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+                assertTrue(q.isEmpty());
+            }});
 
-            executor.execute(new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    threadsStarted.await();
-                    q.put(one);
-                }});
-        }
+        executor.execute(new CheckedRunnable() {
+            public void realRun() throws InterruptedException {
+                threadsStarted.await();
+                q.put(one);
+            }});
+
+        joinPool(executor);
     }
 
     /**
@@ -598,12 +595,10 @@
             }});
 
         ArrayList l = new ArrayList();
-        int drained;
-        while ((drained = q.drainTo(l, 1)) == 0) Thread.yield();
-        assertEquals(1, drained);
+        delay(SHORT_DELAY_MS);
+        q.drainTo(l, 1);
         assertEquals(1, l.size());
-        while ((drained = q.drainTo(l, 1)) == 0) Thread.yield();
-        assertEquals(1, drained);
+        q.drainTo(l, 1);
         assertEquals(2, l.size());
         assertTrue(l.contains(one));
         assertTrue(l.contains(two));
diff --git a/jsr166-tests/src/test/java/jsr166/SystemTest.java b/jsr166-tests/src/test/java/jsr166/SystemTest.java
index 412ce17..6918374 100644
--- a/jsr166-tests/src/test/java/jsr166/SystemTest.java
+++ b/jsr166-tests/src/test/java/jsr166/SystemTest.java
@@ -19,7 +19,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(SystemTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadLocalRandom8Test.java b/jsr166-tests/src/test/java/jsr166/ThreadLocalRandom8Test.java
deleted file mode 100644
index 614af83..0000000
--- a/jsr166-tests/src/test/java/jsr166/ThreadLocalRandom8Test.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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 jsr166;
-
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.LongAdder;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class ThreadLocalRandom8Test extends JSR166TestCase {
-
-    // android-note: Removed because the CTS runner does a bad job of
-    // retrying tests that have suite() declarations.
-    //
-    // public static void main(String[] args) {
-    //     main(suite(), args);
-    // }
-    // public static Test suite() {
-    //     return new TestSuite(ThreadLocalRandom8Test.class);
-    // }
-
-    // max sampled int bound
-    static final int MAX_INT_BOUND = (1 << 26);
-
-    // max sampled long bound
-    static final long MAX_LONG_BOUND = (1L << 42);
-
-    // Number of replications for other checks
-    static final int REPS =
-        Integer.getInteger("ThreadLocalRandom8Test.reps", 4);
-
-    /**
-     * Invoking sized ints, long, doubles, with negative sizes throws
-     * IllegalArgumentException
-     */
-    // TODO(streams):
-    // public void testBadStreamSize() {
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     Runnable[] throwingActions = {
-    //         () -> r.ints(-1L),
-    //         () -> r.ints(-1L, 2, 3),
-    //         () -> r.longs(-1L),
-    //         () -> r.longs(-1L, -1L, 1L),
-    //         () -> r.doubles(-1L),
-    //         () -> r.doubles(-1L, .5, .6),
-    //     };
-    //     assertThrows(IllegalArgumentException.class, throwingActions);
-    // }
-
-    // /**
-    //  * Invoking bounded ints, long, doubles, with illegal bounds throws
-    //  * IllegalArgumentException
-    //  */
-    // public void testBadStreamBounds() {
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     Runnable[] throwingActions = {
-    //         () -> r.ints(2, 1),
-    //         () -> r.ints(10, 42, 42),
-    //         () -> r.longs(-1L, -1L),
-    //         () -> r.longs(10, 1L, -2L),
-    //         () -> r.doubles(0.0, 0.0),
-    //         () -> r.doubles(10, .5, .4),
-    //     };
-    //     assertThrows(IllegalArgumentException.class, throwingActions);
-    // }
-
-    // /**
-    //  * A parallel sized stream of ints generates the given number of values
-    //  */
-    // public void testIntsCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 0;
-    //     for (int reps = 0; reps < REPS; ++reps) {
-    //         counter.reset();
-    //         r.ints(size).parallel().forEach(x -> counter.increment());
-    //         assertEquals(size, counter.sum());
-    //         size += 524959;
-    //     }
-    // }
-
-    // /**
-    //  * A parallel sized stream of longs generates the given number of values
-    //  */
-    // public void testLongsCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 0;
-    //     for (int reps = 0; reps < REPS; ++reps) {
-    //         counter.reset();
-    //         r.longs(size).parallel().forEach(x -> counter.increment());
-    //         assertEquals(size, counter.sum());
-    //         size += 524959;
-    //     }
-    // }
-
-    // /**
-    //  * A parallel sized stream of doubles generates the given number of values
-    //  */
-    // public void testDoublesCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 0;
-    //     for (int reps = 0; reps < REPS; ++reps) {
-    //         counter.reset();
-    //         r.doubles(size).parallel().forEach(x -> counter.increment());
-    //         assertEquals(size, counter.sum());
-    //         size += 524959;
-    //     }
-    // }
-
-    // /**
-    //  * Each of a parallel sized stream of bounded ints is within bounds
-    //  */
-    // public void testBoundedInts() {
-    //     AtomicInteger fails = new AtomicInteger(0);
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 12345L;
-    //     for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
-    //         for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
-    //             final int lo = least, hi = bound;
-    //             r.ints(size, lo, hi).parallel().forEach(
-    //                 x -> {
-    //                     if (x < lo || x >= hi)
-    //                         fails.getAndIncrement(); });
-    //         }
-    //     }
-    //     assertEquals(0, fails.get());
-    // }
-
-    // /**
-    //  * Each of a parallel sized stream of bounded longs is within bounds
-    //  */
-    // public void testBoundedLongs() {
-    //     AtomicInteger fails = new AtomicInteger(0);
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 123L;
-    //     for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
-    //         for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
-    //             final long lo = least, hi = bound;
-    //             r.longs(size, lo, hi).parallel().forEach(
-    //                 x -> {
-    //                     if (x < lo || x >= hi)
-    //                         fails.getAndIncrement(); });
-    //         }
-    //     }
-    //     assertEquals(0, fails.get());
-    // }
-
-    // /**
-    //  * Each of a parallel sized stream of bounded doubles is within bounds
-    //  */
-    // public void testBoundedDoubles() {
-    //     AtomicInteger fails = new AtomicInteger(0);
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 456;
-    //     for (double least = 0.00011; least < 1.0e20; least *= 9) {
-    //         for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
-    //             final double lo = least, hi = bound;
-    //             r.doubles(size, lo, hi).parallel().forEach(
-    //                 x -> {
-    //                     if (x < lo || x >= hi)
-    //                         fails.getAndIncrement(); });
-    //         }
-    //     }
-    //     assertEquals(0, fails.get());
-    // }
-
-    // /**
-    //  * A parallel unsized stream of ints generates at least 100 values
-    //  */
-    // public void testUnsizedIntsCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.ints().limit(size).parallel().forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-    // /**
-    //  * A parallel unsized stream of longs generates at least 100 values
-    //  */
-    // public void testUnsizedLongsCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.longs().limit(size).parallel().forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-    // /**
-    //  * A parallel unsized stream of doubles generates at least 100 values
-    //  */
-    // public void testUnsizedDoublesCount() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.doubles().limit(size).parallel().forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-    // /**
-    //  * A sequential unsized stream of ints generates at least 100 values
-    //  */
-    // public void testUnsizedIntsCountSeq() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.ints().limit(size).forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-    // /**
-    //  * A sequential unsized stream of longs generates at least 100 values
-    //  */
-    // public void testUnsizedLongsCountSeq() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.longs().limit(size).forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-    // /**
-    //  * A sequential unsized stream of doubles generates at least 100 values
-    //  */
-    // public void testUnsizedDoublesCountSeq() {
-    //     LongAdder counter = new LongAdder();
-    //     ThreadLocalRandom r = ThreadLocalRandom.current();
-    //     long size = 100;
-    //     r.doubles().limit(size).forEach(x -> counter.increment());
-    //     assertEquals(size, counter.sum());
-    // }
-
-}
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadLocalRandomTest.java b/jsr166-tests/src/test/java/jsr166/ThreadLocalRandomTest.java
index 5d9f894..4ae141d 100644
--- a/jsr166-tests/src/test/java/jsr166/ThreadLocalRandomTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ThreadLocalRandomTest.java
@@ -22,7 +22,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ThreadLocalRandomTest.class);
+    //     return new TestSuite(...);
     // }
 
     /*
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadLocalTest.java b/jsr166-tests/src/test/java/jsr166/ThreadLocalTest.java
index 8bfcf70..7f5f072 100644
--- a/jsr166-tests/src/test/java/jsr166/ThreadLocalTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ThreadLocalTest.java
@@ -19,7 +19,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ThreadLocalTest.class);
+    //     return new TestSuite(...);
     // }
 
     static ThreadLocal<Integer> tl = new ThreadLocal<Integer>() {
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorSubclassTest.java b/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorSubclassTest.java
index a502392..5f38d39 100644
--- a/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorSubclassTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorSubclassTest.java
@@ -9,14 +9,12 @@
 package jsr166;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
@@ -32,7 +30,6 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -47,7 +44,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ThreadPoolExecutorSubclassTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class CustomTask<V> implements RunnableFuture<V> {
@@ -106,13 +103,11 @@
             }
             lock.lock();
             try {
-                if (!done) {
-                    result = v;
-                    exception = e;
-                    done = true;
-                    thread = null;
-                    cond.signalAll();
-                }
+                result = v;
+                exception = e;
+                done = true;
+                thread = null;
+                cond.signalAll();
             }
             finally { lock.unlock(); }
         }
@@ -121,8 +116,6 @@
             try {
                 while (!done)
                     cond.await();
-                if (cancelled)
-                    throw new CancellationException();
                 if (exception != null)
                     throw new ExecutionException(exception);
                 return result;
@@ -134,13 +127,12 @@
             long nanos = unit.toNanos(timeout);
             lock.lock();
             try {
-                while (!done) {
-                    if (nanos <= 0L)
+                for (;;) {
+                    if (done) break;
+                    if (nanos < 0)
                         throw new TimeoutException();
                     nanos = cond.awaitNanos(nanos);
                 }
-                if (cancelled)
-                    throw new CancellationException();
                 if (exception != null)
                     throw new ExecutionException(exception);
                 return result;
@@ -237,14 +229,18 @@
     public void testExecute() throws InterruptedException {
         final ThreadPoolExecutor p =
             new CustomTPE(1, 1,
-                          2 * LONG_DELAY_MS, MILLISECONDS,
+                          LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Runnable task = new CheckedRunnable() {
-                public void realRun() { done.countDown(); }};
+        final CountDownLatch done = new CountDownLatch(1);
+        final Runnable task = new CheckedRunnable() {
+            public void realRun() {
+                done.countDown();
+            }};
+        try {
             p.execute(task);
-            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
+            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -253,22 +249,25 @@
      * thread becomes active
      */
     public void testGetActiveCount() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new CustomTPE(2, 2,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getActiveCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getActiveCount());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getActiveCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -276,48 +275,28 @@
      * prestartCoreThread starts a thread if under corePoolSize, else doesn't
      */
     public void testPrestartCoreThread() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 6,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(0, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(1, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(2, p.getPoolSize());
-            assertFalse(p.prestartCoreThread());
-            assertEquals(2, p.getPoolSize());
-            p.setCorePoolSize(4);
-            assertTrue(p.prestartCoreThread());
-            assertEquals(3, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(4, p.getPoolSize());
-            assertFalse(p.prestartCoreThread());
-            assertEquals(4, p.getPoolSize());
-        }
+        ThreadPoolExecutor p = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertEquals(0, p.getPoolSize());
+        assertTrue(p.prestartCoreThread());
+        assertEquals(1, p.getPoolSize());
+        assertTrue(p.prestartCoreThread());
+        assertEquals(2, p.getPoolSize());
+        assertFalse(p.prestartCoreThread());
+        assertEquals(2, p.getPoolSize());
+        joinPool(p);
     }
 
     /**
      * prestartAllCoreThreads starts all corePoolSize threads
      */
     public void testPrestartAllCoreThreads() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 6,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(0, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(2, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(2, p.getPoolSize());
-            p.setCorePoolSize(4);
-            p.prestartAllCoreThreads();
-            assertEquals(4, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(4, p.getPoolSize());
-        }
+        ThreadPoolExecutor p = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertEquals(0, p.getPoolSize());
+        p.prestartAllCoreThreads();
+        assertEquals(2, p.getPoolSize());
+        p.prestartAllCoreThreads();
+        assertEquals(2, p.getPoolSize());
+        joinPool(p);
     }
 
     /**
@@ -329,10 +308,10 @@
             new CustomTPE(2, 2,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch threadProceed = new CountDownLatch(1);
-            final CountDownLatch threadDone = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadProceed = new CountDownLatch(1);
+        final CountDownLatch threadDone = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
@@ -351,6 +330,8 @@
                     fail("timed out");
                 Thread.yield();
             }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -358,72 +339,52 @@
      * getCorePoolSize returns size given in constructor if not otherwise set
      */
     public void testGetCorePoolSize() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getCorePoolSize());
-        }
+        ThreadPoolExecutor p = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertEquals(1, p.getCorePoolSize());
+        joinPool(p);
     }
 
     /**
      * getKeepAliveTime returns value given in constructor if not otherwise set
      */
     public void testGetKeepAliveTime() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 2,
-                          1000, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getKeepAliveTime(SECONDS));
-        }
+        ThreadPoolExecutor p = new CustomTPE(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertEquals(1, p.getKeepAliveTime(TimeUnit.SECONDS));
+        joinPool(p);
     }
 
     /**
      * getThreadFactory returns factory in constructor if not set
      */
     public void testGetThreadFactory() {
-        final ThreadFactory threadFactory = new SimpleThreadFactory();
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          threadFactory,
-                          new NoOpREHandler());
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), tf, new NoOpREHandler());
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory sets the thread factory returned by getThreadFactory
      */
     public void testSetThreadFactory() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            ThreadFactory threadFactory = new SimpleThreadFactory();
-            p.setThreadFactory(threadFactory);
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        ThreadFactory tf = new SimpleThreadFactory();
+        p.setThreadFactory(tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
      * setThreadFactory(null) throws NPE
      */
     public void testSetThreadFactoryNull() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setThreadFactory(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            p.setThreadFactory(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -431,15 +392,10 @@
      * getRejectedExecutionHandler returns handler in constructor if not set
      */
     public void testGetRejectedExecutionHandler() {
-        final RejectedExecutionHandler handler = new NoOpREHandler();
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          handler);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(handler, p.getRejectedExecutionHandler());
-        }
+        RejectedExecutionHandler h = new NoOpREHandler();
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), h);
+        assertSame(h, p.getRejectedExecutionHandler());
+        joinPool(p);
     }
 
     /**
@@ -447,30 +403,24 @@
      * getRejectedExecutionHandler
      */
     public void testSetRejectedExecutionHandler() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            RejectedExecutionHandler handler = new NoOpREHandler();
-            p.setRejectedExecutionHandler(handler);
-            assertSame(handler, p.getRejectedExecutionHandler());
-        }
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        RejectedExecutionHandler h = new NoOpREHandler();
+        p.setRejectedExecutionHandler(h);
+        assertSame(h, p.getRejectedExecutionHandler());
+        joinPool(p);
     }
 
     /**
      * setRejectedExecutionHandler(null) throws NPE
      */
     public void testSetRejectedExecutionHandlerNull() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setRejectedExecutionHandler(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            p.setRejectedExecutionHandler(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -480,25 +430,28 @@
      */
     public void testGetLargestPoolSize() throws InterruptedException {
         final int THREADS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new CustomTPE(THREADS, THREADS,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getLargestPoolSize());
-            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
             for (int i = 0; i < THREADS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadsStarted.countDown();
-                        await(done);
+                        done.await();
                         assertEquals(THREADS, p.getLargestPoolSize());
                     }});
-            await(threadsStarted);
+            assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(THREADS, p.getLargestPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
             assertEquals(THREADS, p.getLargestPoolSize());
         }
-        assertEquals(THREADS, p.getLargestPoolSize());
     }
 
     /**
@@ -506,17 +459,9 @@
      * otherwise set
      */
     public void testGetMaximumPoolSize() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 3,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(3, p.getMaximumPoolSize());
-            p.setMaximumPoolSize(5);
-            assertEquals(5, p.getMaximumPoolSize());
-            p.setMaximumPoolSize(4);
-            assertEquals(4, p.getMaximumPoolSize());
-        }
+        ThreadPoolExecutor p = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertEquals(2, p.getMaximumPoolSize());
+        joinPool(p);
     }
 
     /**
@@ -524,22 +469,25 @@
      * become active
      */
     public void testGetPoolSize() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getPoolSize());
-            final CountDownLatch threadStarted = new CountDownLatch(1);
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getPoolSize());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -547,53 +495,38 @@
      * getTaskCount increases, but doesn't overestimate, when tasks submitted
      */
     public void testGetTaskCount() throws InterruptedException {
-        final int TASKS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
-                    await(done);
+                    assertEquals(1, p.getTaskCount());
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            for (int i = 0; i < TASKS; i++) {
-                assertEquals(1 + i, p.getTaskCount());
-                p.execute(new CheckedRunnable() {
-                    public void realRun() throws InterruptedException {
-                        threadStarted.countDown();
-                        assertEquals(1 + TASKS, p.getTaskCount());
-                        await(done);
-                    }});
-            }
-            assertEquals(1 + TASKS, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
-        assertEquals(1 + TASKS, p.getTaskCount());
-        assertEquals(1 + TASKS, p.getCompletedTaskCount());
     }
 
     /**
      * isShutdown is false before shutdown, true after
      */
     public void testIsShutdown() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.isShutdown());
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.isShutdown());
-        }
+
+        ThreadPoolExecutor p = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertFalse(p.isShutdown());
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.isShutdown());
+        joinPool(p);
     }
 
     /**
@@ -604,24 +537,25 @@
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch done = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertFalse(p.isTerminating());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminating());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
+        assertFalse(p.isTerminating());
     }
 
     /**
@@ -632,55 +566,59 @@
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch done = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertFalse(p.isTerminating());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminating());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
+        assertFalse(p.isTerminating());
     }
 
     /**
      * getQueue returns the work queue, which contains queued tasks
      */
     public void testGetQueue() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
         final ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             FutureTask[] tasks = new FutureTask[5];
             for (int i = 0; i < tasks.length; i++) {
                 Callable task = new CheckedCallable<Boolean>() {
                     public Boolean realCall() throws InterruptedException {
                         threadStarted.countDown();
                         assertSame(q, p.getQueue());
-                        await(done);
+                        done.await();
                         return Boolean.TRUE;
                     }};
                 tasks[i] = new FutureTask(task);
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertSame(q, p.getQueue());
             assertFalse(q.contains(tasks[0]));
             assertTrue(q.contains(tasks[tasks.length - 1]));
             assertEquals(tasks.length - 1, q.size());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -688,24 +626,24 @@
      * remove(task) removes queued task, and fails to remove active task
      */
     public void testRemove() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
         final ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            Runnable[] tasks = new Runnable[6];
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        Runnable[] tasks = new Runnable[6];
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 tasks[i] = new CheckedRunnable() {
-                    public void realRun() throws InterruptedException {
-                        threadStarted.countDown();
-                        await(done);
-                    }};
+                        public void realRun() throws InterruptedException {
+                            threadStarted.countDown();
+                            done.await();
+                        }};
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.remove(tasks[0]));
             assertTrue(q.contains(tasks[4]));
             assertTrue(q.contains(tasks[3]));
@@ -715,6 +653,9 @@
             assertTrue(q.contains(tasks[3]));
             assertTrue(p.remove(tasks[3]));
             assertFalse(q.contains(tasks[3]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -729,19 +670,19 @@
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            FutureTask[] tasks = new FutureTask[5];
+        FutureTask[] tasks = new FutureTask[5];
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 Callable task = new CheckedCallable<Boolean>() {
                     public Boolean realCall() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                         return Boolean.TRUE;
                     }};
                 tasks[i] = new FutureTask(task);
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(tasks.length, p.getTaskCount());
             assertEquals(tasks.length - 1, q.size());
             assertEquals(1L, p.getActiveCount());
@@ -754,47 +695,29 @@
             p.purge();         // Nothing to do
             assertEquals(tasks.length - 3, q.size());
             assertEquals(tasks.length - 2, p.getTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * shutdownNow returns a list containing tasks that were not run
      */
-    public void testShutdownNow() throws InterruptedException {
-        final int poolSize = 2;
-        final int count = 5;
-        final AtomicInteger ran = new AtomicInteger(0);
-        final ThreadPoolExecutor p =
-            new CustomTPE(poolSize, poolSize,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
-        Runnable waiter = new CheckedRunnable() { public void realRun() {
-            threadsStarted.countDown();
-            try {
-                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
-            } catch (InterruptedException success) {}
-            ran.getAndIncrement();
-        }};
-        for (int i = 0; i < count; i++)
-            p.execute(waiter);
-        await(threadsStarted);
-        assertEquals(poolSize, p.getActiveCount());
-        assertEquals(0, p.getCompletedTaskCount());
-        final List<Runnable> queuedTasks;
+    public void testShutdownNow() {
+        ThreadPoolExecutor p = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List l;
         try {
-            queuedTasks = p.shutdownNow();
-        } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
+            for (int i = 0; i < 5; i++)
+                p.execute(new MediumPossiblyInterruptedRunnable());
+        }
+        finally {
+            try {
+                l = p.shutdownNow();
+            } catch (SecurityException ok) { return; }
         }
         assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        assertEquals(count - poolSize, queuedTasks.size());
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(p.isTerminated());
-        assertEquals(poolSize, ran.get());
-        assertEquals(poolSize, p.getCompletedTaskCount());
+        assertTrue(l.size() <= 4);
     }
 
     // Exception Tests
@@ -804,8 +727,7 @@
      */
     public void testConstructor1() {
         try {
-            new CustomTPE(-1, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
+            new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -815,8 +737,7 @@
      */
     public void testConstructor2() {
         try {
-            new CustomTPE(1, -1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
+            new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -826,8 +747,7 @@
      */
     public void testConstructor3() {
         try {
-            new CustomTPE(1, 0, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
+            new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -837,8 +757,7 @@
      */
     public void testConstructor4() {
         try {
-            new CustomTPE(1, 2, -1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
+            new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -848,8 +767,7 @@
      */
     public void testConstructor5() {
         try {
-            new CustomTPE(2, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
+            new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -859,7 +777,7 @@
      */
     public void testConstructorNullPointerException() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS, null);
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -869,9 +787,7 @@
      */
     public void testConstructor6() {
         try {
-            new CustomTPE(-1, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory());
+            new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -881,9 +797,7 @@
      */
     public void testConstructor7() {
         try {
-            new CustomTPE(1,-1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory());
+            new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -893,9 +807,7 @@
      */
     public void testConstructor8() {
         try {
-            new CustomTPE(1, 0, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory());
+            new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -905,9 +817,7 @@
      */
     public void testConstructor9() {
         try {
-            new CustomTPE(1, 2, -1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory());
+            new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -917,9 +827,7 @@
      */
     public void testConstructor10() {
         try {
-            new CustomTPE(2, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory());
+            new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -929,7 +837,7 @@
      */
     public void testConstructorNullPointerException2() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS, null, new SimpleThreadFactory());
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory());
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -939,9 +847,8 @@
      */
     public void testConstructorNullPointerException3() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          (ThreadFactory) null);
+            ThreadFactory f = null;
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -951,9 +858,7 @@
      */
     public void testConstructor11() {
         try {
-            new CustomTPE(-1, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new NoOpREHandler());
+            new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -963,9 +868,7 @@
      */
     public void testConstructor12() {
         try {
-            new CustomTPE(1, -1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new NoOpREHandler());
+            new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -975,9 +878,7 @@
      */
     public void testConstructor13() {
         try {
-            new CustomTPE(1, 0, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new NoOpREHandler());
+            new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -987,9 +888,7 @@
      */
     public void testConstructor14() {
         try {
-            new CustomTPE(1, 2, -1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new NoOpREHandler());
+            new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -999,9 +898,7 @@
      */
     public void testConstructor15() {
         try {
-            new CustomTPE(2, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new NoOpREHandler());
+            new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1011,9 +908,7 @@
      */
     public void testConstructorNullPointerException4() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
-                          null,
-                          new NoOpREHandler());
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new NoOpREHandler());
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -1023,9 +918,8 @@
      */
     public void testConstructorNullPointerException5() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          (RejectedExecutionHandler) null);
+            RejectedExecutionHandler r = null;
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),r);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -1035,10 +929,7 @@
      */
     public void testConstructor16() {
         try {
-            new CustomTPE(-1, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1048,10 +939,7 @@
      */
     public void testConstructor17() {
         try {
-            new CustomTPE(1, -1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1061,10 +949,7 @@
      */
     public void testConstructor18() {
         try {
-            new CustomTPE(1, 0, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1074,10 +959,7 @@
      */
     public void testConstructor19() {
         try {
-            new CustomTPE(1, 2, -1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1087,10 +969,7 @@
      */
     public void testConstructor20() {
         try {
-            new CustomTPE(2, 1, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -1100,10 +979,7 @@
      */
     public void testConstructorNullPointerException6() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
-                          null,
-                          new SimpleThreadFactory(),
-                          new NoOpREHandler());
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory(),new NoOpREHandler());
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -1113,10 +989,8 @@
      */
     public void testConstructorNullPointerException7() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10),
-                          new SimpleThreadFactory(),
-                          (RejectedExecutionHandler) null);
+            RejectedExecutionHandler r = null;
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),r);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -1126,7 +1000,8 @@
      */
     public void testConstructorNullPointerException8() {
         try {
-            new CustomTPE(1, 2, 1L, SECONDS,
+            new CustomTPE(1, 2,
+                          LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10),
                           (ThreadFactory) null,
                           new NoOpREHandler());
@@ -1138,15 +1013,15 @@
      * execute throws RejectedExecutionException if saturated.
      */
     public void testSaturatedExecute() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(1));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
-                    await(done);
+                    done.await();
                 }};
             for (int i = 0; i < 2; ++i)
                 p.execute(task);
@@ -1157,6 +1032,9 @@
                 } catch (RejectedExecutionException success) {}
                 assertTrue(p.getTaskCount() <= 2);
             }
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -1164,26 +1042,24 @@
      * executor using CallerRunsPolicy runs task if saturated.
      */
     public void testSaturatedExecute2() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.CallerRunsPolicy());
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            Runnable blocker = new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    await(done);
-                }};
-            p.execute(blocker);
+        RejectedExecutionHandler h = new CustomTPE.CallerRunsPolicy();
+        ThreadPoolExecutor p = new CustomTPE(1, 1,
+                                             LONG_DELAY_MS, MILLISECONDS,
+                                             new ArrayBlockingQueue<Runnable>(1),
+                                             h);
+        try {
             TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
-            for (int i = 0; i < tasks.length; i++)
+            for (int i = 0; i < tasks.length; ++i)
                 tasks[i] = new TrackedNoOpRunnable();
-            for (int i = 0; i < tasks.length; i++)
+            TrackedLongRunnable mr = new TrackedLongRunnable();
+            p.execute(mr);
+            for (int i = 0; i < tasks.length; ++i)
                 p.execute(tasks[i]);
-            for (int i = 1; i < tasks.length; i++)
+            for (int i = 1; i < tasks.length; ++i)
                 assertTrue(tasks[i].done);
-            assertFalse(tasks[0].done); // waiting in queue
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1191,88 +1067,77 @@
      * executor using DiscardPolicy drops task if saturated.
      */
     public void testSaturatedExecute3() {
-        final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
-        for (int i = 0; i < tasks.length; ++i)
-            tasks[i] = new TrackedNoOpRunnable();
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
+        RejectedExecutionHandler h = new CustomTPE.DiscardPolicy();
+        ThreadPoolExecutor p =
             new CustomTPE(1, 1,
                           LONG_DELAY_MS, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.DiscardPolicy());
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            p.execute(awaiter(done));
-
+                          h);
+        try {
+            TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
+            for (int i = 0; i < tasks.length; ++i)
+                tasks[i] = new TrackedNoOpRunnable();
+            p.execute(new TrackedLongRunnable());
             for (TrackedNoOpRunnable task : tasks)
                 p.execute(task);
-            for (int i = 1; i < tasks.length; i++)
-                assertFalse(tasks[i].done);
+            for (TrackedNoOpRunnable task : tasks)
+                assertFalse(task.done);
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
-        for (int i = 1; i < tasks.length; i++)
-            assertFalse(tasks[i].done);
-        assertTrue(tasks[0].done); // was waiting in queue
     }
 
     /**
      * executor using DiscardOldestPolicy drops oldest task if saturated.
      */
     public void testSaturatedExecute4() {
-        final CountDownLatch done = new CountDownLatch(1);
-        LatchAwaiter r1 = awaiter(done);
-        LatchAwaiter r2 = awaiter(done);
-        LatchAwaiter r3 = awaiter(done);
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.DiscardOldestPolicy());
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            assertEquals(LatchAwaiter.NEW, r1.state);
-            assertEquals(LatchAwaiter.NEW, r2.state);
-            assertEquals(LatchAwaiter.NEW, r3.state);
-            p.execute(r1);
+        RejectedExecutionHandler h = new CustomTPE.DiscardOldestPolicy();
+        ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+        try {
+            p.execute(new TrackedLongRunnable());
+            TrackedLongRunnable r2 = new TrackedLongRunnable();
             p.execute(r2);
             assertTrue(p.getQueue().contains(r2));
+            TrackedNoOpRunnable r3 = new TrackedNoOpRunnable();
             p.execute(r3);
             assertFalse(p.getQueue().contains(r2));
             assertTrue(p.getQueue().contains(r3));
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
-        assertEquals(LatchAwaiter.DONE, r1.state);
-        assertEquals(LatchAwaiter.NEW, r2.state);
-        assertEquals(LatchAwaiter.DONE, r3.state);
     }
 
     /**
      * execute throws RejectedExecutionException if shutdown
      */
     public void testRejectedExecutionExceptionOnShutdown() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1));
+        ThreadPoolExecutor p =
+            new CustomTPE(1,1,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(1));
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(new NoOpRunnable());
-                shouldThrow();
-            } catch (RejectedExecutionException success) {}
-        }
+        try {
+            p.execute(new NoOpRunnable());
+            shouldThrow();
+        } catch (RejectedExecutionException success) {}
+
+        joinPool(p);
     }
 
     /**
      * execute using CallerRunsPolicy drops task on shutdown
      */
     public void testCallerRunsOnShutdown() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.CallerRunsPolicy());
+        RejectedExecutionHandler h = new CustomTPE.CallerRunsPolicy();
+        ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1280,16 +1145,16 @@
      * execute using DiscardPolicy drops task on shutdown
      */
     public void testDiscardOnShutdown() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.DiscardPolicy());
+        RejectedExecutionHandler h = new CustomTPE.DiscardPolicy();
+        ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1297,17 +1162,16 @@
      * execute using DiscardOldestPolicy drops task on shutdown
      */
     public void testDiscardOldestOnShutdown() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new CustomTPE.DiscardOldestPolicy());
+        RejectedExecutionHandler h = new CustomTPE.DiscardOldestPolicy();
+        ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
 
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1315,32 +1179,30 @@
      * execute(null) throws NPE
      */
     public void testExecuteNull() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          1L, SECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        ThreadPoolExecutor p = null;
+        try {
+            p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+            p.execute(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+
+        joinPool(p);
     }
 
     /**
      * setCorePoolSize of negative value throws IllegalArgumentException
      */
     public void testCorePoolSizeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(1, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setCorePoolSize(-1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ThreadPoolExecutor p =
+            new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+        try {
+            p.setCorePoolSize(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1348,16 +1210,16 @@
      * if given a value less the core pool size
      */
     public void testMaximumPoolSizeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 3,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setMaximumPoolSize(1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ThreadPoolExecutor p =
+            new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+        try {
+            p.setMaximumPoolSize(1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1365,16 +1227,16 @@
      * if given a negative value
      */
     public void testMaximumPoolSizeIllegalArgumentException2() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 3,
-                          LONG_DELAY_MS,
-                          MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setMaximumPoolSize(-1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ThreadPoolExecutor p =
+            new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+        try {
+            p.setMaximumPoolSize(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1382,16 +1244,17 @@
      * when given a negative value
      */
     public void testKeepAliveTimeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 3,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setKeepAliveTime(-1, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ThreadPoolExecutor p =
+            new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+
+        try {
+            p.setKeepAliveTime(-1,MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1399,11 +1262,9 @@
      */
     public void testTerminated() {
         CustomTPE p = new CustomTPE();
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.terminatedCalled());
-            assertTrue(p.isShutdown());
-        }
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.terminatedCalled());
+        joinPool(p);
     }
 
     /**
@@ -1411,7 +1272,7 @@
      */
     public void testBeforeAfter() throws InterruptedException {
         CustomTPE p = new CustomTPE();
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             final CountDownLatch done = new CountDownLatch(1);
             p.execute(new CheckedRunnable() {
                 public void realRun() {
@@ -1421,6 +1282,9 @@
             assertEquals(0, done.getCount());
             assertTrue(p.afterCalled());
             assertTrue(p.beforeCalled());
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1428,14 +1292,13 @@
      * completed submit of callable returns result
      */
     public void testSubmitCallable() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             Future<String> future = e.submit(new StringTask());
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1443,14 +1306,13 @@
      * completed submit of runnable returns successfully
      */
     public void testSubmitRunnable() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             Future<?> future = e.submit(new NoOpRunnable());
             future.get();
             assertTrue(future.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1458,14 +1320,13 @@
      * completed submit of (runnable, result) returns result
      */
     public void testSubmitRunnable2() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1473,15 +1334,13 @@
      * invokeAny(null) throws NPE
      */
     public void testInvokeAny1() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1489,15 +1348,13 @@
      * invokeAny(empty collection) throws IAE
      */
     public void testInvokeAny2() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1506,19 +1363,17 @@
      */
     public void testInvokeAny3() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1526,19 +1381,16 @@
      * invokeAny(c) throws ExecutionException if no task completes
      */
     public void testInvokeAny4() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1546,16 +1398,15 @@
      * invokeAny(c) returns result of some task
      */
     public void testInvokeAny5() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1563,15 +1414,13 @@
      * invokeAll(null) throws NPE
      */
     public void testInvokeAll1() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1579,13 +1428,12 @@
      * invokeAll(empty collection) returns empty collection
      */
     public void testInvokeAll2() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1593,18 +1441,16 @@
      * invokeAll(c) throws NPE if c has null elements
      */
     public void testInvokeAll3() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1612,21 +1458,18 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testInvokeAll4() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures = e.invokeAll(l);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures = e.invokeAll(l);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1634,11 +1477,8 @@
      * invokeAll(c) returns results of all completed tasks
      */
     public void testInvokeAll5() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -1646,6 +1486,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1653,15 +1495,13 @@
      * timed invokeAny(null) throws NPE
      */
     public void testTimedInvokeAny1() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1669,17 +1509,15 @@
      * timed invokeAny(,,null) throws NPE
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1687,16 +1525,13 @@
      * timed invokeAny(empty collection) throws IAE
      */
     public void testTimedInvokeAny2() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(),
-                            MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1705,19 +1540,17 @@
      */
     public void testTimedInvokeAny3() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1725,21 +1558,16 @@
      * timed invokeAny(c) throws ExecutionException if no task completes
      */
     public void testTimedInvokeAny4() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1747,18 +1575,15 @@
      * timed invokeAny(c) returns result of some task
      */
     public void testTimedInvokeAny5() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1766,15 +1591,13 @@
      * timed invokeAll(null) throws NPE
      */
     public void testTimedInvokeAll1() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1782,17 +1605,15 @@
      * timed invokeAll(,,null) throws NPE
      */
     public void testTimedInvokeAllNullTimeUnit() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1800,14 +1621,12 @@
      * timed invokeAll(empty collection) returns empty collection
      */
     public void testTimedInvokeAll2() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(),
-                                                 MEDIUM_DELAY_MS, MILLISECONDS);
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1815,18 +1634,16 @@
      * timed invokeAll(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAll3() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1834,22 +1651,19 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testTimedInvokeAll4() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures =
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1857,19 +1671,18 @@
      * timed invokeAll(c) returns results of all completed tasks
      */
     public void testTimedInvokeAll5() throws Exception {
-        final ExecutorService e =
-            new CustomTPE(2, 2,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1877,40 +1690,21 @@
      * timed invokeAll(c) cancels tasks not completed by timeout
      */
     public void testTimedInvokeAll6() throws Exception {
-        for (long timeout = timeoutMillis();;) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Callable<String> waiter = new CheckedCallable<String>() {
-                public String realCall() {
-                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
-                    catch (InterruptedException ok) {}
-                    return "1"; }};
-            final ExecutorService p =
-                new CustomTPE(2, 2,
-                              LONG_DELAY_MS, MILLISECONDS,
-                              new ArrayBlockingQueue<Runnable>(10));
-            try (PoolCleaner cleaner = cleaner(p, done)) {
-                List<Callable<String>> tasks = new ArrayList<>();
-                tasks.add(new StringTask("0"));
-                tasks.add(waiter);
-                tasks.add(new StringTask("2"));
-                long startTime = System.nanoTime();
-                List<Future<String>> futures =
-                    p.invokeAll(tasks, timeout, MILLISECONDS);
-                assertEquals(tasks.size(), futures.size());
-                assertTrue(millisElapsedSince(startTime) >= timeout);
-                for (Future future : futures)
-                    assertTrue(future.isDone());
-                assertTrue(futures.get(1).isCancelled());
-                try {
-                    assertEquals("0", futures.get(0).get());
-                    assertEquals("2", futures.get(2).get());
-                    break;
-                } catch (CancellationException retryWithLongerTimeout) {
-                    timeout *= 2;
-                    if (timeout >= LONG_DELAY_MS / 2)
-                        fail("expected exactly one task to be cancelled");
-                }
-            }
+        ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        try {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+            assertEquals(l.size(), futures.size());
+            for (Future future : futures)
+                assertTrue(future.isDone());
+            assertFalse(futures.get(0).isCancelled());
+            assertTrue(futures.get(1).isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1924,7 +1718,7 @@
                           LONG_DELAY_MS, MILLISECONDS,
                           new LinkedBlockingQueue<Runnable>(),
                           new FailingThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             final int TASKS = 100;
             final CountDownLatch done = new CountDownLatch(TASKS);
             for (int k = 0; k < TASKS; ++k)
@@ -1933,6 +1727,8 @@
                         done.countDown();
                     }});
             assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1940,40 +1736,38 @@
      * allowsCoreThreadTimeOut is by default false.
      */
     public void testAllowsCoreThreadTimeOut() {
-        final ThreadPoolExecutor p =
-            new CustomTPE(2, 2,
-                          1000, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.allowsCoreThreadTimeOut());
-        }
+        ThreadPoolExecutor p = new CustomTPE(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+        assertFalse(p.allowsCoreThreadTimeOut());
+        joinPool(p);
     }
 
     /**
      * allowCoreThreadTimeOut(true) causes idle threads to time out
      */
     public void testAllowCoreThreadTimeOut_true() throws Exception {
-        long keepAliveTime = timeoutMillis();
+        long coreThreadTimeOut = SHORT_DELAY_MS;
         final ThreadPoolExecutor p =
             new CustomTPE(2, 10,
-                          keepAliveTime, MILLISECONDS,
+                          coreThreadTimeOut, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             p.allowCoreThreadTimeOut(true);
             p.execute(new CheckedRunnable() {
-                public void realRun() {
+                public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getPoolSize());
                 }});
             await(threadStarted);
-            delay(keepAliveTime);
+            delay(coreThreadTimeOut);
             long startTime = System.nanoTime();
             while (p.getPoolSize() > 0
                    && millisElapsedSince(startTime) < LONG_DELAY_MS)
                 Thread.yield();
             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             assertEquals(0, p.getPoolSize());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1981,59 +1775,23 @@
      * allowCoreThreadTimeOut(false) causes idle threads not to time out
      */
     public void testAllowCoreThreadTimeOut_false() throws Exception {
-        long keepAliveTime = timeoutMillis();
+        long coreThreadTimeOut = SHORT_DELAY_MS;
         final ThreadPoolExecutor p =
             new CustomTPE(2, 10,
-                          keepAliveTime, MILLISECONDS,
+                          coreThreadTimeOut, MILLISECONDS,
                           new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             p.allowCoreThreadTimeOut(false);
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertTrue(p.getPoolSize() >= 1);
                 }});
-            delay(2 * keepAliveTime);
+            delay(2 * coreThreadTimeOut);
             assertTrue(p.getPoolSize() >= 1);
-        }
-    }
-
-    /**
-     * get(cancelled task) throws CancellationException
-     * (in part, a test of CustomTPE itself)
-     */
-    public void testGet_cancelled() throws Exception {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ExecutorService e =
-            new CustomTPE(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new LinkedBlockingQueue<Runnable>());
-        try (PoolCleaner cleaner = cleaner(e, done)) {
-            final CountDownLatch blockerStarted = new CountDownLatch(1);
-            final List<Future<?>> futures = new ArrayList<>();
-            for (int i = 0; i < 2; i++) {
-                Runnable r = new CheckedRunnable() { public void realRun()
-                                                         throws Throwable {
-                    blockerStarted.countDown();
-                    assertTrue(done.await(2 * LONG_DELAY_MS, MILLISECONDS));
-                }};
-                futures.add(e.submit(r));
-            }
-            await(blockerStarted);
-            for (Future<?> future : futures) future.cancel(false);
-            for (Future<?> future : futures) {
-                try {
-                    future.get();
-                    shouldThrow();
-                } catch (CancellationException success) {}
-                try {
-                    future.get(LONG_DELAY_MS, MILLISECONDS);
-                    shouldThrow();
-                } catch (CancellationException success) {}
-                assertTrue(future.isCancelled());
-                assertTrue(future.isDone());
-            }
+        } finally {
+            joinPool(p);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorTest.java b/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorTest.java
index 7fe26f4..52a7002 100644
--- a/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ThreadPoolExecutorTest.java
@@ -10,14 +10,12 @@
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
@@ -31,7 +29,6 @@
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -44,7 +41,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ThreadPoolExecutorTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class ExtendedTPE extends ThreadPoolExecutor {
@@ -92,12 +89,16 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Runnable task = new CheckedRunnable() {
-                public void realRun() { done.countDown(); }};
+        final CountDownLatch done = new CountDownLatch(1);
+        final Runnable task = new CheckedRunnable() {
+            public void realRun() {
+                done.countDown();
+            }};
+        try {
             p.execute(task);
-            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
+            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -106,22 +107,25 @@
      * thread becomes active
      */
     public void testGetActiveCount() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getActiveCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getActiveCount());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getActiveCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -130,25 +134,17 @@
      */
     public void testPrestartCoreThread() {
         final ThreadPoolExecutor p =
-            new ThreadPoolExecutor(2, 6,
+            new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(0, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(1, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(2, p.getPoolSize());
-            assertFalse(p.prestartCoreThread());
-            assertEquals(2, p.getPoolSize());
-            p.setCorePoolSize(4);
-            assertTrue(p.prestartCoreThread());
-            assertEquals(3, p.getPoolSize());
-            assertTrue(p.prestartCoreThread());
-            assertEquals(4, p.getPoolSize());
-            assertFalse(p.prestartCoreThread());
-            assertEquals(4, p.getPoolSize());
-        }
+        assertEquals(0, p.getPoolSize());
+        assertTrue(p.prestartCoreThread());
+        assertEquals(1, p.getPoolSize());
+        assertTrue(p.prestartCoreThread());
+        assertEquals(2, p.getPoolSize());
+        assertFalse(p.prestartCoreThread());
+        assertEquals(2, p.getPoolSize());
+        joinPool(p);
     }
 
     /**
@@ -156,21 +152,15 @@
      */
     public void testPrestartAllCoreThreads() {
         final ThreadPoolExecutor p =
-            new ThreadPoolExecutor(2, 6,
+            new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(0, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(2, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(2, p.getPoolSize());
-            p.setCorePoolSize(4);
-            p.prestartAllCoreThreads();
-            assertEquals(4, p.getPoolSize());
-            p.prestartAllCoreThreads();
-            assertEquals(4, p.getPoolSize());
-        }
+        assertEquals(0, p.getPoolSize());
+        p.prestartAllCoreThreads();
+        assertEquals(2, p.getPoolSize());
+        p.prestartAllCoreThreads();
+        assertEquals(2, p.getPoolSize());
+        joinPool(p);
     }
 
     /**
@@ -182,10 +172,10 @@
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch threadProceed = new CountDownLatch(1);
-            final CountDownLatch threadDone = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadProceed = new CountDownLatch(1);
+        final CountDownLatch threadDone = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
@@ -204,6 +194,8 @@
                     fail("timed out");
                 Thread.yield();
             }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -215,9 +207,8 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getCorePoolSize());
-        }
+        assertEquals(1, p.getCorePoolSize());
+        joinPool(p);
     }
 
     /**
@@ -228,25 +219,23 @@
             new ThreadPoolExecutor(2, 2,
                                    1000, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(1, p.getKeepAliveTime(SECONDS));
-        }
+        assertEquals(1, p.getKeepAliveTime(TimeUnit.SECONDS));
+        joinPool(p);
     }
 
     /**
      * getThreadFactory returns factory in constructor if not set
      */
     public void testGetThreadFactory() {
-        ThreadFactory threadFactory = new SimpleThreadFactory();
+        ThreadFactory tf = new SimpleThreadFactory();
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
-                                   threadFactory,
+                                   tf,
                                    new NoOpREHandler());
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
@@ -257,11 +246,10 @@
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            ThreadFactory threadFactory = new SimpleThreadFactory();
-            p.setThreadFactory(threadFactory);
-            assertSame(threadFactory, p.getThreadFactory());
-        }
+        ThreadFactory tf = new SimpleThreadFactory();
+        p.setThreadFactory(tf);
+        assertSame(tf, p.getThreadFactory());
+        joinPool(p);
     }
 
     /**
@@ -272,11 +260,12 @@
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setThreadFactory(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            p.setThreadFactory(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -284,15 +273,14 @@
      * getRejectedExecutionHandler returns handler in constructor if not set
      */
     public void testGetRejectedExecutionHandler() {
-        final RejectedExecutionHandler handler = new NoOpREHandler();
+        final RejectedExecutionHandler h = new NoOpREHandler();
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
-                                   handler);
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertSame(handler, p.getRejectedExecutionHandler());
-        }
+                                   h);
+        assertSame(h, p.getRejectedExecutionHandler());
+        joinPool(p);
     }
 
     /**
@@ -304,11 +292,10 @@
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            RejectedExecutionHandler handler = new NoOpREHandler();
-            p.setRejectedExecutionHandler(handler);
-            assertSame(handler, p.getRejectedExecutionHandler());
-        }
+        RejectedExecutionHandler h = new NoOpREHandler();
+        p.setRejectedExecutionHandler(h);
+        assertSame(h, p.getRejectedExecutionHandler());
+        joinPool(p);
     }
 
     /**
@@ -319,11 +306,12 @@
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setRejectedExecutionHandler(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            p.setRejectedExecutionHandler(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -333,25 +321,28 @@
      */
     public void testGetLargestPoolSize() throws InterruptedException {
         final int THREADS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(THREADS, THREADS,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getLargestPoolSize());
-            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
             for (int i = 0; i < THREADS; i++)
                 p.execute(new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadsStarted.countDown();
-                        await(done);
+                        done.await();
                         assertEquals(THREADS, p.getLargestPoolSize());
                     }});
-            await(threadsStarted);
+            assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
+            assertEquals(THREADS, p.getLargestPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
             assertEquals(THREADS, p.getLargestPoolSize());
         }
-        assertEquals(THREADS, p.getLargestPoolSize());
     }
 
     /**
@@ -363,13 +354,8 @@
             new ThreadPoolExecutor(2, 3,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertEquals(3, p.getMaximumPoolSize());
-            p.setMaximumPoolSize(5);
-            assertEquals(5, p.getMaximumPoolSize());
-            p.setMaximumPoolSize(4);
-            assertEquals(4, p.getMaximumPoolSize());
-        }
+        assertEquals(3, p.getMaximumPoolSize());
+        joinPool(p);
     }
 
     /**
@@ -377,22 +363,25 @@
      * become active
      */
     public void testGetPoolSize() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getPoolSize());
-            final CountDownLatch threadStarted = new CountDownLatch(1);
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertEquals(1, p.getPoolSize());
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getPoolSize());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -400,38 +389,26 @@
      * getTaskCount increases, but doesn't overestimate, when tasks submitted
      */
     public void testGetTaskCount() throws InterruptedException {
-        final int TASKS = 3;
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertEquals(0, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
-                    await(done);
+                    assertEquals(1, p.getTaskCount());
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(1, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
-            for (int i = 0; i < TASKS; i++) {
-                assertEquals(1 + i, p.getTaskCount());
-                p.execute(new CheckedRunnable() {
-                    public void realRun() throws InterruptedException {
-                        threadStarted.countDown();
-                        assertEquals(1 + TASKS, p.getTaskCount());
-                        await(done);
-                    }});
-            }
-            assertEquals(1 + TASKS, p.getTaskCount());
-            assertEquals(0, p.getCompletedTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
-        assertEquals(1 + TASKS, p.getTaskCount());
-        assertEquals(1 + TASKS, p.getCompletedTaskCount());
     }
 
     /**
@@ -442,11 +419,10 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.isShutdown());
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.isShutdown());
-        }
+        assertFalse(p.isShutdown());
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.isShutdown());
+        joinPool(p);
     }
 
     /**
@@ -457,28 +433,26 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.isTerminated());
-            assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS));
-            assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
-            assertFalse(p.awaitTermination(-1L, NANOSECONDS));
-            assertFalse(p.awaitTermination(-1L, MILLISECONDS));
-            assertFalse(p.awaitTermination(0L, NANOSECONDS));
-            assertFalse(p.awaitTermination(0L, MILLISECONDS));
-            long timeoutNanos = 999999L;
-            long startTime = System.nanoTime();
-            assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
-            assertTrue(System.nanoTime() - startTime >= timeoutNanos);
-            assertFalse(p.isTerminated());
-            startTime = System.nanoTime();
-            long timeoutMillis = timeoutMillis();
-            assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS));
-            assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
-            assertFalse(p.isTerminated());
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-        }
+        assertFalse(p.isTerminated());
+        assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS));
+        assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
+        assertFalse(p.awaitTermination(-1L, NANOSECONDS));
+        assertFalse(p.awaitTermination(-1L, MILLISECONDS));
+        assertFalse(p.awaitTermination(0L, NANOSECONDS));
+        assertFalse(p.awaitTermination(0L, MILLISECONDS));
+        long timeoutNanos = 999999L;
+        long startTime = System.nanoTime();
+        assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
+        assertTrue(System.nanoTime() - startTime >= timeoutNanos);
+        assertFalse(p.isTerminated());
+        startTime = System.nanoTime();
+        long timeoutMillis = timeoutMillis();
+        assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS));
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+        assertFalse(p.isTerminated());
+        p.shutdown();
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
     }
 
     /**
@@ -489,24 +463,24 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch done = new CountDownLatch(1);
-            assertFalse(p.isTerminating());
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        assertFalse(p.isTerminated());
+        try {
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
-                    assertFalse(p.isTerminating());
+                    assertFalse(p.isTerminated());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
     }
 
     /**
@@ -517,55 +491,59 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
-            final CountDownLatch done = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             assertFalse(p.isTerminating());
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     assertFalse(p.isTerminating());
                     threadStarted.countDown();
-                    await(done);
+                    done.await();
                 }});
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.isTerminating());
             done.countDown();
+        } finally {
             try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-            assertTrue(p.isTerminated());
-            assertFalse(p.isTerminating());
         }
+        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        assertTrue(p.isTerminated());
+        assertFalse(p.isTerminating());
     }
 
     /**
      * getQueue returns the work queue, which contains queued tasks
      */
     public void testGetQueue() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             FutureTask[] tasks = new FutureTask[5];
             for (int i = 0; i < tasks.length; i++) {
                 Callable task = new CheckedCallable<Boolean>() {
                     public Boolean realCall() throws InterruptedException {
                         threadStarted.countDown();
                         assertSame(q, p.getQueue());
-                        await(done);
+                        done.await();
                         return Boolean.TRUE;
                     }};
                 tasks[i] = new FutureTask(task);
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertSame(q, p.getQueue());
             assertFalse(q.contains(tasks[0]));
             assertTrue(q.contains(tasks[tasks.length - 1]));
             assertEquals(tasks.length - 1, q.size());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -573,24 +551,24 @@
      * remove(task) removes queued task, and fails to remove active task
      */
     public void testRemove() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            Runnable[] tasks = new Runnable[6];
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        Runnable[] tasks = new Runnable[5];
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 tasks[i] = new CheckedRunnable() {
                     public void realRun() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                     }};
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertFalse(p.remove(tasks[0]));
             assertTrue(q.contains(tasks[4]));
             assertTrue(q.contains(tasks[3]));
@@ -600,6 +578,9 @@
             assertTrue(q.contains(tasks[3]));
             assertTrue(p.remove(tasks[3]));
             assertFalse(q.contains(tasks[3]));
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -614,19 +595,19 @@
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    q);
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            FutureTask[] tasks = new FutureTask[5];
+        FutureTask[] tasks = new FutureTask[5];
+        try {
             for (int i = 0; i < tasks.length; i++) {
                 Callable task = new CheckedCallable<Boolean>() {
                     public Boolean realCall() throws InterruptedException {
                         threadStarted.countDown();
-                        await(done);
+                        done.await();
                         return Boolean.TRUE;
                     }};
                 tasks[i] = new FutureTask(task);
                 p.execute(tasks[i]);
             }
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             assertEquals(tasks.length, p.getTaskCount());
             assertEquals(tasks.length - 1, q.size());
             assertEquals(1L, p.getActiveCount());
@@ -639,47 +620,32 @@
             p.purge();         // Nothing to do
             assertEquals(tasks.length - 3, q.size());
             assertEquals(tasks.length - 2, p.getTaskCount());
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
     /**
-     * shutdownNow returns a list containing tasks that were not run,
-     * and those tasks are drained from the queue
+     * shutdownNow returns a list containing tasks that were not run
      */
-    public void testShutdownNow() throws InterruptedException {
-        final int poolSize = 2;
-        final int count = 5;
-        final AtomicInteger ran = new AtomicInteger(0);
+    public void testShutdownNow() {
         final ThreadPoolExecutor p =
-            new ThreadPoolExecutor(poolSize, poolSize,
+            new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
-        Runnable waiter = new CheckedRunnable() { public void realRun() {
-            threadsStarted.countDown();
-            try {
-                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
-            } catch (InterruptedException success) {}
-            ran.getAndIncrement();
-        }};
-        for (int i = 0; i < count; i++)
-            p.execute(waiter);
-        await(threadsStarted);
-        assertEquals(poolSize, p.getActiveCount());
-        assertEquals(0, p.getCompletedTaskCount());
-        final List<Runnable> queuedTasks;
+        List l;
         try {
-            queuedTasks = p.shutdownNow();
-        } catch (SecurityException ok) {
-            return; // Allowed in case test doesn't have privs
+            for (int i = 0; i < 5; i++)
+                p.execute(new MediumPossiblyInterruptedRunnable());
+        }
+        finally {
+            try {
+                l = p.shutdownNow();
+            } catch (SecurityException ok) { return; }
         }
         assertTrue(p.isShutdown());
-        assertTrue(p.getQueue().isEmpty());
-        assertEquals(count - poolSize, queuedTasks.size());
-        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
-        assertTrue(p.isTerminated());
-        assertEquals(poolSize, ran.get());
-        assertEquals(poolSize, p.getCompletedTaskCount());
+        assertTrue(l.size() <= 4);
     }
 
     // Exception Tests
@@ -689,7 +655,8 @@
      */
     public void testConstructor1() {
         try {
-            new ThreadPoolExecutor(-1, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(-1, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -700,7 +667,8 @@
      */
     public void testConstructor2() {
         try {
-            new ThreadPoolExecutor(1, -1, 1L, SECONDS,
+            new ThreadPoolExecutor(1, -1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -711,7 +679,8 @@
      */
     public void testConstructor3() {
         try {
-            new ThreadPoolExecutor(1, 0, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 0,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -722,7 +691,8 @@
      */
     public void testConstructor4() {
         try {
-            new ThreadPoolExecutor(1, 2, -1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   -1L, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -733,7 +703,8 @@
      */
     public void testConstructor5() {
         try {
-            new ThreadPoolExecutor(2, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(2, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
@@ -744,7 +715,8 @@
      */
     public void testConstructorNullPointerException() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    (BlockingQueue) null);
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -755,7 +727,8 @@
      */
     public void testConstructor6() {
         try {
-            new ThreadPoolExecutor(-1, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(-1, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -767,7 +740,8 @@
      */
     public void testConstructor7() {
         try {
-            new ThreadPoolExecutor(1, -1, 1L, SECONDS,
+            new ThreadPoolExecutor(1, -1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -779,7 +753,8 @@
      */
     public void testConstructor8() {
         try {
-            new ThreadPoolExecutor(1, 0, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 0,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -791,7 +766,8 @@
      */
     public void testConstructor9() {
         try {
-            new ThreadPoolExecutor(1, 2, -1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   -1L, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -803,7 +779,8 @@
      */
     public void testConstructor10() {
         try {
-            new ThreadPoolExecutor(2, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(2, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -815,7 +792,8 @@
      */
     public void testConstructorNullPointerException2() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    (BlockingQueue) null,
                                    new SimpleThreadFactory());
             shouldThrow();
@@ -827,7 +805,8 @@
      */
     public void testConstructorNullPointerException3() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    (ThreadFactory) null);
             shouldThrow();
@@ -839,7 +818,8 @@
      */
     public void testConstructor11() {
         try {
-            new ThreadPoolExecutor(-1, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(-1, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new NoOpREHandler());
             shouldThrow();
@@ -851,7 +831,8 @@
      */
     public void testConstructor12() {
         try {
-            new ThreadPoolExecutor(1, -1, 1L, SECONDS,
+            new ThreadPoolExecutor(1, -1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new NoOpREHandler());
             shouldThrow();
@@ -863,7 +844,8 @@
      */
     public void testConstructor13() {
         try {
-            new ThreadPoolExecutor(1, 0, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 0,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new NoOpREHandler());
             shouldThrow();
@@ -875,7 +857,8 @@
      */
     public void testConstructor14() {
         try {
-            new ThreadPoolExecutor(1, 2, -1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   -1L, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new NoOpREHandler());
             shouldThrow();
@@ -887,7 +870,8 @@
      */
     public void testConstructor15() {
         try {
-            new ThreadPoolExecutor(2, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(2, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new NoOpREHandler());
             shouldThrow();
@@ -899,7 +883,8 @@
      */
     public void testConstructorNullPointerException4() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    (BlockingQueue) null,
                                    new NoOpREHandler());
             shouldThrow();
@@ -911,7 +896,8 @@
      */
     public void testConstructorNullPointerException5() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    (RejectedExecutionHandler) null);
             shouldThrow();
@@ -923,7 +909,8 @@
      */
     public void testConstructor16() {
         try {
-            new ThreadPoolExecutor(-1, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(-1, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -936,7 +923,8 @@
      */
     public void testConstructor17() {
         try {
-            new ThreadPoolExecutor(1, -1, 1L, SECONDS,
+            new ThreadPoolExecutor(1, -1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -949,7 +937,8 @@
      */
     public void testConstructor18() {
         try {
-            new ThreadPoolExecutor(1, 0, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 0,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -962,7 +951,8 @@
      */
     public void testConstructor19() {
         try {
-            new ThreadPoolExecutor(1, 2, -1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   -1L, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -975,7 +965,8 @@
      */
     public void testConstructor20() {
         try {
-            new ThreadPoolExecutor(2, 1, 1L, SECONDS,
+            new ThreadPoolExecutor(2, 1,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -988,7 +979,8 @@
      */
     public void testConstructorNullPointerException6() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    (BlockingQueue) null,
                                    new SimpleThreadFactory(),
                                    new NoOpREHandler());
@@ -1001,7 +993,8 @@
      */
     public void testConstructorNullPointerException7() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    new SimpleThreadFactory(),
                                    (RejectedExecutionHandler) null);
@@ -1014,7 +1007,8 @@
      */
     public void testConstructorNullPointerException8() {
         try {
-            new ThreadPoolExecutor(1, 2, 1L, SECONDS,
+            new ThreadPoolExecutor(1, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10),
                                    (ThreadFactory) null,
                                    new NoOpREHandler());
@@ -1026,28 +1020,31 @@
      * get of submitted callable throws InterruptedException if interrupted
      */
     public void testInterruptedSubmit() throws InterruptedException {
-        final CountDownLatch done = new CountDownLatch(1);
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
-                                   60, SECONDS,
+                                   60, TimeUnit.SECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
 
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Thread t = newStartedThread(new CheckedInterruptedRunnable() {
                 public void realRun() throws Exception {
                     Callable task = new CheckedCallable<Boolean>() {
                         public Boolean realCall() throws InterruptedException {
                             threadStarted.countDown();
-                            await(done);
+                            done.await();
                             return Boolean.TRUE;
                         }};
                     p.submit(task).get();
                 }});
 
-            await(threadStarted);
+            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
             t.interrupt();
-            awaitTermination(t);
+            awaitTermination(t, MEDIUM_DELAY_MS);
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -1055,15 +1052,15 @@
      * execute throws RejectedExecutionException if saturated.
      */
     public void testSaturatedExecute() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
-                    await(done);
+                    done.await();
                 }};
             for (int i = 0; i < 2; ++i)
                 p.execute(task);
@@ -1074,6 +1071,9 @@
                 } catch (RejectedExecutionException success) {}
                 assertTrue(p.getTaskCount() <= 2);
             }
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -1081,15 +1081,15 @@
      * submit(runnable) throws RejectedExecutionException if saturated.
      */
     public void testSaturatedSubmitRunnable() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
-                    await(done);
+                    done.await();
                 }};
             for (int i = 0; i < 2; ++i)
                 p.submit(task);
@@ -1100,6 +1100,9 @@
                 } catch (RejectedExecutionException success) {}
                 assertTrue(p.getTaskCount() <= 2);
             }
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -1107,15 +1110,15 @@
      * submit(callable) throws RejectedExecutionException if saturated.
      */
     public void testSaturatedSubmitCallable() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1));
-        try (PoolCleaner cleaner = cleaner(p, done)) {
+        final CountDownLatch done = new CountDownLatch(1);
+        try {
             Runnable task = new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
-                    await(done);
+                    done.await();
                 }};
             for (int i = 0; i < 2; ++i)
                 p.submit(Executors.callable(task));
@@ -1126,6 +1129,9 @@
                 } catch (RejectedExecutionException success) {}
                 assertTrue(p.getTaskCount() <= 2);
             }
+        } finally {
+            done.countDown();
+            joinPool(p);
         }
     }
 
@@ -1133,28 +1139,26 @@
      * executor using CallerRunsPolicy runs task if saturated.
      */
     public void testSaturatedExecute2() {
+        RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy();
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS,
                                    MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1),
-                                   new ThreadPoolExecutor.CallerRunsPolicy());
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch done = new CountDownLatch(1);
-            Runnable blocker = new CheckedRunnable() {
-                public void realRun() throws InterruptedException {
-                    await(done);
-                }};
-            p.execute(blocker);
+                                   h);
+        try {
             TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
-            for (int i = 0; i < tasks.length; i++)
+            for (int i = 0; i < tasks.length; ++i)
                 tasks[i] = new TrackedNoOpRunnable();
-            for (int i = 0; i < tasks.length; i++)
+            TrackedLongRunnable mr = new TrackedLongRunnable();
+            p.execute(mr);
+            for (int i = 0; i < tasks.length; ++i)
                 p.execute(tasks[i]);
-            for (int i = 1; i < tasks.length; i++)
+            for (int i = 1; i < tasks.length; ++i)
                 assertTrue(tasks[i].done);
-            assertFalse(tasks[0].done); // waiting in queue
-            done.countDown();
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1162,72 +1166,67 @@
      * executor using DiscardPolicy drops task if saturated.
      */
     public void testSaturatedExecute3() {
-        final CountDownLatch done = new CountDownLatch(1);
-        final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
-        for (int i = 0; i < tasks.length; ++i)
-            tasks[i] = new TrackedNoOpRunnable();
+        RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy();
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
-                          LONG_DELAY_MS, MILLISECONDS,
-                          new ArrayBlockingQueue<Runnable>(1),
-                          new ThreadPoolExecutor.DiscardPolicy());
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            p.execute(awaiter(done));
-
+                                   LONG_DELAY_MS, MILLISECONDS,
+                                   new ArrayBlockingQueue<Runnable>(1),
+                                   h);
+        try {
+            TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
+            for (int i = 0; i < tasks.length; ++i)
+                tasks[i] = new TrackedNoOpRunnable();
+            p.execute(new TrackedLongRunnable());
             for (TrackedNoOpRunnable task : tasks)
                 p.execute(task);
-            for (int i = 1; i < tasks.length; i++)
-                assertFalse(tasks[i].done);
+            for (TrackedNoOpRunnable task : tasks)
+                assertFalse(task.done);
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
-        for (int i = 1; i < tasks.length; i++)
-            assertFalse(tasks[i].done);
-        assertTrue(tasks[0].done); // was waiting in queue
     }
 
     /**
      * executor using DiscardOldestPolicy drops oldest task if saturated.
      */
     public void testSaturatedExecute4() {
-        final CountDownLatch done = new CountDownLatch(1);
-        LatchAwaiter r1 = awaiter(done);
-        LatchAwaiter r2 = awaiter(done);
-        LatchAwaiter r3 = awaiter(done);
+        RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy();
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1),
-                                   new ThreadPoolExecutor.DiscardOldestPolicy());
-        try (PoolCleaner cleaner = cleaner(p, done)) {
-            assertEquals(LatchAwaiter.NEW, r1.state);
-            assertEquals(LatchAwaiter.NEW, r2.state);
-            assertEquals(LatchAwaiter.NEW, r3.state);
-            p.execute(r1);
+                                   h);
+        try {
+            p.execute(new TrackedLongRunnable());
+            TrackedLongRunnable r2 = new TrackedLongRunnable();
             p.execute(r2);
             assertTrue(p.getQueue().contains(r2));
+            TrackedNoOpRunnable r3 = new TrackedNoOpRunnable();
             p.execute(r3);
             assertFalse(p.getQueue().contains(r2));
             assertTrue(p.getQueue().contains(r3));
+            try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
-        assertEquals(LatchAwaiter.DONE, r1.state);
-        assertEquals(LatchAwaiter.NEW, r2.state);
-        assertEquals(LatchAwaiter.DONE, r3.state);
     }
 
     /**
      * execute throws RejectedExecutionException if shutdown
      */
     public void testRejectedExecutionExceptionOnShutdown() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1));
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(new NoOpRunnable());
-                shouldThrow();
-            } catch (RejectedExecutionException success) {}
-        }
+        try {
+            p.execute(new NoOpRunnable());
+            shouldThrow();
+        } catch (RejectedExecutionException success) {}
+
+        joinPool(p);
     }
 
     /**
@@ -1241,10 +1240,12 @@
                                    new ArrayBlockingQueue<Runnable>(1), h);
 
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1252,17 +1253,20 @@
      * execute using DiscardPolicy drops task on shutdown
      */
     public void testDiscardOnShutdown() {
-        final ThreadPoolExecutor p =
+        RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy();
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1),
-                                   new ThreadPoolExecutor.DiscardPolicy());
+                                   h);
 
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1270,17 +1274,20 @@
      * execute using DiscardOldestPolicy drops task on shutdown
      */
     public void testDiscardOldestOnShutdown() {
-        final ThreadPoolExecutor p =
+        RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy();
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 1,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(1),
-                                   new ThreadPoolExecutor.DiscardOldestPolicy());
+                                   h);
 
         try { p.shutdown(); } catch (SecurityException ok) { return; }
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             TrackedNoOpRunnable r = new TrackedNoOpRunnable();
             p.execute(r);
             assertFalse(r.done);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1288,32 +1295,34 @@
      * execute(null) throws NPE
      */
     public void testExecuteNull() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 2,
-                                   1L, SECONDS,
+                                   LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.execute(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+        try {
+            p.execute(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+
+        joinPool(p);
     }
 
     /**
      * setCorePoolSize of negative value throws IllegalArgumentException
      */
     public void testCorePoolSizeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(1, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setCorePoolSize(-1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            p.setCorePoolSize(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1321,16 +1330,18 @@
      * given a value less the core pool size
      */
     public void testMaximumPoolSizeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 3,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setMaximumPoolSize(1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            p.setMaximumPoolSize(1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1338,45 +1349,18 @@
      * if given a negative value
      */
     public void testMaximumPoolSizeIllegalArgumentException2() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 3,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setMaximumPoolSize(-1);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            p.setMaximumPoolSize(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
-    }
-
-    /**
-     * Configuration changes that allow core pool size greater than
-     * max pool size result in IllegalArgumentException.
-     */
-    public void testPoolSizeInvariants() {
-        final ThreadPoolExecutor p =
-            new ThreadPoolExecutor(1, 1,
-                                   LONG_DELAY_MS, MILLISECONDS,
-                                   new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            for (int s = 1; s < 5; s++) {
-                p.setMaximumPoolSize(s);
-                p.setCorePoolSize(s);
-                try {
-                    p.setMaximumPoolSize(s - 1);
-                    shouldThrow();
-                } catch (IllegalArgumentException success) {}
-                assertEquals(s, p.getCorePoolSize());
-                assertEquals(s, p.getMaximumPoolSize());
-                try {
-                    p.setCorePoolSize(s + 1);
-                    shouldThrow();
-                } catch (IllegalArgumentException success) {}
-                assertEquals(s, p.getCorePoolSize());
-                assertEquals(s, p.getMaximumPoolSize());
-            }
-        }
+        joinPool(p);
     }
 
     /**
@@ -1384,16 +1368,18 @@
      * when given a negative value
      */
     public void testKeepAliveTimeIllegalArgumentException() {
-        final ThreadPoolExecutor p =
+        ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 3,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try {
-                p.setKeepAliveTime(-1, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            p.setKeepAliveTime(-1,MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
         }
+        joinPool(p);
     }
 
     /**
@@ -1401,11 +1387,9 @@
      */
     public void testTerminated() {
         ExtendedTPE p = new ExtendedTPE();
-        try (PoolCleaner cleaner = cleaner(p)) {
-            try { p.shutdown(); } catch (SecurityException ok) { return; }
-            assertTrue(p.terminatedCalled());
-            assertTrue(p.isShutdown());
-        }
+        try { p.shutdown(); } catch (SecurityException ok) { return; }
+        assertTrue(p.terminatedCalled());
+        joinPool(p);
     }
 
     /**
@@ -1413,7 +1397,7 @@
      */
     public void testBeforeAfter() throws InterruptedException {
         ExtendedTPE p = new ExtendedTPE();
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             final CountDownLatch done = new CountDownLatch(1);
             p.execute(new CheckedRunnable() {
                 public void realRun() {
@@ -1423,6 +1407,9 @@
             assertEquals(0, done.getCount());
             assertTrue(p.afterCalled());
             assertTrue(p.beforeCalled());
+            try { p.shutdown(); } catch (SecurityException ok) { return; }
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1430,14 +1417,16 @@
      * completed submit of callable returns result
      */
     public void testSubmitCallable() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<String> future = e.submit(new StringTask());
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1445,14 +1434,16 @@
      * completed submit of runnable returns successfully
      */
     public void testSubmitRunnable() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<?> future = e.submit(new NoOpRunnable());
             future.get();
             assertTrue(future.isDone());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1460,14 +1451,16 @@
      * completed submit of (runnable, result) returns result
      */
     public void testSubmitRunnable2() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
             String result = future.get();
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1475,15 +1468,16 @@
      * invokeAny(null) throws NPE
      */
     public void testInvokeAny1() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAny(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1491,15 +1485,16 @@
      * invokeAny(empty collection) throws IAE
      */
     public void testInvokeAny2() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>());
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>());
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1512,15 +1507,16 @@
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1528,19 +1524,19 @@
      * invokeAny(c) throws ExecutionException if no task completes
      */
     public void testInvokeAny4() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1548,16 +1544,18 @@
      * invokeAny(c) returns result of some task
      */
     public void testInvokeAny5() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             String result = e.invokeAny(l);
             assertSame(TEST_STRING, result);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1565,15 +1563,16 @@
      * invokeAll(null) throws NPE
      */
     public void testInvokeAll1() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAll(null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1581,13 +1580,15 @@
      * invokeAll(empty collection) returns empty collection
      */
     public void testInvokeAll2() throws InterruptedException {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1595,18 +1596,19 @@
      * invokeAll(c) throws NPE if c has null elements
      */
     public void testInvokeAll3() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1614,11 +1616,11 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testInvokeAll4() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new NPETask());
             List<Future<String>> futures = e.invokeAll(l);
@@ -1629,6 +1631,8 @@
             } catch (ExecutionException success) {
                 assertTrue(success.getCause() instanceof NullPointerException);
             }
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1636,11 +1640,11 @@
      * invokeAll(c) returns results of all completed tasks
      */
     public void testInvokeAll5() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
@@ -1648,6 +1652,8 @@
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1655,15 +1661,16 @@
      * timed invokeAny(null) throws NPE
      */
     public void testTimedInvokeAny1() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1671,17 +1678,18 @@
      * timed invokeAny(,,null) throws NPE
      */
     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1689,16 +1697,16 @@
      * timed invokeAny(empty collection) throws IAE
      */
     public void testTimedInvokeAny2() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAny(new ArrayList<Callable<String>>(),
-                            MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (IllegalArgumentException success) {}
+        try {
+            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1711,15 +1719,16 @@
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(latchAwaitingStringTask(latch));
-            l.add(null);
-            try {
-                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(latchAwaitingStringTask(latch));
+        l.add(null);
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
             latch.countDown();
+            joinPool(e);
         }
     }
 
@@ -1727,21 +1736,19 @@
      * timed invokeAny(c) throws ExecutionException if no task completes
      */
     public void testTimedInvokeAny4() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            try {
-                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        try {
+            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1749,18 +1756,18 @@
      * timed invokeAny(c) returns result of some task
      */
     public void testTimedInvokeAny5() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            long startTime = System.nanoTime();
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
-            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertSame(TEST_STRING, result);
-            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1768,15 +1775,16 @@
      * timed invokeAll(null) throws NPE
      */
     public void testTimedInvokeAll1() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            try {
-                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        try {
+            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1784,17 +1792,18 @@
      * timed invokeAll(,,null) throws NPE
      */
     public void testTimedInvokeAllNullTimeUnit() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, null);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1802,14 +1811,15 @@
      * timed invokeAll(empty collection) returns empty collection
      */
     public void testTimedInvokeAll2() throws InterruptedException {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(),
-                                                 MEDIUM_DELAY_MS, MILLISECONDS);
+        try {
+            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
             assertTrue(r.isEmpty());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1817,18 +1827,19 @@
      * timed invokeAll(c) throws NPE if c has null elements
      */
     public void testTimedInvokeAll3() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new StringTask());
-            l.add(null);
-            try {
-                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
-                shouldThrow();
-            } catch (NullPointerException success) {}
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new StringTask());
+        l.add(null);
+        try {
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+            shouldThrow();
+        } catch (NullPointerException success) {
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1836,22 +1847,22 @@
      * get of element of invokeAll(c) throws exception on failed task
      */
     public void testTimedInvokeAll4() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
-            List<Callable<String>> l = new ArrayList<Callable<String>>();
-            l.add(new NPETask());
-            List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
-            assertEquals(1, futures.size());
-            try {
-                futures.get(0).get();
-                shouldThrow();
-            } catch (ExecutionException success) {
-                assertTrue(success.getCause() instanceof NullPointerException);
-            }
+        List<Callable<String>> l = new ArrayList<Callable<String>>();
+        l.add(new NPETask());
+        List<Future<String>> futures =
+            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+        assertEquals(1, futures.size());
+        try {
+            futures.get(0).get();
+            shouldThrow();
+        } catch (ExecutionException success) {
+            assertTrue(success.getCause() instanceof NullPointerException);
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1859,19 +1870,21 @@
      * timed invokeAll(c) returns results of all completed tasks
      */
     public void testTimedInvokeAll5() throws Exception {
-        final ExecutorService e =
+        ExecutorService e =
             new ThreadPoolExecutor(2, 2,
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             List<Callable<String>> l = new ArrayList<Callable<String>>();
             l.add(new StringTask());
             l.add(new StringTask());
             List<Future<String>> futures =
-                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
             assertEquals(2, futures.size());
             for (Future<String> future : futures)
                 assertSame(TEST_STRING, future.get());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1879,40 +1892,24 @@
      * timed invokeAll(c) cancels tasks not completed by timeout
      */
     public void testTimedInvokeAll6() throws Exception {
-        for (long timeout = timeoutMillis();;) {
-            final CountDownLatch done = new CountDownLatch(1);
-            final Callable<String> waiter = new CheckedCallable<String>() {
-                public String realCall() {
-                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
-                    catch (InterruptedException ok) {}
-                    return "1"; }};
-            final ExecutorService p =
-                new ThreadPoolExecutor(2, 2,
-                                       LONG_DELAY_MS, MILLISECONDS,
-                                       new ArrayBlockingQueue<Runnable>(10));
-            try (PoolCleaner cleaner = cleaner(p, done)) {
-                List<Callable<String>> tasks = new ArrayList<>();
-                tasks.add(new StringTask("0"));
-                tasks.add(waiter);
-                tasks.add(new StringTask("2"));
-                long startTime = System.nanoTime();
-                List<Future<String>> futures =
-                    p.invokeAll(tasks, timeout, MILLISECONDS);
-                assertEquals(tasks.size(), futures.size());
-                assertTrue(millisElapsedSince(startTime) >= timeout);
-                for (Future future : futures)
-                    assertTrue(future.isDone());
-                assertTrue(futures.get(1).isCancelled());
-                try {
-                    assertEquals("0", futures.get(0).get());
-                    assertEquals("2", futures.get(2).get());
-                    break;
-                } catch (CancellationException retryWithLongerTimeout) {
-                    timeout *= 2;
-                    if (timeout >= LONG_DELAY_MS / 2)
-                        fail("expected exactly one task to be cancelled");
-                }
-            }
+        ExecutorService e =
+            new ThreadPoolExecutor(2, 2,
+                                   LONG_DELAY_MS, MILLISECONDS,
+                                   new ArrayBlockingQueue<Runnable>(10));
+        try {
+            List<Callable<String>> l = new ArrayList<Callable<String>>();
+            l.add(new StringTask());
+            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
+            l.add(new StringTask());
+            List<Future<String>> futures =
+                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+            assertEquals(l.size(), futures.size());
+            for (Future future : futures)
+                assertTrue(future.isDone());
+            assertFalse(futures.get(0).isCancelled());
+            assertTrue(futures.get(1).isCancelled());
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1926,7 +1923,7 @@
                                    LONG_DELAY_MS, MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    new FailingThreadFactory());
-        try (PoolCleaner cleaner = cleaner(e)) {
+        try {
             final int TASKS = 100;
             final CountDownLatch done = new CountDownLatch(TASKS);
             for (int k = 0; k < TASKS; ++k)
@@ -1935,6 +1932,8 @@
                         done.countDown();
                     }});
             assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
+        } finally {
+            joinPool(e);
         }
     }
 
@@ -1946,22 +1945,21 @@
             new ThreadPoolExecutor(2, 2,
                                    1000, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            assertFalse(p.allowsCoreThreadTimeOut());
-        }
+        assertFalse(p.allowsCoreThreadTimeOut());
+        joinPool(p);
     }
 
     /**
      * allowCoreThreadTimeOut(true) causes idle threads to time out
      */
     public void testAllowCoreThreadTimeOut_true() throws Exception {
-        long keepAliveTime = timeoutMillis();
+        long coreThreadTimeOut = SHORT_DELAY_MS;
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 10,
-                                   keepAliveTime, MILLISECONDS,
+                                   coreThreadTimeOut, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             p.allowCoreThreadTimeOut(true);
             p.execute(new CheckedRunnable() {
                 public void realRun() {
@@ -1969,13 +1967,15 @@
                     assertEquals(1, p.getPoolSize());
                 }});
             await(threadStarted);
-            delay(keepAliveTime);
+            delay(coreThreadTimeOut);
             long startTime = System.nanoTime();
             while (p.getPoolSize() > 0
                    && millisElapsedSince(startTime) < LONG_DELAY_MS)
                 Thread.yield();
             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
             assertEquals(0, p.getPoolSize());
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -1983,21 +1983,23 @@
      * allowCoreThreadTimeOut(false) causes idle threads not to time out
      */
     public void testAllowCoreThreadTimeOut_false() throws Exception {
-        long keepAliveTime = timeoutMillis();
+        long coreThreadTimeOut = SHORT_DELAY_MS;
         final ThreadPoolExecutor p =
             new ThreadPoolExecutor(2, 10,
-                                   keepAliveTime, MILLISECONDS,
+                                   coreThreadTimeOut, MILLISECONDS,
                                    new ArrayBlockingQueue<Runnable>(10));
-        try (PoolCleaner cleaner = cleaner(p)) {
-            final CountDownLatch threadStarted = new CountDownLatch(1);
+        final CountDownLatch threadStarted = new CountDownLatch(1);
+        try {
             p.allowCoreThreadTimeOut(false);
             p.execute(new CheckedRunnable() {
                 public void realRun() throws InterruptedException {
                     threadStarted.countDown();
                     assertTrue(p.getPoolSize() >= 1);
                 }});
-            delay(2 * keepAliveTime);
+            delay(2 * coreThreadTimeOut);
             assertTrue(p.getPoolSize() >= 1);
+        } finally {
+            joinPool(p);
         }
     }
 
@@ -2013,10 +2015,9 @@
                 done.countDown();
             }};
         final ThreadPoolExecutor p =
-            new ThreadPoolExecutor(1, 30,
-                                   60, SECONDS,
+            new ThreadPoolExecutor(1, 30, 60, TimeUnit.SECONDS,
                                    new ArrayBlockingQueue(30));
-        try (PoolCleaner cleaner = cleaner(p)) {
+        try {
             for (int i = 0; i < nTasks; ++i) {
                 for (;;) {
                     try {
@@ -2028,43 +2029,8 @@
             }
             // enough time to run all tasks
             assertTrue(done.await(nTasks * SHORT_DELAY_MS, MILLISECONDS));
-        }
-    }
-
-    /**
-     * get(cancelled task) throws CancellationException
-     */
-    public void testGet_cancelled() throws Exception {
-        final CountDownLatch done = new CountDownLatch(1);
-        final ExecutorService e =
-            new ThreadPoolExecutor(1, 1,
-                                   LONG_DELAY_MS, MILLISECONDS,
-                                   new LinkedBlockingQueue<Runnable>());
-        try (PoolCleaner cleaner = cleaner(e, done)) {
-            final CountDownLatch blockerStarted = new CountDownLatch(1);
-            final List<Future<?>> futures = new ArrayList<>();
-            for (int i = 0; i < 2; i++) {
-                Runnable r = new CheckedRunnable() { public void realRun()
-                                                         throws Throwable {
-                    blockerStarted.countDown();
-                    assertTrue(done.await(2 * LONG_DELAY_MS, MILLISECONDS));
-                }};
-                futures.add(e.submit(r));
-            }
-            await(blockerStarted);
-            for (Future<?> future : futures) future.cancel(false);
-            for (Future<?> future : futures) {
-                try {
-                    future.get();
-                    shouldThrow();
-                } catch (CancellationException success) {}
-                try {
-                    future.get(LONG_DELAY_MS, MILLISECONDS);
-                    shouldThrow();
-                } catch (CancellationException success) {}
-                assertTrue(future.isCancelled());
-                assertTrue(future.isDone());
-            }
+        } finally {
+            joinPool(p);
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ThreadTest.java b/jsr166-tests/src/test/java/jsr166/ThreadTest.java
index e69b422..27f22ca 100644
--- a/jsr166-tests/src/test/java/jsr166/ThreadTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ThreadTest.java
@@ -19,7 +19,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(ThreadTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyHandler implements Thread.UncaughtExceptionHandler {
@@ -57,7 +57,8 @@
         // default uncaught exception handler installed by the framework.
         //
         // assertEquals(null, Thread.getDefaultUncaughtExceptionHandler());
-        // failure due to SecurityException is OK.
+
+        // failure due to securityException is OK.
         // Would be nice to explicitly test both ways, but cannot yet.
         Thread.UncaughtExceptionHandler defaultHandler
             = Thread.getDefaultUncaughtExceptionHandler();
diff --git a/jsr166-tests/src/test/java/jsr166/TimeUnitTest.java b/jsr166-tests/src/test/java/jsr166/TimeUnitTest.java
index b21fa7d..2c9529b 100644
--- a/jsr166-tests/src/test/java/jsr166/TimeUnitTest.java
+++ b/jsr166-tests/src/test/java/jsr166/TimeUnitTest.java
@@ -30,7 +30,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(TimeUnitTest.class);
+    //     return new TestSuite(...);
     // }
 
     // (loops to 88888 check increments at all time divisions.)
@@ -433,8 +433,8 @@
      * a deserialized serialized unit is the same instance
      */
     public void testSerialization() throws Exception {
-        for (TimeUnit x : TimeUnit.values())
-            assertSame(x, serialClone(x));
+        TimeUnit x = MILLISECONDS;
+        assertSame(x, serialClone(x));
     }
 
 }
diff --git a/jsr166-tests/src/test/java/jsr166/TreeMapTest.java b/jsr166-tests/src/test/java/jsr166/TreeMapTest.java
index e445609..afc73de 100644
--- a/jsr166-tests/src/test/java/jsr166/TreeMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/TreeMapTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(TreeMapTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/TreeSetTest.java b/jsr166-tests/src/test/java/jsr166/TreeSetTest.java
index c3093f6..a935637 100644
--- a/jsr166-tests/src/test/java/jsr166/TreeSetTest.java
+++ b/jsr166-tests/src/test/java/jsr166/TreeSetTest.java
@@ -29,7 +29,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(TreeSetTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyReverseComparator implements Comparator {
@@ -50,7 +50,7 @@
     private TreeSet<Integer> populatedSet(int n) {
         TreeSet<Integer> q = new TreeSet<Integer>();
         assertTrue(q.isEmpty());
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.add(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.add(new Integer(i)));
@@ -96,7 +96,8 @@
      */
     public void testConstructor4() {
         try {
-            new TreeSet(Arrays.asList(new Integer[SIZE]));
+            Integer[] ints = new Integer[SIZE];
+            new TreeSet(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
     }
@@ -105,10 +106,10 @@
      * Initializing from Collection with some null elements throws NPE
      */
     public void testConstructor5() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i);
         try {
+            Integer[] ints = new Integer[SIZE];
+            for (int i = 0; i < SIZE-1; ++i)
+                ints[i] = new Integer(i);
             new TreeSet(Arrays.asList(ints));
             shouldThrow();
         } catch (NullPointerException success) {}
@@ -137,7 +138,7 @@
         for (int i = 0; i < SIZE; ++i)
             ints[i] = new Integer(i);
         q.addAll(Arrays.asList(ints));
-        for (int i = SIZE - 1; i >= 0; --i)
+        for (int i = SIZE-1; i >= 0; --i)
             assertEquals(ints[i], q.pollFirst());
     }
 
@@ -161,7 +162,7 @@
     public void testSize() {
         TreeSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -241,7 +242,7 @@
     public void testAddAll3() {
         TreeSet q = new TreeSet();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
+        for (int i = 0; i < SIZE-1; ++i)
             ints[i] = new Integer(i);
         try {
             q.addAll(Arrays.asList(ints));
@@ -256,7 +257,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1-i);
         TreeSet q = new TreeSet();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -280,7 +281,7 @@
      */
     public void testPollLast() {
         TreeSet q = populatedSet(SIZE);
-        for (int i = SIZE - 1; i >= 0; --i) {
+        for (int i = SIZE-1; i >= 0; --i) {
             assertEquals(i, q.pollLast());
         }
         assertNull(q.pollFirst());
@@ -295,14 +296,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -361,7 +362,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -374,7 +375,7 @@
             TreeSet q = populatedSet(SIZE);
             TreeSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
@@ -908,18 +909,18 @@
                 else if (element > max)
                     return -1;
                 int result = bs.nextSetBit(element);
-                return (result > max) ? -1 : result;
+                return result > max ? -1 : result;
             }
             int higherAscending(int element) {
                 return ceilingAscending(element + 1);
             }
             private int firstAscending() {
                 int result = ceilingAscending(min);
-                return (result > max) ? -1 : result;
+                return result > max ? -1 : result;
             }
             private int lastAscending() {
                 int result = floorAscending(max);
-                return (result < min) ? -1 : result;
+                return result < min ? -1 : result;
             }
         }
         ReferenceSet rs = new ReferenceSet();
@@ -980,7 +981,7 @@
     }
 
     static boolean eq(Integer i, int j) {
-        return (i == null) ? j == -1 : i == j;
+        return i == null ? j == -1 : i == j;
     }
 
 }
diff --git a/jsr166-tests/src/test/java/jsr166/TreeSubMapTest.java b/jsr166-tests/src/test/java/jsr166/TreeSubMapTest.java
index 09b809e..18a9e37 100644
--- a/jsr166-tests/src/test/java/jsr166/TreeSubMapTest.java
+++ b/jsr166-tests/src/test/java/jsr166/TreeSubMapTest.java
@@ -27,7 +27,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(TreeSubMapTest.class);
+    //     return new TestSuite(...);
     // }
 
     /**
diff --git a/jsr166-tests/src/test/java/jsr166/TreeSubSetTest.java b/jsr166-tests/src/test/java/jsr166/TreeSubSetTest.java
index 31403be..5398c4e 100644
--- a/jsr166-tests/src/test/java/jsr166/TreeSubSetTest.java
+++ b/jsr166-tests/src/test/java/jsr166/TreeSubSetTest.java
@@ -25,7 +25,7 @@
     //     main(suite(), args);
     // }
     // public static Test suite() {
-    //     return new TestSuite(TreeSubSetTest.class);
+    //     return new TestSuite(...);
     // }
 
     static class MyReverseComparator implements Comparator {
@@ -42,7 +42,7 @@
         TreeSet<Integer> q = new TreeSet<Integer>();
         assertTrue(q.isEmpty());
 
-        for (int i = n - 1; i >= 0; i -= 2)
+        for (int i = n-1; i >= 0; i -= 2)
             assertTrue(q.add(new Integer(i)));
         for (int i = (n & 1); i < n; i += 2)
             assertTrue(q.add(new Integer(i)));
@@ -124,7 +124,7 @@
     public void testSize() {
         NavigableSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -203,8 +203,8 @@
     public void testAddAll3() {
         NavigableSet q = set0();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i + SIZE);
+        for (int i = 0; i < SIZE-1; ++i)
+            ints[i] = new Integer(i+SIZE);
         try {
             q.addAll(Arrays.asList(ints));
             shouldThrow();
@@ -218,7 +218,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1- i);
         NavigableSet q = set0();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -246,14 +246,14 @@
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertTrue(q.contains(i - 1));
+            assertTrue(q.contains(i-1));
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.contains(i));
             assertTrue(q.remove(i));
             assertFalse(q.contains(i));
-            assertFalse(q.remove(i + 1));
-            assertFalse(q.contains(i + 1));
+            assertFalse(q.remove(i+1));
+            assertFalse(q.contains(i+1));
         }
         assertTrue(q.isEmpty());
     }
@@ -312,7 +312,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -325,7 +325,7 @@
             NavigableSet q = populatedSet(SIZE);
             NavigableSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
@@ -620,7 +620,7 @@
     public void testDescendingSize() {
         NavigableSet q = populatedSet(SIZE);
         for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             q.pollFirst();
         }
         for (int i = 0; i < SIZE; ++i) {
@@ -688,8 +688,8 @@
     public void testDescendingAddAll3() {
         NavigableSet q = dset0();
         Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE - 1; ++i)
-            ints[i] = new Integer(i + SIZE);
+        for (int i = 0; i < SIZE-1; ++i)
+            ints[i] = new Integer(i+SIZE);
         try {
             q.addAll(Arrays.asList(ints));
             shouldThrow();
@@ -703,7 +703,7 @@
         Integer[] empty = new Integer[0];
         Integer[] ints = new Integer[SIZE];
         for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(SIZE - 1 - i);
+            ints[i] = new Integer(SIZE-1- i);
         NavigableSet q = dset0();
         assertFalse(q.addAll(Arrays.asList(empty)));
         assertTrue(q.addAll(Arrays.asList(ints)));
@@ -732,7 +732,7 @@
         }
         for (int i = 0; i < SIZE; i += 2) {
             assertTrue(q.remove(new Integer(i)));
-            assertFalse(q.remove(new Integer(i + 1)));
+            assertFalse(q.remove(new Integer(i+1)));
         }
         assertTrue(q.isEmpty());
     }
@@ -791,7 +791,7 @@
                 assertTrue(changed);
 
             assertTrue(q.containsAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             p.pollFirst();
         }
     }
@@ -804,7 +804,7 @@
             NavigableSet q = populatedSet(SIZE);
             NavigableSet p = populatedSet(i);
             assertTrue(q.removeAll(p));
-            assertEquals(SIZE - i, q.size());
+            assertEquals(SIZE-i, q.size());
             for (int j = 0; j < i; ++j) {
                 Integer x = (Integer)(p.pollFirst());
                 assertFalse(q.contains(x));
diff --git a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
index 213baf2..f444b29 100644
--- a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -6,12 +6,7 @@
 
 package java.util.concurrent;
 
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 /**
  * Provides default implementations of {@link ExecutorService}
@@ -28,7 +23,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> {...}
@@ -123,7 +118,7 @@
         int ntasks = tasks.size();
         if (ntasks == 0)
             throw new IllegalArgumentException();
-        ArrayList<Future<T>> futures = new ArrayList<>(ntasks);
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
         ExecutorCompletionService<T> ecs =
             new ExecutorCompletionService<T>(this);
 
@@ -156,7 +151,7 @@
                     else if (active == 0)
                         break;
                     else if (timed) {
-                        f = ecs.poll(nanos, NANOSECONDS);
+                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                         if (f == null)
                             throw new TimeoutException();
                         nanos = deadline - System.nanoTime();
@@ -181,7 +176,8 @@
             throw ee;
 
         } finally {
-            cancelAll(futures);
+            for (int i = 0, size = futures.size(); i < size; i++)
+                futures.get(i).cancel(true);
         }
     }
 
@@ -205,7 +201,8 @@
         throws InterruptedException {
         if (tasks == null)
             throw new NullPointerException();
-        ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        boolean done = false;
         try {
             for (Callable<T> t : tasks) {
                 RunnableFuture<T> f = newTaskFor(t);
@@ -215,15 +212,19 @@
             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;
-        } catch (Throwable t) {
-            cancelAll(futures);
-            throw t;
+        } finally {
+            if (!done)
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(true);
         }
     }
 
@@ -232,52 +233,47 @@
         throws InterruptedException {
         if (tasks == null)
             throw new NullPointerException();
-        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 {
+        long nanos = unit.toNanos(timeout);
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        boolean done = false;
+        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 (; j < size; j++) {
-                Future<T> f = futures.get(j);
+            for (int i = 0; i < size; i++) {
+                Future<T> f = futures.get(i);
                 if (!f.isDone()) {
-                    try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
-                    catch (CancellationException ignore) {}
-                    catch (ExecutionException ignore) {}
-                    catch (TimeoutException timedOut) {
-                        break timedOut;
+                    if (nanos <= 0L)
+                        return futures;
+                    try {
+                        f.get(nanos, TimeUnit.NANOSECONDS);
+                    } catch (CancellationException ignore) {
+                    } catch (ExecutionException ignore) {
+                    } catch (TimeoutException toe) {
+                        return futures;
                     }
+                    nanos = deadline - System.nanoTime();
                 }
             }
+            done = true;
             return futures;
-        } catch (Throwable t) {
-            cancelAll(futures);
-            throw t;
+        } finally {
+            if (!done)
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(true);
         }
-        // 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);
-    }
 }
diff --git a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 3183c01..9dca1b3 100644
--- a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -7,14 +7,11 @@
 package java.util.concurrent;
 
 import java.lang.ref.WeakReference;
-import java.util.AbstractQueue;
 import java.util.Arrays;
+import java.util.AbstractQueue;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Spliterator;
-import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -95,7 +92,7 @@
      * are known not to be any.  Allows queue operations to update
      * iterator state.
      */
-    transient Itrs itrs;
+    transient Itrs itrs = null;
 
     // Internal helper methods
 
@@ -240,8 +237,10 @@
         try {
             int i = 0;
             try {
-                for (E e : c)
-                    items[i++] = Objects.requireNonNull(e);
+                for (E e : c) {
+                    if (e == null) throw new NullPointerException();
+                    items[i++] = e;
+                }
             } catch (ArrayIndexOutOfBoundsException ex) {
                 throw new IllegalArgumentException();
             }
@@ -277,7 +276,7 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        Objects.requireNonNull(e);
+        if (e == null) throw new NullPointerException();
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
@@ -300,7 +299,7 @@
      * @throws NullPointerException {@inheritDoc}
      */
     public void put(E e) throws InterruptedException {
-        Objects.requireNonNull(e);
+        if (e == null) throw new NullPointerException();
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
@@ -323,13 +322,13 @@
     public boolean offer(E e, long timeout, TimeUnit unit)
         throws InterruptedException {
 
-        Objects.requireNonNull(e);
+        if (e == null) throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
             while (count == items.length) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -368,7 +367,7 @@
         lock.lockInterruptibly();
         try {
             while (count == 0) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -585,7 +584,27 @@
     }
 
     public String toString() {
-        return Helpers.collectionToString(this);
+        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();
+        }
     }
 
     /**
@@ -593,12 +612,12 @@
      * 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 {
@@ -634,7 +653,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        Objects.requireNonNull(c);
+        if (c == null) throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -1314,27 +1333,4 @@
 //         }
     }
 
-    /**
-     * Returns a {@link Spliterator} over the elements in this queue.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this queue
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return Spliterators.spliterator
-            (this, (Spliterator.ORDERED |
-                    Spliterator.NONNULL |
-                    Spliterator.CONCURRENT));
-    }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/BlockingDeque.java b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
index b52f719..b1437cc 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -6,13 +6,7 @@
 
 package java.util.concurrent;
 
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-// BEGIN android-note
-// fixed framework docs link to "Collection#optional"
-// END android-note
+import java.util.*;
 
 /**
  * A {@link Deque} that additionally supports blocking operations that wait
@@ -28,6 +22,7 @@
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Summary of BlockingDeque methods</caption>
  *  <tr>
@@ -103,6 +98,7 @@
  * {@code BlockingQueue} interface are precisely equivalent to
  * {@code BlockingDeque} methods as indicated in the following table:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
  *  <tr>
@@ -173,7 +169,7 @@
  *
  * @since 1.6
  * @author Doug Lea
- * @param <E> the type of elements held in this deque
+ * @param <E> the type of elements held in this collection
  */
 public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
     /*
@@ -379,9 +375,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeFirstOccurrence(Object o);
 
@@ -397,9 +393,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeLastOccurrence(Object o);
 
@@ -574,9 +570,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -589,18 +585,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
-    boolean contains(Object o);
+    public boolean contains(Object o);
 
     /**
      * Returns the number of elements in this deque.
      *
      * @return the number of elements in this deque
      */
-    int size();
+    public int size();
 
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
diff --git a/luni/src/main/java/java/util/concurrent/BlockingQueue.java b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
index 2a56179..33d83b7 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -10,8 +10,7 @@
 import java.util.Queue;
 
 // BEGIN android-note
-// removed link to collections framework docs from header
-// fixed framework docs link to "Collection#optional"
+// removed link to collections framework docs
 // END android-note
 
 /**
@@ -29,6 +28,7 @@
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Summary of BlockingQueue methods</caption>
  *  <tr>
@@ -103,7 +103,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; }
@@ -147,7 +147,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public interface BlockingQueue<E> extends Queue<E> {
     /**
@@ -275,9 +275,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -290,11 +290,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="../Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
      */
-    boolean contains(Object o);
+    public boolean contains(Object o);
 
     /**
      * Removes all available elements from this queue and adds them
diff --git a/luni/src/main/java/java/util/concurrent/Callable.java b/luni/src/main/java/java/util/concurrent/Callable.java
index a22ec50..a3b3883 100644
--- a/luni/src/main/java/java/util/concurrent/Callable.java
+++ b/luni/src/main/java/java/util/concurrent/Callable.java
@@ -25,7 +25,6 @@
  * @author Doug Lea
  * @param <V> the result type of method {@code call}
  */
-@FunctionalInterface
 public interface Callable<V> {
     /**
      * Computes a result, or throws an exception if unable to do so.
diff --git a/luni/src/main/java/java/util/concurrent/CompletableFuture.java b/luni/src/main/java/java/util/concurrent/CompletableFuture.java
deleted file mode 100644
index bcb6ed5..0000000
--- a/luni/src/main/java/java/util/concurrent/CompletableFuture.java
+++ /dev/null
@@ -1,2770 +0,0 @@
-/*
- * 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.concurrent.locks.LockSupport;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-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
- * value and status), and may be used as a {@link CompletionStage},
- * supporting dependent functions and actions that trigger upon its
- * completion.
- *
- * <p>When two or more threads attempt to
- * {@link #complete complete},
- * {@link #completeExceptionally completeExceptionally}, or
- * {@link #cancel cancel}
- * a CompletableFuture, only one of them succeeds.
- *
- * <p>In addition to these and related methods for directly
- * manipulating status and results, CompletableFuture implements
- * interface {@link CompletionStage} with the following policies: <ul>
- *
- * <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>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).  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>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>
- *
- * <li>Since (unlike {@link FutureTask}) this class has no direct
- * control over the computation that causes it to be completed,
- * cancellation is treated as just another form of exceptional
- * 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>In case of exceptional completion with a CompletionException,
- * methods {@link #get()} and {@link #get(long, TimeUnit)} throw an
- * {@link ExecutionException} with the same cause as held in the
- * 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.
- * </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> {
-
-    /*
-     * Overview:
-     *
-     * A CompletableFuture may have dependent completion actions,
-     * collected in a linked stack. It atomically completes by CASing
-     * a result field, and then pops off and runs those actions. This
-     * applies across normal vs exceptional outcomes, sync vs async
-     * actions, binary triggers, and various forms of completions.
-     *
-     * Non-nullness of field result (set via CAS) indicates done.  An
-     * AltResult is used to box null as a result, as well as to hold
-     * exceptions.  Using a single field makes completion simple to
-     * detect and trigger.  Encoding and decoding is straightforward
-     * but adds to the sprawl of trapping and associating exceptions
-     * with targets.  Minor simplifications rely on (static) NIL (to
-     * box null results) being the only AltResult with a null
-     * exception field, so we don't usually need explicit comparisons.
-     * Even though some of the generics casts are unchecked (see
-     * SuppressWarnings annotations), they are placed to be
-     * appropriate even if checked.
-     *
-     * Dependent actions are represented by Completion objects linked
-     * as Treiber stacks headed by field "stack". There are Completion
-     * classes for each kind of action, grouped into single-input
-     * (UniCompletion), two-input (BiCompletion), projected
-     * (BiCompletions using either (not both) of two inputs), shared
-     * (CoCompletion, used by the second of two sources), zero-input
-     * source actions, and Signallers that unblock waiters. Class
-     * Completion extends ForkJoinTask to enable async execution
-     * (adding no space overhead because we exploit its "tag" methods
-     * to maintain claims). It is also declared as Runnable to allow
-     * usage with arbitrary executors.
-     *
-     * Support for each kind of CompletionStage relies on a separate
-     * class, along with two CompletableFuture methods:
-     *
-     * * A Completion class with name X corresponding to function,
-     *   prefaced with "Uni", "Bi", or "Or". Each class contains
-     *   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 adapters in common usages.
-     *
-     * * Boolean CompletableFuture method x(...) (for example
-     *   uniApply) takes all of the arguments needed to check that an
-     *   action is triggerable, and then either runs the action or
-     *   arranges its async execution by executing its Completion
-     *   argument, if present. The method returns true if known to be
-     *   complete.
-     *
-     * * Completion method tryFire(int mode) invokes the associated x
-     *   method with its held arguments, and on success cleans up.
-     *   The mode argument allows tryFire to be called twice (SYNC,
-     *   then ASYNC); the first to screen and trap exceptions while
-     *   arranging to execute, and the second when called from a
-     *   task. (A few classes are not used async so take slightly
-     *   different forms.)  The claim() callback suppresses function
-     *   invocation if already claimed by another thread.
-     *
-     * * CompletableFuture method xStage(...) is called from a public
-     *   stage method of CompletableFuture x. It screens user
-     *   arguments and invokes and/or creates the stage object.  If
-     *   not async and x is already complete, the action is run
-     *   immediately.  Otherwise a Completion c is created, pushed to
-     *   x's stack (unless done), and started or triggered via
-     *   c.tryFire.  This also covers races possible if x completes
-     *   while pushing.  Classes with two inputs (for example BiApply)
-     *   deal with races across both while pushing actions.  The
-     *   second completion is a CoCompletion pointing to the first,
-     *   shared so that at most one performs the action.  The
-     *   multiple-arity methods allOf and anyOf do this pairwise to
-     *   form trees of completions.
-     *
-     * Note that the generic type parameters of methods vary according
-     * to whether "this" is a source, dependent, or completion.
-     *
-     * Method postComplete is called upon completion unless the target
-     * is guaranteed not to be observable (i.e., not yet returned or
-     * linked). Multiple threads can call postComplete, which
-     * atomically pops each dependent action, and tries to trigger it
-     * via method tryFire, in NESTED mode.  Triggering can propagate
-     * recursively, so NESTED mode returns its completed dependent (if
-     * one exists) for further processing by its caller (see method
-     * postFire).
-     *
-     * Blocking methods get() and join() rely on Signaller Completions
-     * that wake up waiting threads.  The mechanics are similar to
-     * Treiber stack wait-nodes used in FutureTask, Phaser, and
-     * SynchronousQueue. See their internal documentation for
-     * algorithmic details.
-     *
-     * Without precautions, CompletableFutures would be prone to
-     * garbage accumulation as chains of Completions build up, each
-     * pointing back to its sources. So we null out fields as soon as
-     * possible.  The screening checks needed anyway harmlessly ignore
-     * null arguments that may have been obtained during races with
-     * threads nulling out fields.  We also try to unlink fired
-     * Completions from stacks that might never be popped (see method
-     * postFire).  Completion fields need not be declared as final or
-     * volatile because they are only visible to other threads upon
-     * safe publication.
-     */
-
-    volatile Object result;       // Either the result or boxed AltResult
-    volatile Completion stack;    // Top of Treiber stack of dependent actions
-
-    final boolean internalComplete(Object r) { // CAS from null to r
-        return U.compareAndSwapObject(this, RESULT, null, r);
-    }
-
-    final boolean casStack(Completion cmp, Completion 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 U.compareAndSwapObject(this, STACK, h, c);
-    }
-
-    /** Unconditionally pushes c onto stack, retrying if necessary. */
-    final void pushStack(Completion c) {
-        do {} while (!tryPushStack(c));
-    }
-
-    /* ------------- Encoding and decoding outcomes -------------- */
-
-    static final class AltResult { // See above
-        final Throwable ex;        // null only for NIL
-        AltResult(Throwable x) { this.ex = x; }
-    }
-
-    /** The encoding of the null value. */
-    static final AltResult NIL = new AltResult(null);
-
-    /** Completes with the null value, unless already completed. */
-    final boolean completeNull() {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      NIL);
-    }
-
-    /** Returns the encoding of the given non-exceptional value. */
-    final Object encodeValue(T t) {
-        return (t == null) ? NIL : t;
-    }
-
-    /** Completes with a non-exceptional result, unless already completed. */
-    final boolean completeValue(T t) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      (t == null) ? NIL : t);
-    }
-
-    /**
-     * Returns the encoding of the given (non-null) exception as a
-     * wrapped CompletionException unless it is one already.
-     */
-    static AltResult encodeThrowable(Throwable x) {
-        return new AltResult((x instanceof CompletionException) ? x :
-                             new CompletionException(x));
-    }
-
-    /** Completes with an exceptional result, unless already completed. */
-    final boolean completeThrowable(Throwable x) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x));
-    }
-
-    /**
-     * Returns the encoding of the given (non-null) exception as a
-     * wrapped CompletionException unless it is one already.  May
-     * return the given Object r (which must have been the result of a
-     * source future) if it is equivalent, i.e. if this is a simple
-     * relay of an existing CompletionException.
-     */
-    static Object encodeThrowable(Throwable x, Object r) {
-        if (!(x instanceof CompletionException))
-            x = new CompletionException(x);
-        else if (r instanceof AltResult && x == ((AltResult)r).ex)
-            return r;
-        return new AltResult(x);
-    }
-
-    /**
-     * Completes with the given (non-null) exceptional result as a
-     * wrapped CompletionException unless it is one already, unless
-     * already completed.  May complete with the given Object r
-     * (which must have been the result of a source future) if it is
-     * equivalent, i.e. if this is a simple propagation of an
-     * existing CompletionException.
-     */
-    final boolean completeThrowable(Throwable x, Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x, r));
-    }
-
-    /**
-     * Returns the encoding of the given arguments: if the exception
-     * is non-null, encodes as AltResult.  Otherwise uses the given
-     * value, boxed as NIL if null.
-     */
-    Object encodeOutcome(T t, Throwable x) {
-        return (x == null) ? (t == null) ? NIL : t : encodeThrowable(x);
-    }
-
-    /**
-     * Returns the encoding of a copied outcome; if exceptional,
-     * rewraps as a CompletionException, else returns argument.
-     */
-    static Object encodeRelay(Object r) {
-        Throwable x;
-        return (((r instanceof AltResult) &&
-                 (x = ((AltResult)r).ex) != null &&
-                 !(x instanceof CompletionException)) ?
-                new AltResult(new CompletionException(x)) : r);
-    }
-
-    /**
-     * Completes with r or a copy of r, unless already completed.
-     * If exceptional, r is first coerced to a CompletionException.
-     */
-    final boolean completeRelay(Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeRelay(r));
-    }
-
-    /**
-     * Reports result using Future.get conventions.
-     */
-    private static <T> T reportGet(Object r)
-        throws InterruptedException, ExecutionException {
-        if (r == null) // by convention below, null means interrupted
-            throw new InterruptedException();
-        if (r instanceof AltResult) {
-            Throwable x, cause;
-            if ((x = ((AltResult)r).ex) == null)
-                return null;
-            if (x instanceof CancellationException)
-                throw (CancellationException)x;
-            if ((x instanceof CompletionException) &&
-                (cause = x.getCause()) != null)
-                x = cause;
-            throw new ExecutionException(x);
-        }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
-    }
-
-    /**
-     * Decodes outcome to return result or throw unchecked exception.
-     */
-    private static <T> T reportJoin(Object r) {
-        if (r instanceof AltResult) {
-            Throwable x;
-            if ((x = ((AltResult)r).ex) == null)
-                return null;
-            if (x instanceof CancellationException)
-                throw (CancellationException)x;
-            if (x instanceof CompletionException)
-                throw (CompletionException)x;
-            throw new CompletionException(x);
-        }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
-    }
-
-    /* ------------- Async task preliminaries -------------- */
-
-    /**
-     * A marker interface identifying asynchronous tasks produced by
-     * {@code async} methods. This may be useful for monitoring,
-     * debugging, and tracking asynchronous activities.
-     *
-     * @since 1.8
-     */
-    public static interface AsynchronousCompletionTask {
-    }
-
-    private static final boolean USE_COMMON_POOL =
-        (ForkJoinPool.getCommonPoolParallelism() > 1);
-
-    /**
-     * Default executor -- ForkJoinPool.commonPool() unless it cannot
-     * support parallelism.
-     */
-    private static final Executor ASYNC_POOL = USE_COMMON_POOL ?
-        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
-
-    /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
-    static final class ThreadPerTaskExecutor implements Executor {
-        public void execute(Runnable r) { new Thread(r).start(); }
-    }
-
-    /**
-     * Null-checks user executor argument, and translates uses of
-     * commonPool to ASYNC_POOL in case parallelism disabled.
-     */
-    static Executor screenExecutor(Executor e) {
-        if (!USE_COMMON_POOL && e == ForkJoinPool.commonPool())
-            return ASYNC_POOL;
-        if (e == null) throw new NullPointerException();
-        return e;
-    }
-
-    // Modes for Completion.tryFire. Signedness matters.
-    static final int SYNC   =  0;
-    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")
-    abstract static class Completion extends ForkJoinTask<Void>
-        implements Runnable, AsynchronousCompletionTask {
-        volatile Completion next;      // Treiber stack link
-
-        /**
-         * Performs completion action if triggered, returning a
-         * dependent that may need propagation, if one exists.
-         *
-         * @param mode SYNC, ASYNC, or NESTED
-         */
-        abstract CompletableFuture<?> tryFire(int mode);
-
-        /** Returns true if possibly still triggerable. Used by cleanStack. */
-        abstract boolean isLive();
-
-        public final void run()                { tryFire(ASYNC); }
-        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) {
-        U.putOrderedObject(c, NEXT, next);
-    }
-
-    /**
-     * Pops and tries to trigger all reachable dependents.  Call only
-     * when known to be done.
-     */
-    final void postComplete() {
-        /*
-         * On each step, variable f holds current dependents to pop
-         * and run.  It is extended along only one path at a time,
-         * pushing others to avoid unbounded recursion.
-         */
-        CompletableFuture<?> f = this; Completion h;
-        while ((h = f.stack) != null ||
-               (f != this && (h = (f = this).stack) != null)) {
-            CompletableFuture<?> d; Completion t;
-            if (f.casStack(h, t = h.next)) {
-                if (t != null) {
-                    if (f != this) {
-                        pushStack(h);
-                        continue;
-                    }
-                    h.next = null;    // detach
-                }
-                f = (d = h.tryFire(NESTED)) == null ? this : d;
-            }
-        }
-    }
-
-    /** Traverses stack and unlinks dead Completions. */
-    final void cleanStack() {
-        for (Completion p = null, q = stack; q != null;) {
-            Completion s = q.next;
-            if (q.isLive()) {
-                p = q;
-                q = s;
-            }
-            else if (p == null) {
-                casStack(q, s);
-                q = stack;
-            }
-            else {
-                p.next = s;
-                if (p.isLive())
-                    q = s;
-                else {
-                    p = null;  // restart
-                    q = stack;
-                }
-            }
-        }
-    }
-
-    /* ------------- One-input Completions -------------- */
-
-    /** A Completion with a source, dependent, and executor. */
-    @SuppressWarnings("serial")
-    abstract static class UniCompletion<T,V> extends Completion {
-        Executor executor;                 // executor to use (null if none)
-        CompletableFuture<V> dep;          // the dependent to complete
-        CompletableFuture<T> src;          // source for action
-
-        UniCompletion(Executor executor, CompletableFuture<V> dep,
-                      CompletableFuture<T> src) {
-            this.executor = executor; this.dep = dep; this.src = src;
-        }
-
-        /**
-         * Returns true if action can be run. Call only when known to
-         * be triggerable. Uses FJ tag bit to ensure that only one
-         * thread claims ownership.  If async, starts as task -- a
-         * later call to tryFire will run action.
-         */
-        final boolean claim() {
-            Executor e = executor;
-            if (compareAndSetForkJoinTaskTag((short)0, (short)1)) {
-                if (e == null)
-                    return true;
-                executor = null; // disable
-                e.execute(this);
-            }
-            return false;
-        }
-
-        final boolean isLive() { return dep != null; }
-    }
-
-    /** Pushes the given completion (if it exists) unless done. */
-    final void push(UniCompletion<?,?> c) {
-        if (c != null) {
-            while (result == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
-        }
-    }
-
-    /**
-     * Post-processing by dependent after successful UniCompletion
-     * tryFire.  Tries to clean stack of source a, and then either runs
-     * postComplete or returns this to caller, depending on mode.
-     */
-    final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
-        if (a != null && a.stack != null) {
-            if (mode < 0 || a.result == null)
-                a.cleanStack();
-            else
-                a.postComplete();
-        }
-        if (result != null && stack != null) {
-            if (mode < 0)
-                return this;
-            else
-                postComplete();
-        }
-        return null;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniApply<T,V> extends UniCompletion<T,V> {
-        Function<? super T,? extends V> fn;
-        UniApply(Executor executor, CompletableFuture<V> dep,
-                 CompletableFuture<T> src,
-                 Function<? super T,? extends V> fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<V> tryFire(int mode) {
-            CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniApply(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final <S> boolean uniApply(CompletableFuture<S> a,
-                               Function<? super S,? extends T> f,
-                               UniApply<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                completeValue(f.apply(s));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <V> CompletableFuture<V> uniApplyStage(
-        Executor e, Function<? super T,? extends V> f) {
-        if (f == null) throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniAccept<T> extends UniCompletion<T,Void> {
-        Consumer<? super T> fn;
-        UniAccept(Executor executor, CompletableFuture<Void> dep,
-                  CompletableFuture<T> src, Consumer<? super T> fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniAccept(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final <S> boolean uniAccept(CompletableFuture<S> a,
-                                Consumer<? super S> f, UniAccept<S> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                f.accept(s);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private CompletableFuture<Void> uniAcceptStage(Executor e,
-                                                   Consumer<? super T> f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniAccept(this, f, null)) {
-            UniAccept<T> c = new UniAccept<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniRun<T> extends UniCompletion<T,Void> {
-        Runnable fn;
-        UniRun(Executor executor, CompletableFuture<Void> dep,
-               CompletableFuture<T> src, Runnable fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniRun(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final boolean uniRun(CompletableFuture<?> a, Runnable f, UniRun<?> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else
-                try {
-                    if (c != null && !c.claim())
-                        return false;
-                    f.run();
-                    completeNull();
-                } catch (Throwable ex) {
-                    completeThrowable(ex);
-                }
-        }
-        return true;
-    }
-
-    private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniRun(this, f, null)) {
-            UniRun<T> c = new UniRun<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniWhenComplete<T> extends UniCompletion<T,T> {
-        BiConsumer<? super T, ? super Throwable> fn;
-        UniWhenComplete(Executor executor, CompletableFuture<T> dep,
-                        CompletableFuture<T> src,
-                        BiConsumer<? super T, ? super Throwable> fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<T> tryFire(int mode) {
-            CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final boolean uniWhenComplete(CompletableFuture<T> a,
-                                  BiConsumer<? super T,? super Throwable> f,
-                                  UniWhenComplete<T> c) {
-        Object r; T t; Throwable x = null;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    x = ((AltResult)r).ex;
-                    t = null;
-                } else {
-                    @SuppressWarnings("unchecked") T tr = (T) r;
-                    t = tr;
-                }
-                f.accept(t, x);
-                if (x == null) {
-                    internalComplete(r);
-                    return true;
-                }
-            } catch (Throwable ex) {
-                if (x == null)
-                    x = ex;
-                else if (x != ex)
-                    x.addSuppressed(ex);
-            }
-            completeThrowable(x, r);
-        }
-        return true;
-    }
-
-    private CompletableFuture<T> uniWhenCompleteStage(
-        Executor e, BiConsumer<? super T, ? super Throwable> f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<T> d = newIncompleteFuture();
-        if (e != null || !d.uniWhenComplete(this, f, null)) {
-            UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniHandle<T,V> extends UniCompletion<T,V> {
-        BiFunction<? super T, Throwable, ? extends V> fn;
-        UniHandle(Executor executor, CompletableFuture<V> dep,
-                  CompletableFuture<T> src,
-                  BiFunction<? super T, Throwable, ? extends V> fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<V> tryFire(int mode) {
-            CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniHandle(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final <S> boolean uniHandle(CompletableFuture<S> a,
-                                BiFunction<? super S, Throwable, ? extends T> f,
-                                UniHandle<S,T> c) {
-        Object r; S s; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    x = ((AltResult)r).ex;
-                    s = null;
-                } else {
-                    x = null;
-                    @SuppressWarnings("unchecked") S ss = (S) r;
-                    s = ss;
-                }
-                completeValue(f.apply(s, x));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <V> CompletableFuture<V> uniHandleStage(
-        Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
-        if (f == null) throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniExceptionally<T> extends UniCompletion<T,T> {
-        Function<? super Throwable, ? extends T> fn;
-        UniExceptionally(CompletableFuture<T> dep, CompletableFuture<T> src,
-                         Function<? super Throwable, ? extends T> fn) {
-            super(null, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<T> tryFire(int mode) { // never ASYNC
-            // assert mode != ASYNC;
-            CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniExceptionally(a = src, fn, this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final boolean uniExceptionally(CompletableFuture<T> a,
-                                   Function<? super Throwable, ? extends T> f,
-                                   UniExceptionally<T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) {
-                    if (c != null && !c.claim())
-                        return false;
-                    completeValue(f.apply(x));
-                } else
-                    internalComplete(r);
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private CompletableFuture<T> uniExceptionallyStage(
-        Function<Throwable, ? extends T> f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<T> d = newIncompleteFuture();
-        if (!d.uniExceptionally(this, f, null)) {
-            UniExceptionally<T> c = new UniExceptionally<T>(d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class UniRelay<T> extends UniCompletion<T,T> { // for Compose
-        UniRelay(CompletableFuture<T> dep, CompletableFuture<T> src) {
-            super(null, dep, src);
-        }
-        final CompletableFuture<T> tryFire(int mode) {
-            CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniRelay(a = src))
-                return null;
-            src = null; dep = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final boolean uniRelay(CompletableFuture<T> a) {
-        Object r;
-        if (a == null || (r = a.result) == null)
-            return false;
-        if (result == null) // no need to claim
-            completeRelay(r);
-        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;
-        UniCompose(Executor executor, CompletableFuture<V> dep,
-                   CompletableFuture<T> src,
-                   Function<? super T, ? extends CompletionStage<V>> fn) {
-            super(executor, dep, src); this.fn = fn;
-        }
-        final CompletableFuture<V> tryFire(int mode) {
-            CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniCompose(a = src, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; fn = null;
-            return d.postFire(a, mode);
-        }
-    }
-
-    final <S> boolean uniCompose(
-        CompletableFuture<S> a,
-        Function<? super S, ? extends CompletionStage<T>> f,
-        UniCompose<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                CompletableFuture<T> g = f.apply(s).toCompletableFuture();
-                if (g.result == null || !uniRelay(g)) {
-                    UniRelay<T> copy = new UniRelay<T>(this, g);
-                    g.push(copy);
-                    copy.tryFire(SYNC);
-                    if (result == null)
-                        return false;
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <V> CompletableFuture<V> uniComposeStage(
-        Executor e, Function<? super T, ? extends CompletionStage<V>> f) {
-        if (f == null) throw new NullPointerException();
-        Object r, s; Throwable x;
-        CompletableFuture<V> d = newIncompleteFuture();
-        if (e == null && (r = result) != null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    d.result = encodeThrowable(x, r);
-                    return d;
-                }
-                r = null;
-            }
-            try {
-                @SuppressWarnings("unchecked") T t = (T) r;
-                CompletableFuture<V> g = f.apply(t).toCompletableFuture();
-                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) {
-                d.result = encodeThrowable(ex);
-                return d;
-            }
-        }
-        UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f);
-        push(c);
-        c.tryFire(SYNC);
-        return d;
-    }
-
-    /* ------------- Two-input Completions -------------- */
-
-    /** A Completion for an action with two sources */
-    @SuppressWarnings("serial")
-    abstract static class BiCompletion<T,U,V> extends UniCompletion<T,V> {
-        CompletableFuture<U> snd; // second source for action
-        BiCompletion(Executor executor, CompletableFuture<V> dep,
-                     CompletableFuture<T> src, CompletableFuture<U> snd) {
-            super(executor, dep, src); this.snd = snd;
-        }
-    }
-
-    /** A Completion delegating to a BiCompletion */
-    @SuppressWarnings("serial")
-    static final class CoCompletion extends Completion {
-        BiCompletion<?,?,?> base;
-        CoCompletion(BiCompletion<?,?,?> base) { this.base = base; }
-        final CompletableFuture<?> tryFire(int mode) {
-            BiCompletion<?,?,?> c; CompletableFuture<?> d;
-            if ((c = base) == null || (d = c.tryFire(mode)) == null)
-                return null;
-            base = null; // detach
-            return d;
-        }
-        final boolean isLive() {
-            BiCompletion<?,?,?> c;
-            return (c = base) != null && c.dep != null;
-        }
-    }
-
-    /** Pushes completion to this and b unless both done. */
-    final void bipush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
-        if (c != null) {
-            Object r;
-            while ((r = result) == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
-            if (b != null && b != this && b.result == null) {
-                Completion q = (r != null) ? c : new CoCompletion(c);
-                while (b.result == null && !b.tryPushStack(q))
-                    lazySetNext(q, null); // clear on failure
-            }
-        }
-    }
-
-    /** Post-processing after successful BiCompletion tryFire. */
-    final CompletableFuture<T> postFire(CompletableFuture<?> a,
-                                        CompletableFuture<?> b, int mode) {
-        if (b != null && b.stack != null) { // clean second source
-            if (mode < 0 || b.result == null)
-                b.cleanStack();
-            else
-                b.postComplete();
-        }
-        return postFire(a, mode);
-    }
-
-    @SuppressWarnings("serial")
-    static final class BiApply<T,U,V> extends BiCompletion<T,U,V> {
-        BiFunction<? super T,? super U,? extends V> fn;
-        BiApply(Executor executor, CompletableFuture<V> dep,
-                CompletableFuture<T> src, CompletableFuture<U> snd,
-                BiFunction<? super T,? super U,? extends V> fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<V> tryFire(int mode) {
-            CompletableFuture<V> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biApply(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final <R,S> boolean biApply(CompletableFuture<R> a,
-                                CompletableFuture<S> b,
-                                BiFunction<? super R,? super S,? extends T> f,
-                                BiApply<R,S,T> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            if (s instanceof AltResult) {
-                if ((x = ((AltResult)s).ex) != null) {
-                    completeThrowable(x, s);
-                    break tryComplete;
-                }
-                s = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                @SuppressWarnings("unchecked") S ss = (S) s;
-                completeValue(f.apply(rr, ss));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <U,V> CompletableFuture<V> biApplyStage(
-        Executor e, CompletionStage<U> o,
-        BiFunction<? super T,? super U,? extends V> f) {
-        CompletableFuture<U> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class BiAccept<T,U> extends BiCompletion<T,U,Void> {
-        BiConsumer<? super T,? super U> fn;
-        BiAccept(Executor executor, CompletableFuture<Void> dep,
-                 CompletableFuture<T> src, CompletableFuture<U> snd,
-                 BiConsumer<? super T,? super U> fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final <R,S> boolean biAccept(CompletableFuture<R> a,
-                                 CompletableFuture<S> b,
-                                 BiConsumer<? super R,? super S> f,
-                                 BiAccept<R,S> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            if (s instanceof AltResult) {
-                if ((x = ((AltResult)s).ex) != null) {
-                    completeThrowable(x, s);
-                    break tryComplete;
-                }
-                s = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                @SuppressWarnings("unchecked") S ss = (S) s;
-                f.accept(rr, ss);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <U> CompletableFuture<Void> biAcceptStage(
-        Executor e, CompletionStage<U> o,
-        BiConsumer<? super T,? super U> f) {
-        CompletableFuture<U> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class BiRun<T,U> extends BiCompletion<T,U,Void> {
-        Runnable fn;
-        BiRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
-              Runnable fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biRun(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final boolean biRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, BiRun<?,?> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
-            else
-                try {
-                    if (c != null && !c.claim())
-                        return false;
-                    f.run();
-                    completeNull();
-                } catch (Throwable ex) {
-                    completeThrowable(ex);
-                }
-        }
-        return true;
-    }
-
-    private CompletableFuture<Void> biRunStage(Executor e, CompletionStage<?> o,
-                                               Runnable f) {
-        CompletableFuture<?> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class BiRelay<T,U> extends BiCompletion<T,U,Void> { // for And
-        BiRelay(CompletableFuture<Void> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
-            super(null, dep, src, snd);
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null || !d.biRelay(a = src, b = snd))
-                return null;
-            src = null; snd = null; dep = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
-            else
-                completeNull();
-        }
-        return true;
-    }
-
-    /** Recursively constructs a tree of completions. */
-    static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs,
-                                           int lo, int hi) {
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
-        if (lo > hi) // empty
-            d.result = NIL;
-        else {
-            CompletableFuture<?> a, b;
-            int mid = (lo + hi) >>> 1;
-            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)
-                throw new NullPointerException();
-            if (!d.biRelay(a, b)) {
-                BiRelay<?,?> c = new BiRelay<>(d, a, b);
-                a.bipush(b, c);
-                c.tryFire(SYNC);
-            }
-        }
-        return d;
-    }
-
-    /* ------------- Projected (Ored) BiCompletions -------------- */
-
-    /** Pushes completion to this and b unless either done. */
-    final void orpush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
-        if (c != null) {
-            while ((b == null || b.result == null) && result == null) {
-                if (tryPushStack(c)) {
-                    if (b != null && b != this && b.result == null) {
-                        Completion q = new CoCompletion(c);
-                        while (result == null && b.result == null &&
-                               !b.tryPushStack(q))
-                            lazySetNext(q, null); // clear on failure
-                    }
-                    break;
-                }
-                lazySetNext(c, null); // clear on failure
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class OrApply<T,U extends T,V> extends BiCompletion<T,U,V> {
-        Function<? super T,? extends V> fn;
-        OrApply(Executor executor, CompletableFuture<V> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd,
-                Function<? super T,? extends V> fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<V> tryFire(int mode) {
-            CompletableFuture<V> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orApply(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final <R,S extends R> boolean orApply(CompletableFuture<R> a,
-                                          CompletableFuture<S> b,
-                                          Function<? super R, ? extends T> f,
-                                          OrApply<R,S,T> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                completeValue(f.apply(rr));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <U extends T,V> CompletableFuture<V> orApplyStage(
-        Executor e, CompletionStage<U> o,
-        Function<? super T, ? extends V> f) {
-        CompletableFuture<U> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class OrAccept<T,U extends T> extends BiCompletion<T,U,Void> {
-        Consumer<? super T> fn;
-        OrAccept(Executor executor, CompletableFuture<Void> dep,
-                 CompletableFuture<T> src,
-                 CompletableFuture<U> snd,
-                 Consumer<? super T> fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final <R,S extends R> boolean orAccept(CompletableFuture<R> a,
-                                           CompletableFuture<S> b,
-                                           Consumer<? super R> f,
-                                           OrAccept<R,S> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                f.accept(rr);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private <U extends T> CompletableFuture<Void> orAcceptStage(
-        Executor e, CompletionStage<U> o, Consumer<? super T> f) {
-        CompletableFuture<U> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class OrRun<T,U> extends BiCompletion<T,U,Void> {
-        Runnable fn;
-        OrRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
-              Runnable fn) {
-            super(executor, dep, src, snd); this.fn = fn;
-        }
-        final CompletableFuture<Void> tryFire(int mode) {
-            CompletableFuture<Void> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orRun(a = src, b = snd, fn, mode > 0 ? null : this))
-                return null;
-            dep = null; src = null; snd = null; fn = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final boolean orRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, OrRun<?,?> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                    completeThrowable(x, r);
-                else {
-                    f.run();
-                    completeNull();
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
-    private CompletableFuture<Void> orRunStage(Executor e, CompletionStage<?> o,
-                                               Runnable f) {
-        CompletableFuture<?> b;
-        if (f == null || (b = o.toCompletableFuture()) == null)
-            throw new NullPointerException();
-        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);
-            c.tryFire(SYNC);
-        }
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class OrRelay<T,U> extends BiCompletion<T,U,Object> { // for Or
-        OrRelay(CompletableFuture<Object> dep, CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
-            super(null, dep, src, snd);
-        }
-        final CompletableFuture<Object> tryFire(int mode) {
-            CompletableFuture<Object> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null || !d.orRelay(a = src, b = snd))
-                return null;
-            src = null; snd = null; dep = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final boolean orRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null))
-            return false;
-        if (result == null)
-            completeRelay(r);
-        return true;
-    }
-
-    /** Recursively constructs a tree of completions. */
-    static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs,
-                                            int lo, int hi) {
-        CompletableFuture<Object> d = new CompletableFuture<Object>();
-        if (lo <= hi) {
-            CompletableFuture<?> a, b;
-            int mid = (lo + hi) >>> 1;
-            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)
-                throw new NullPointerException();
-            if (!d.orRelay(a, b)) {
-                OrRelay<?,?> c = new OrRelay<>(d, a, b);
-                a.orpush(b, c);
-                c.tryFire(SYNC);
-            }
-        }
-        return d;
-    }
-
-    /* ------------- Zero-input Async forms -------------- */
-
-    @SuppressWarnings("serial")
-    static final class AsyncSupply<T> extends ForkJoinTask<Void>
-        implements Runnable, AsynchronousCompletionTask {
-        CompletableFuture<T> dep; Supplier<? extends T> fn;
-        AsyncSupply(CompletableFuture<T> dep, Supplier<? extends T> fn) {
-            this.dep = dep; this.fn = fn;
-        }
-
-        public final Void getRawResult() { return null; }
-        public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
-
-        public void run() {
-            CompletableFuture<T> d; Supplier<? extends T> f;
-            if ((d = dep) != null && (f = fn) != null) {
-                dep = null; fn = null;
-                if (d.result == null) {
-                    try {
-                        d.completeValue(f.get());
-                    } catch (Throwable ex) {
-                        d.completeThrowable(ex);
-                    }
-                }
-                d.postComplete();
-            }
-        }
-    }
-
-    static <U> CompletableFuture<U> asyncSupplyStage(Executor e,
-                                                     Supplier<U> f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<U> d = new CompletableFuture<U>();
-        e.execute(new AsyncSupply<U>(d, f));
-        return d;
-    }
-
-    @SuppressWarnings("serial")
-    static final class AsyncRun extends ForkJoinTask<Void>
-        implements Runnable, AsynchronousCompletionTask {
-        CompletableFuture<Void> dep; Runnable fn;
-        AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
-            this.dep = dep; this.fn = fn;
-        }
-
-        public final Void getRawResult() { return null; }
-        public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
-
-        public void run() {
-            CompletableFuture<Void> d; Runnable f;
-            if ((d = dep) != null && (f = fn) != null) {
-                dep = null; fn = null;
-                if (d.result == null) {
-                    try {
-                        f.run();
-                        d.completeNull();
-                    } catch (Throwable ex) {
-                        d.completeThrowable(ex);
-                    }
-                }
-                d.postComplete();
-            }
-        }
-    }
-
-    static CompletableFuture<Void> asyncRunStage(Executor e, Runnable f) {
-        if (f == null) throw new NullPointerException();
-        CompletableFuture<Void> d = new CompletableFuture<Void>();
-        e.execute(new AsyncRun(d, f));
-        return d;
-    }
-
-    /* ------------- Signallers -------------- */
-
-    /**
-     * Completion for recording and releasing a waiting thread.  This
-     * class implements ManagedBlocker to avoid starvation when
-     * blocking actions pile up in ForkJoinPools.
-     */
-    @SuppressWarnings("serial")
-    static final class Signaller extends Completion
-        implements ForkJoinPool.ManagedBlocker {
-        long nanos;                    // remaining wait time if timed
-        final long deadline;           // non-zero if timed
-        final boolean interruptible;
-        boolean interrupted;
-        volatile Thread thread;
-
-        Signaller(boolean interruptible, long nanos, long deadline) {
-            this.thread = Thread.currentThread();
-            this.interruptible = interruptible;
-            this.nanos = nanos;
-            this.deadline = deadline;
-        }
-        final CompletableFuture<?> tryFire(int ignore) {
-            Thread w; // no need to atomically claim
-            if ((w = thread) != null) {
-                thread = null;
-                LockSupport.unpark(w);
-            }
-            return null;
-        }
-        public boolean isReleasable() {
-            if (Thread.interrupted())
-                interrupted = true;
-            return ((interrupted && interruptible) ||
-                    (deadline != 0L &&
-                     (nanos <= 0L ||
-                      (nanos = deadline - System.nanoTime()) <= 0L)) ||
-                    thread == null);
-        }
-        public boolean block() {
-            while (!isReleasable()) {
-                if (deadline == 0L)
-                    LockSupport.park(this);
-                else
-                    LockSupport.parkNanos(this, nanos);
-            }
-            return true;
-        }
-        final boolean isLive() { return thread != null; }
-    }
-
-    /**
-     * Returns raw result after waiting, or null if interruptible and
-     * interrupted.
-     */
-    private Object waitingGet(boolean interruptible) {
-        Signaller q = null;
-        boolean queued = false;
-        int spins = SPINS;
-        Object r;
-        while ((r = result) == null) {
-            if (spins > 0) {
-                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
-                    --spins;
-            }
-            else if (q == null)
-                q = new Signaller(interruptible, 0L, 0L);
-            else if (!queued)
-                queued = tryPushStack(q);
-            else {
-                try {
-                    ForkJoinPool.managedBlock(q);
-                } catch (InterruptedException ie) { // currently cannot happen
-                    q.interrupted = true;
-                }
-                if (q.interrupted && interruptible)
-                    break;
-            }
-        }
-        if (q != null) {
-            q.thread = null;
-            if (q.interrupted) {
-                if (interruptible)
-                    cleanStack();
-                else
-                    Thread.currentThread().interrupt();
-            }
-        }
-        if (r != null)
-            postComplete();
-        return r;
-    }
-
-    /**
-     * Returns raw result after waiting, or null if interrupted, or
-     * throws TimeoutException on timeout.
-     */
-    private Object timedGet(long nanos) throws TimeoutException {
-        if (Thread.interrupted())
-            return null;
-        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;
-        }
-        throw new TimeoutException();
-    }
-
-    /* ------------- public methods -------------- */
-
-    /**
-     * Creates a new incomplete CompletableFuture.
-     */
-    public CompletableFuture() {
-    }
-
-    /**
-     * Creates a new complete CompletableFuture with given encoded result.
-     */
-    CompletableFuture(Object r) {
-        this.result = r;
-    }
-
-    /**
-     * Returns a new CompletableFuture that is asynchronously completed
-     * by a task running in the {@link ForkJoinPool#commonPool()} with
-     * the value obtained by calling the given Supplier.
-     *
-     * @param supplier a function returning the value to be used
-     * to complete the returned CompletableFuture
-     * @param <U> the function's return type
-     * @return the new CompletableFuture
-     */
-    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
-        return asyncSupplyStage(ASYNC_POOL, supplier);
-    }
-
-    /**
-     * Returns a new CompletableFuture that is asynchronously completed
-     * by a task running in the given executor with the value obtained
-     * by calling the given Supplier.
-     *
-     * @param supplier a function returning the value to be used
-     * to complete the returned CompletableFuture
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the function's return type
-     * @return the new CompletableFuture
-     */
-    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
-                                                       Executor executor) {
-        return asyncSupplyStage(screenExecutor(executor), supplier);
-    }
-
-    /**
-     * Returns a new CompletableFuture that is asynchronously completed
-     * by a task running in the {@link ForkJoinPool#commonPool()} after
-     * it runs the given action.
-     *
-     * @param runnable the action to run before completing the
-     * returned CompletableFuture
-     * @return the new CompletableFuture
-     */
-    public static CompletableFuture<Void> runAsync(Runnable runnable) {
-        return asyncRunStage(ASYNC_POOL, runnable);
-    }
-
-    /**
-     * Returns a new CompletableFuture that is asynchronously completed
-     * by a task running in the given executor after it runs the given
-     * action.
-     *
-     * @param runnable the action to run before completing the
-     * returned CompletableFuture
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletableFuture
-     */
-    public static CompletableFuture<Void> runAsync(Runnable runnable,
-                                                   Executor executor) {
-        return asyncRunStage(screenExecutor(executor), runnable);
-    }
-
-    /**
-     * Returns a new CompletableFuture that is already completed with
-     * the given value.
-     *
-     * @param value the value
-     * @param <U> the type of the value
-     * @return the completed CompletableFuture
-     */
-    public static <U> CompletableFuture<U> completedFuture(U value) {
-        return new CompletableFuture<U>((value == null) ? NIL : value);
-    }
-
-    /**
-     * Returns {@code true} if completed in any fashion: normally,
-     * exceptionally, or via cancellation.
-     *
-     * @return {@code true} if completed
-     */
-    public boolean isDone() {
-        return result != null;
-    }
-
-    /**
-     * Waits if necessary for this future to complete, and then
-     * returns its result.
-     *
-     * @return the result value
-     * @throws CancellationException if this future was cancelled
-     * @throws ExecutionException if this future completed exceptionally
-     * @throws InterruptedException if the current thread was interrupted
-     * while waiting
-     */
-    public T get() throws InterruptedException, ExecutionException {
-        Object r;
-        return reportGet((r = result) == null ? waitingGet(true) : r);
-    }
-
-    /**
-     * Waits if necessary for at most the given time for this future
-     * to complete, and then returns its result, if available.
-     *
-     * @param timeout the maximum time to wait
-     * @param unit the time unit of the timeout argument
-     * @return the result value
-     * @throws CancellationException if this future was cancelled
-     * @throws ExecutionException if this future completed exceptionally
-     * @throws InterruptedException if the current thread was interrupted
-     * while waiting
-     * @throws TimeoutException if the wait timed out
-     */
-    public T get(long timeout, TimeUnit unit)
-        throws InterruptedException, ExecutionException, TimeoutException {
-        Object r;
-        long nanos = unit.toNanos(timeout);
-        return reportGet((r = result) == null ? timedGet(nanos) : r);
-    }
-
-    /**
-     * Returns the result value when complete, or throws an
-     * (unchecked) exception if completed exceptionally. To better
-     * conform with the use of common functional forms, if a
-     * computation involved in the completion of this
-     * CompletableFuture threw an exception, this method throws an
-     * (unchecked) {@link CompletionException} with the underlying
-     * exception as its cause.
-     *
-     * @return the result value
-     * @throws CancellationException if the computation was cancelled
-     * @throws CompletionException if this future completed
-     * exceptionally or a completion computation threw an exception
-     */
-    public T join() {
-        Object r;
-        return reportJoin((r = result) == null ? waitingGet(false) : r);
-    }
-
-    /**
-     * Returns the result value (or throws any encountered exception)
-     * if completed, else returns the given valueIfAbsent.
-     *
-     * @param valueIfAbsent the value to return if not completed
-     * @return the result value, if completed, else the given valueIfAbsent
-     * @throws CancellationException if the computation was cancelled
-     * @throws CompletionException if this future completed
-     * exceptionally or a completion computation threw an exception
-     */
-    public T getNow(T valueIfAbsent) {
-        Object r;
-        return ((r = result) == null) ? valueIfAbsent : reportJoin(r);
-    }
-
-    /**
-     * If not already completed, sets the value returned by {@link
-     * #get()} and related methods to the given value.
-     *
-     * @param value the result value
-     * @return {@code true} if this invocation caused this CompletableFuture
-     * to transition to a completed state, else {@code false}
-     */
-    public boolean complete(T value) {
-        boolean triggered = completeValue(value);
-        postComplete();
-        return triggered;
-    }
-
-    /**
-     * If not already completed, causes invocations of {@link #get()}
-     * and related methods to throw the given exception.
-     *
-     * @param ex the exception
-     * @return {@code true} if this invocation caused this CompletableFuture
-     * to transition to a completed state, else {@code false}
-     */
-    public boolean completeExceptionally(Throwable ex) {
-        if (ex == null) throw new NullPointerException();
-        boolean triggered = internalComplete(new AltResult(ex));
-        postComplete();
-        return triggered;
-    }
-
-    public <U> CompletableFuture<U> thenApply(
-        Function<? super T,? extends U> fn) {
-        return uniApplyStage(null, fn);
-    }
-
-    public <U> CompletableFuture<U> thenApplyAsync(
-        Function<? super T,? extends U> fn) {
-        return uniApplyStage(defaultExecutor(), fn);
-    }
-
-    public <U> CompletableFuture<U> thenApplyAsync(
-        Function<? super T,? extends U> fn, Executor executor) {
-        return uniApplyStage(screenExecutor(executor), fn);
-    }
-
-    public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
-        return uniAcceptStage(null, action);
-    }
-
-    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
-        return uniAcceptStage(defaultExecutor(), action);
-    }
-
-    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
-                                                   Executor executor) {
-        return uniAcceptStage(screenExecutor(executor), action);
-    }
-
-    public CompletableFuture<Void> thenRun(Runnable action) {
-        return uniRunStage(null, action);
-    }
-
-    public CompletableFuture<Void> thenRunAsync(Runnable action) {
-        return uniRunStage(defaultExecutor(), action);
-    }
-
-    public CompletableFuture<Void> thenRunAsync(Runnable action,
-                                                Executor executor) {
-        return uniRunStage(screenExecutor(executor), action);
-    }
-
-    public <U,V> CompletableFuture<V> thenCombine(
-        CompletionStage<? extends U> other,
-        BiFunction<? super T,? super U,? extends V> fn) {
-        return biApplyStage(null, other, fn);
-    }
-
-    public <U,V> CompletableFuture<V> thenCombineAsync(
-        CompletionStage<? extends U> other,
-        BiFunction<? super T,? super U,? extends V> fn) {
-        return biApplyStage(defaultExecutor(), other, fn);
-    }
-
-    public <U,V> CompletableFuture<V> thenCombineAsync(
-        CompletionStage<? extends U> other,
-        BiFunction<? super T,? super U,? extends V> fn, Executor executor) {
-        return biApplyStage(screenExecutor(executor), other, fn);
-    }
-
-    public <U> CompletableFuture<Void> thenAcceptBoth(
-        CompletionStage<? extends U> other,
-        BiConsumer<? super T, ? super U> action) {
-        return biAcceptStage(null, other, action);
-    }
-
-    public <U> CompletableFuture<Void> thenAcceptBothAsync(
-        CompletionStage<? extends U> other,
-        BiConsumer<? super T, ? super U> action) {
-        return biAcceptStage(defaultExecutor(), other, action);
-    }
-
-    public <U> CompletableFuture<Void> thenAcceptBothAsync(
-        CompletionStage<? extends U> other,
-        BiConsumer<? super T, ? super U> action, Executor executor) {
-        return biAcceptStage(screenExecutor(executor), other, action);
-    }
-
-    public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
-                                                Runnable action) {
-        return biRunStage(null, other, action);
-    }
-
-    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
-                                                     Runnable action) {
-        return biRunStage(defaultExecutor(), other, action);
-    }
-
-    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
-                                                     Runnable action,
-                                                     Executor executor) {
-        return biRunStage(screenExecutor(executor), other, action);
-    }
-
-    public <U> CompletableFuture<U> applyToEither(
-        CompletionStage<? extends T> other, Function<? super T, U> fn) {
-        return orApplyStage(null, other, fn);
-    }
-
-    public <U> CompletableFuture<U> applyToEitherAsync(
-        CompletionStage<? extends T> other, Function<? super T, U> fn) {
-        return orApplyStage(defaultExecutor(), other, fn);
-    }
-
-    public <U> CompletableFuture<U> applyToEitherAsync(
-        CompletionStage<? extends T> other, Function<? super T, U> fn,
-        Executor executor) {
-        return orApplyStage(screenExecutor(executor), other, fn);
-    }
-
-    public CompletableFuture<Void> acceptEither(
-        CompletionStage<? extends T> other, Consumer<? super T> action) {
-        return orAcceptStage(null, other, action);
-    }
-
-    public CompletableFuture<Void> acceptEitherAsync(
-        CompletionStage<? extends T> other, Consumer<? super T> action) {
-        return orAcceptStage(defaultExecutor(), other, action);
-    }
-
-    public CompletableFuture<Void> acceptEitherAsync(
-        CompletionStage<? extends T> other, Consumer<? super T> action,
-        Executor executor) {
-        return orAcceptStage(screenExecutor(executor), other, action);
-    }
-
-    public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
-                                                  Runnable action) {
-        return orRunStage(null, other, action);
-    }
-
-    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
-                                                       Runnable action) {
-        return orRunStage(defaultExecutor(), other, action);
-    }
-
-    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
-                                                       Runnable action,
-                                                       Executor executor) {
-        return orRunStage(screenExecutor(executor), other, action);
-    }
-
-    public <U> CompletableFuture<U> thenCompose(
-        Function<? super T, ? extends CompletionStage<U>> fn) {
-        return uniComposeStage(null, fn);
-    }
-
-    public <U> CompletableFuture<U> thenComposeAsync(
-        Function<? super T, ? extends CompletionStage<U>> fn) {
-        return uniComposeStage(defaultExecutor(), fn);
-    }
-
-    public <U> CompletableFuture<U> thenComposeAsync(
-        Function<? super T, ? extends CompletionStage<U>> fn,
-        Executor executor) {
-        return uniComposeStage(screenExecutor(executor), fn);
-    }
-
-    public CompletableFuture<T> whenComplete(
-        BiConsumer<? super T, ? super Throwable> action) {
-        return uniWhenCompleteStage(null, action);
-    }
-
-    public CompletableFuture<T> whenCompleteAsync(
-        BiConsumer<? super T, ? super Throwable> action) {
-        return uniWhenCompleteStage(defaultExecutor(), action);
-    }
-
-    public CompletableFuture<T> whenCompleteAsync(
-        BiConsumer<? super T, ? super Throwable> action, Executor executor) {
-        return uniWhenCompleteStage(screenExecutor(executor), action);
-    }
-
-    public <U> CompletableFuture<U> handle(
-        BiFunction<? super T, Throwable, ? extends U> fn) {
-        return uniHandleStage(null, fn);
-    }
-
-    public <U> CompletableFuture<U> handleAsync(
-        BiFunction<? super T, Throwable, ? extends U> fn) {
-        return uniHandleStage(defaultExecutor(), fn);
-    }
-
-    public <U> CompletableFuture<U> handleAsync(
-        BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
-        return uniHandleStage(screenExecutor(executor), fn);
-    }
-
-    /**
-     * Returns this CompletableFuture.
-     *
-     * @return this CompletableFuture
-     */
-    public CompletableFuture<T> toCompletableFuture() {
-        return this;
-    }
-
-    // not in interface CompletionStage
-
-    /**
-     * Returns a new CompletableFuture that is completed when this
-     * CompletableFuture completes, with the result of the given
-     * function of the exception triggering this CompletableFuture's
-     * completion when it completes exceptionally; otherwise, if this
-     * CompletableFuture completes normally, then the returned
-     * CompletableFuture also completes normally with the same value.
-     * Note: More flexible versions of this functionality are
-     * available using methods {@code whenComplete} and {@code handle}.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletableFuture if this CompletableFuture completed
-     * exceptionally
-     * @return the new CompletableFuture
-     */
-    public CompletableFuture<T> exceptionally(
-        Function<Throwable, ? extends T> fn) {
-        return uniExceptionallyStage(fn);
-    }
-
-
-    /* ------------- Arbitrary-arity constructions -------------- */
-
-    /**
-     * Returns a new CompletableFuture that is completed when all of
-     * the given CompletableFutures complete.  If any of the given
-     * CompletableFutures complete exceptionally, then the returned
-     * CompletableFuture also does so, with a CompletionException
-     * holding this exception as its cause.  Otherwise, the results,
-     * if any, of the given CompletableFutures are not reflected in
-     * the returned CompletableFuture, but may be obtained by
-     * inspecting them individually. If no CompletableFutures are
-     * provided, returns a CompletableFuture completed with the value
-     * {@code null}.
-     *
-     * <p>Among the applications of this method is to await completion
-     * of a set of independent CompletableFutures before continuing a
-     * program, as in: {@code CompletableFuture.allOf(c1, c2,
-     * c3).join();}.
-     *
-     * @param cfs the CompletableFutures
-     * @return a new CompletableFuture that is completed when all of the
-     * given CompletableFutures complete
-     * @throws NullPointerException if the array or any of its elements are
-     * {@code null}
-     */
-    public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
-        return andTree(cfs, 0, cfs.length - 1);
-    }
-
-    /**
-     * Returns a new CompletableFuture that is completed when any of
-     * the given CompletableFutures complete, with the same result.
-     * Otherwise, if it completed exceptionally, the returned
-     * CompletableFuture also does so, with a CompletionException
-     * holding this exception as its cause.  If no CompletableFutures
-     * are provided, returns an incomplete CompletableFuture.
-     *
-     * @param cfs the CompletableFutures
-     * @return a new CompletableFuture that is completed with the
-     * result or exception of any of the given CompletableFutures when
-     * one completes
-     * @throws NullPointerException if the array or any of its elements are
-     * {@code null}
-     */
-    public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
-        return orTree(cfs, 0, cfs.length - 1);
-    }
-
-    /* ------------- Control and status methods -------------- */
-
-    /**
-     * If not already completed, completes this CompletableFuture with
-     * a {@link CancellationException}. Dependent CompletableFutures
-     * that have not already completed will also complete
-     * exceptionally, with a {@link CompletionException} caused by
-     * this {@code CancellationException}.
-     *
-     * @param mayInterruptIfRunning this value has no effect in this
-     * implementation because interrupts are not used to control
-     * processing.
-     *
-     * @return {@code true} if this task is now cancelled
-     */
-    public boolean cancel(boolean mayInterruptIfRunning) {
-        boolean cancelled = (result == null) &&
-            internalComplete(new AltResult(new CancellationException()));
-        postComplete();
-        return cancelled || isCancelled();
-    }
-
-    /**
-     * Returns {@code true} if this CompletableFuture was cancelled
-     * before it completed normally.
-     *
-     * @return {@code true} if this CompletableFuture was cancelled
-     * before it completed normally
-     */
-    public boolean isCancelled() {
-        Object r;
-        return ((r = result) instanceof AltResult) &&
-            (((AltResult)r).ex instanceof CancellationException);
-    }
-
-    /**
-     * Returns {@code true} if this CompletableFuture completed
-     * exceptionally, in any way. Possible causes include
-     * cancellation, explicit invocation of {@code
-     * completeExceptionally}, and abrupt termination of a
-     * CompletionStage action.
-     *
-     * @return {@code true} if this CompletableFuture completed
-     * exceptionally
-     */
-    public boolean isCompletedExceptionally() {
-        Object r;
-        return ((r = result) instanceof AltResult) && r != NIL;
-    }
-
-    /**
-     * Forcibly sets or resets the value subsequently returned by
-     * method {@link #get()} and related methods, whether or not
-     * already completed. This method is designed for use only in
-     * error recovery actions, and even in such situations may result
-     * in ongoing dependent completions using established versus
-     * overwritten outcomes.
-     *
-     * @param value the completion value
-     */
-    public void obtrudeValue(T value) {
-        result = (value == null) ? NIL : value;
-        postComplete();
-    }
-
-    /**
-     * Forcibly causes subsequent invocations of method {@link #get()}
-     * and related methods to throw the given exception, whether or
-     * not already completed. This method is designed for use only in
-     * error recovery actions, and even in such situations may result
-     * in ongoing dependent completions using established versus
-     * overwritten outcomes.
-     *
-     * @param ex the exception
-     * @throws NullPointerException if the exception is null
-     */
-    public void obtrudeException(Throwable ex) {
-        if (ex == null) throw new NullPointerException();
-        result = new AltResult(ex);
-        postComplete();
-    }
-
-    /**
-     * Returns the estimated number of CompletableFutures whose
-     * completions are awaiting completion of this CompletableFuture.
-     * This method is designed for use in monitoring system state, not
-     * for synchronization control.
-     *
-     * @return the number of dependent CompletableFutures
-     */
-    public int getNumberOfDependents() {
-        int count = 0;
-        for (Completion p = stack; p != null; p = p.next)
-            ++count;
-        return count;
-    }
-
-    /**
-     * Returns a string identifying this CompletableFuture, as well as
-     * its completion state.  The state, in brackets, contains the
-     * String {@code "Completed Normally"} or the String {@code
-     * "Completed Exceptionally"}, or the String {@code "Not
-     * completed"} followed by the number of CompletableFutures
-     * dependent upon its completion, if any.
-     *
-     * @return a string identifying this CompletableFuture, as well as its state
-     */
-    public String toString() {
-        Object r = result;
-        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 == 0) ?
-              "[Not completed]" :
-              "[Not completed, " + count + " dependents]") :
-             (((r instanceof AltResult) && ((AltResult)r).ex != null) ?
-              "[Completed exceptionally]" :
-              "[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 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 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 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 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 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 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 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 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 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 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 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 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 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 U = sun.misc.Unsafe.getUnsafe();
-    private static final long RESULT;
-    private static final long STACK;
-    private static final long NEXT;
-    static {
-        try {
-            RESULT = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("result"));
-            STACK = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("stack"));
-            NEXT = U.objectFieldOffset
-                (Completion.class.getDeclaredField("next"));
-        } 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;
-    }
-}
diff --git a/luni/src/main/java/java/util/concurrent/CompletionException.java b/luni/src/main/java/java/util/concurrent/CompletionException.java
deleted file mode 100644
index 9b905d2..0000000
--- a/luni/src/main/java/java/util/concurrent/CompletionException.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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;
-
-/**
- * Exception thrown when an error or other exception is encountered
- * in the course of completing a result or task.
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class CompletionException extends RuntimeException {
-    private static final long serialVersionUID = 7830266012832686185L;
-
-    /**
-     * Constructs a {@code CompletionException} with no detail message.
-     * The cause is not initialized, and may subsequently be
-     * initialized by a call to {@link #initCause(Throwable) initCause}.
-     */
-    protected CompletionException() { }
-
-    /**
-     * Constructs a {@code CompletionException} with the specified detail
-     * message. The cause is not initialized, and may subsequently be
-     * initialized by a call to {@link #initCause(Throwable) initCause}.
-     *
-     * @param message the detail message
-     */
-    protected CompletionException(String message) {
-        super(message);
-    }
-
-    /**
-     * Constructs a {@code CompletionException} with the specified detail
-     * message and cause.
-     *
-     * @param  message the detail message
-     * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method)
-     */
-    public CompletionException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    /**
-     * Constructs a {@code CompletionException} with the specified cause.
-     * The detail message is set to {@code (cause == null ? null :
-     * cause.toString())} (which typically contains the class and
-     * detail message of {@code cause}).
-     *
-     * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method)
-     */
-    public CompletionException(Throwable cause) {
-        super(cause);
-    }
-}
diff --git a/luni/src/main/java/java/util/concurrent/CompletionStage.java b/luni/src/main/java/java/util/concurrent/CompletionStage.java
deleted file mode 100644
index ccb1aa4..0000000
--- a/luni/src/main/java/java/util/concurrent/CompletionStage.java
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * 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.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * A stage of a possibly asynchronous computation, that performs an
- * action or computes a value when another CompletionStage completes.
- * A stage completes upon termination of its computation, but this may
- * in turn trigger other dependent stages.  The functionality defined
- * in this interface takes only a few basic forms, which expand out to
- * a larger set of methods to capture a range of usage styles:
- *
- * <ul>
- *
- * <li>The computation performed by a stage may be expressed as a
- * Function, Consumer, or Runnable (using methods with names including
- * <em>apply</em>, <em>accept</em>, or <em>run</em>, respectively)
- * depending on whether it requires arguments and/or produces results.
- * For example:
- * <pre> {@code
- * stage.thenApply(x -> square(x))
- *      .thenAccept(x -> System.out.print(x))
- *      .thenRun(() -> System.out.println());}</pre>
- *
- * An additional form (<em>compose</em>) allows the construction of
- * computation pipelines from functions returning completion stages.
- *
- * <p>Any argument to a stage's computation is the outcome of a
- * triggering stage's computation.
- *
- * <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
- * <em>both</em> of two stages may <em>combine</em> their results or
- * 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>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
- * asynchronous execution (using methods with suffix <em>async</em>
- * that employ the stage's default asynchronous execution facility),
- * or custom (via a supplied {@link Executor}).  The execution
- * properties of default and async modes are specified by
- * CompletionStage implementations, not this interface. Methods with
- * explicit Executor arguments may have arbitrary execution
- * properties, and might not even support concurrent execution, but
- * are arranged for processing in a way that accommodates asynchrony.
- *
- * <li>Two method forms ({@link #handle handle} and {@link
- * #whenComplete whenComplete}) support unconditional computation
- * whether the triggering stage completed normally or exceptionally.
- * Method {@link #exceptionally exceptionally} supports computation
- * only when the triggering stage completes exceptionally, computing a
- * replacement result, similarly to the java {@code catch} keyword.
- * In all other cases, if a stage's computation terminates abruptly
- * with an (unchecked) exception or error, then all dependent stages
- * requiring its completion complete exceptionally as well, with a
- * {@link CompletionException} holding the exception as its cause.  If
- * a stage is dependent on <em>both</em> of two stages, and both
- * complete exceptionally, then the CompletionException may correspond
- * to either one of these exceptions.  If a stage is dependent on
- * <em>either</em> of two others, and only one of them completes
- * exceptionally, no guarantees are made about whether the dependent
- * stage completes normally or exceptionally. In the case of method
- * {@code whenComplete}, when the supplied action itself encounters an
- * exception, then the stage completes exceptionally with this
- * exception unless the source stage also completed exceptionally, in
- * which case the exceptional completion from the source stage is
- * given preference and propagated to the dependent stage.
- *
- * </ul>
- *
- * <p>All methods adhere to the above triggering, execution, and
- * exceptional completion specifications (which are not repeated in
- * individual method specifications). Additionally, while arguments
- * used to pass a completion result (that is, for parameters of type
- * {@code T}) for methods accepting them may be null, passing a null
- * value for any other parameter will result in a {@link
- * NullPointerException} being thrown.
- *
- * <p>Method form {@link #handle handle} is the most general way of
- * creating a continuation stage, unconditionally performing a
- * computation that is given both the result and exception (if any) of
- * the triggering CompletionStage, and computing an arbitrary result.
- * Method {@link #whenComplete whenComplete} is similar, but preserves
- * the result of the triggering stage instead of computing a new one.
- * Because a stage's normal result may be {@code null}, both methods
- * should have a computation structured thus:
- *
- * <pre>{@code (result, exception) -> {
- *   if (exception == null) {
- *     // triggering stage completed normally
- *   } else {
- *     // triggering stage completed exceptionally
- *   }
- * }}</pre>
- *
- * <p>This interface does not define methods for initially creating,
- * forcibly completing normally or exceptionally, probing completion
- * status or results, or awaiting completion of a stage.
- * Implementations of CompletionStage may provide means of achieving
- * such effects, as appropriate.  Method {@link #toCompletableFuture}
- * enables interoperability among different implementations of this
- * interface by providing a common conversion type.
- *
- * @author Doug Lea
- * @since 1.8
- */
-public interface CompletionStage<T> {
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed with this stage's result as the argument
-     * to the supplied function.
-     *
-     * <p>This method is analogous to
-     * {@link java.util.Optional#map Optional.map} and
-     * TODO(streams): make a link to java.util.stream.Stream#map Stream.map.
-     *
-     * <p>See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed using this stage's default asynchronous
-     * execution facility, with this stage's result as the argument to
-     * the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenApplyAsync
-        (Function<? super T,? extends U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed using the supplied Executor, with this
-     * stage's result as the argument to the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenApplyAsync
-        (Function<? super T,? extends U> fn,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed with this stage's result as the argument
-     * to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenAccept(Consumer<? super T> action);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed using this stage's default asynchronous
-     * execution facility, with this stage's result as the argument to
-     * the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, is executed using the supplied Executor, with this
-     * stage's result as the argument to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
-                                                 Executor executor);
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, executes the given action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenRun(Runnable action);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, executes the given action using this stage's default
-     * asynchronous execution facility.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenRunAsync(Runnable action);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * normally, executes the given action using the supplied Executor.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> thenRunAsync(Runnable action,
-                                              Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed with the two
-     * results as arguments to the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the type of the other CompletionStage's result
-     * @param <V> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U,V> CompletionStage<V> thenCombine
-        (CompletionStage<? extends U> other,
-         BiFunction<? super T,? super U,? extends V> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed using this
-     * stage's default asynchronous execution facility, with the two
-     * results as arguments to the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the type of the other CompletionStage's result
-     * @param <V> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U,V> CompletionStage<V> thenCombineAsync
-        (CompletionStage<? extends U> other,
-         BiFunction<? super T,? super U,? extends V> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed using the
-     * supplied executor, with the two results as arguments to the
-     * supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the type of the other CompletionStage's result
-     * @param <V> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U,V> CompletionStage<V> thenCombineAsync
-        (CompletionStage<? extends U> other,
-         BiFunction<? super T,? super U,? extends V> fn,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed with the two
-     * results as arguments to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param <U> the type of the other CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<Void> thenAcceptBoth
-        (CompletionStage<? extends U> other,
-         BiConsumer<? super T, ? super U> action);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed using this
-     * stage's default asynchronous execution facility, with the two
-     * results as arguments to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param <U> the type of the other CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<Void> thenAcceptBothAsync
-        (CompletionStage<? extends U> other,
-         BiConsumer<? super T, ? super U> action);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, is executed using the
-     * supplied executor, with the two results as arguments to the
-     * supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the type of the other CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<Void> thenAcceptBothAsync
-        (CompletionStage<? extends U> other,
-         BiConsumer<? super T, ? super U> action,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, executes the given action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,
-                                              Runnable action);
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, executes the given action
-     * using this stage's default asynchronous execution facility.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
-                                                   Runnable action);
-
-    /**
-     * Returns a new CompletionStage that, when this and the other
-     * given stage both complete normally, executes the given action
-     * using the supplied executor.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
-                                                   Runnable action,
-                                                   Executor executor);
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed with the
-     * corresponding result as argument to the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> applyToEither
-        (CompletionStage<? extends T> other,
-         Function<? super T, U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed using this
-     * stage's default asynchronous execution facility, with the
-     * corresponding result as argument to the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> applyToEitherAsync
-        (CompletionStage<? extends T> other,
-         Function<? super T, U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed using the
-     * supplied executor, with the corresponding result as argument to
-     * the supplied function.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> applyToEitherAsync
-        (CompletionStage<? extends T> other,
-         Function<? super T, U> fn,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed with the
-     * corresponding result as argument to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> acceptEither
-        (CompletionStage<? extends T> other,
-         Consumer<? super T> action);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed using this
-     * stage's default asynchronous execution facility, with the
-     * corresponding result as argument to the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> acceptEitherAsync
-        (CompletionStage<? extends T> other,
-         Consumer<? super T> action);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, is executed using the
-     * supplied executor, with the corresponding result as argument to
-     * the supplied action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> acceptEitherAsync
-        (CompletionStage<? extends T> other,
-         Consumer<? super T> action,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, executes the given action.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterEither(CompletionStage<?> other,
-                                                Runnable action);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, executes the given action
-     * using this stage's default asynchronous execution facility.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterEitherAsync
-        (CompletionStage<?> other,
-         Runnable action);
-
-    /**
-     * Returns a new CompletionStage that, when either this or the
-     * other given stage complete normally, executes the given action
-     * using the supplied executor.
-     *
-     * See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param other the other CompletionStage
-     * @param action the action to perform before completing the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<Void> runAfterEitherAsync
-        (CompletionStage<?> other,
-         Runnable action,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that is completed with the same
-     * value as the CompletionStage returned by the given function.
-     *
-     * <p>When this stage completes normally, the given function is
-     * invoked with this stage's result as the argument, returning
-     * another CompletionStage.  When that stage completes normally,
-     * the CompletionStage returned by this method is completed with
-     * the same value.
-     *
-     * <p>To ensure progress, the supplied function must arrange
-     * eventual completion of its result.
-     *
-     * <p>This method is analogous to
-     * {@link java.util.Optional#flatMap Optional.flatMap} and
-     * TODO(streams): make a link to java.util.stream.Stream#flatMap Stream.flatMap.
-     *
-     * <p>See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute another CompletionStage
-     * @param <U> the type of the returned CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenCompose
-        (Function<? super T, ? extends CompletionStage<U>> fn);
-
-    /**
-     * Returns a new CompletionStage that is completed with the same
-     * value as the CompletionStage returned by the given function,
-     * executed using this stage's default asynchronous execution
-     * facility.
-     *
-     * <p>When this stage completes normally, the given function is
-     * invoked with this stage's result as the argument, returning
-     * another CompletionStage.  When that stage completes normally,
-     * the CompletionStage returned by this method is completed with
-     * the same value.
-     *
-     * <p>To ensure progress, the supplied function must arrange
-     * eventual completion of its result.
-     *
-     * <p>See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute another CompletionStage
-     * @param <U> the type of the returned CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenComposeAsync
-        (Function<? super T, ? extends CompletionStage<U>> fn);
-
-    /**
-     * Returns a new CompletionStage that is completed with the same
-     * value as the CompletionStage returned by the given function,
-     * executed using the supplied Executor.
-     *
-     * <p>When this stage completes normally, the given function is
-     * invoked with this stage's result as the argument, returning
-     * another CompletionStage.  When that stage completes normally,
-     * the CompletionStage returned by this method is completed with
-     * the same value.
-     *
-     * <p>To ensure progress, the supplied function must arrange
-     * eventual completion of its result.
-     *
-     * <p>See the {@link CompletionStage} documentation for rules
-     * covering exceptional completion.
-     *
-     * @param fn the function to use to compute another CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the type of the returned CompletionStage's result
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> thenComposeAsync
-        (Function<? super T, ? extends CompletionStage<U>> fn,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * either normally or exceptionally, is executed with this stage's
-     * result and exception as arguments to the supplied function.
-     *
-     * <p>When this stage is complete, the given function is invoked
-     * with the result (or {@code null} if none) and the exception (or
-     * {@code null} if none) of this stage as arguments, and the
-     * function's result is used to complete the returned stage.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> handle
-        (BiFunction<? super T, Throwable, ? extends U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * either normally or exceptionally, is executed using this stage's
-     * default asynchronous execution facility, with this stage's
-     * result and exception as arguments to the supplied function.
-     *
-     * <p>When this stage is complete, the given function is invoked
-     * with the result (or {@code null} if none) and the exception (or
-     * {@code null} if none) of this stage as arguments, and the
-     * function's result is used to complete the returned stage.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> handleAsync
-        (BiFunction<? super T, Throwable, ? extends U> fn);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * either normally or exceptionally, is executed using the
-     * supplied executor, with this stage's result and exception as
-     * arguments to the supplied function.
-     *
-     * <p>When this stage is complete, the given function is invoked
-     * with the result (or {@code null} if none) and the exception (or
-     * {@code null} if none) of this stage as arguments, and the
-     * function's result is used to complete the returned stage.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage
-     * @param executor the executor to use for asynchronous execution
-     * @param <U> the function's return type
-     * @return the new CompletionStage
-     */
-    public <U> CompletionStage<U> handleAsync
-        (BiFunction<? super T, Throwable, ? extends U> fn,
-         Executor executor);
-
-    /**
-     * 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.
-     *
-     * <p>Unlike method {@link #handle handle},
-     * this method is not designed to translate completion outcomes,
-     * so the supplied action should not throw an exception. However,
-     * if it does, the following rules apply: if this stage completed
-     * normally but the supplied action throws an exception, then the
-     * returned stage completes exceptionally with the supplied
-     * action's exception. Or, if this stage completed exceptionally
-     * and the supplied action throws an exception, then the returned
-     * stage completes exceptionally with this stage's exception.
-     *
-     * @param action the action to perform
-     * @return the new CompletionStage
-     */
-    public CompletionStage<T> whenComplete
-        (BiConsumer<? super T, ? super Throwable> action);
-
-    /**
-     * Returns a new CompletionStage with the same result or exception as
-     * this stage, that executes the given action using this stage's
-     * default asynchronous execution facility 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.
-     *
-     * <p>Unlike method {@link #handleAsync(BiFunction) handleAsync},
-     * this method is not designed to translate completion outcomes,
-     * so the supplied action should not throw an exception. However,
-     * if it does, the following rules apply: If this stage completed
-     * normally but the supplied action throws an exception, then the
-     * returned stage completes exceptionally with the supplied
-     * action's exception. Or, if this stage completed exceptionally
-     * and the supplied action throws an exception, then the returned
-     * stage completes exceptionally with this stage's exception.
-     *
-     * @param action the action to perform
-     * @return the new CompletionStage
-     */
-    public CompletionStage<T> whenCompleteAsync
-        (BiConsumer<? super T, ? super Throwable> action);
-
-    /**
-     * Returns a new CompletionStage with the same result or exception as
-     * this stage, that executes the given action using the supplied
-     * Executor 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.
-     *
-     * <p>Unlike method {@link #handleAsync(BiFunction,Executor) handleAsync},
-     * this method is not designed to translate completion outcomes,
-     * so the supplied action should not throw an exception. However,
-     * if it does, the following rules apply: If this stage completed
-     * normally but the supplied action throws an exception, then the
-     * returned stage completes exceptionally with the supplied
-     * action's exception. Or, if this stage completed exceptionally
-     * and the supplied action throws an exception, then the returned
-     * stage completes exceptionally with this stage's exception.
-     *
-     * @param action the action to perform
-     * @param executor the executor to use for asynchronous execution
-     * @return the new CompletionStage
-     */
-    public CompletionStage<T> whenCompleteAsync
-        (BiConsumer<? super T, ? super Throwable> action,
-         Executor executor);
-
-    /**
-     * Returns a new CompletionStage that, when this stage completes
-     * exceptionally, is executed with this stage's exception as the
-     * argument to the supplied function.  Otherwise, if this stage
-     * completes normally, then the returned stage also completes
-     * normally with the same value.
-     *
-     * @param fn the function to use to compute the value of the
-     * returned CompletionStage if this CompletionStage completed
-     * exceptionally
-     * @return the new CompletionStage
-     */
-    public CompletionStage<T> exceptionally
-        (Function<Throwable, ? extends T> fn);
-
-    /**
-     * Returns a {@link CompletableFuture} maintaining the same
-     * completion properties as this stage. If this stage is already a
-     * CompletableFuture, this method may return this stage itself.
-     * Otherwise, invocation of this method may be equivalent in
-     * effect to {@code thenApply(x -> x)}, but returning an instance
-     * of type {@code CompletableFuture}. A CompletionStage
-     * implementation that does not choose to interoperate with others
-     * may throw {@code UnsupportedOperationException}.
-     *
-     * @return the CompletableFuture
-     * @throws UnsupportedOperationException if this implementation
-     * does not interoperate with CompletableFuture
-     */
-    public CompletableFuture<T> toCompletableFuture();
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index b4fa8aa..3ed54cf 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -13,6 +13,7 @@
 import java.util.AbstractMap;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.ConcurrentModificationException;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -20,29 +21,14 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
-import java.util.Spliterator;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
 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.Consumer;
-import java.util.function.DoubleBinaryOperator;
-import java.util.function.Function;
-import java.util.function.IntBinaryOperator;
-import java.util.function.LongBinaryOperator;
-import java.util.function.Predicate;
-import java.util.function.ToDoubleBiFunction;
-import java.util.function.ToDoubleFunction;
-import java.util.function.ToIntBiFunction;
-import java.util.function.ToIntFunction;
-import java.util.function.ToLongBiFunction;
-import java.util.function.ToLongFunction;
-// TODO(streams):
-//import java.util.stream.Stream;
 
 // BEGIN android-note
 // removed link to collections framework docs
+// removed links to hidden api
 // END android-note
 
 /**
@@ -66,14 +52,14 @@
  * that key reporting the updated value.)  For aggregate operations
  * such as {@code putAll} and {@code clear}, concurrent retrievals may
  * reflect insertion or removal of only some entries.  Similarly,
- * Iterators, Spliterators and Enumerations return elements reflecting the
- * state of the hash table at some point at or since the creation of the
+ * Iterators and Enumerations return elements reflecting the state of
+ * the hash table at some point at or since the creation of the
  * iterator/enumeration.  They do <em>not</em> throw {@link
- * java.util.ConcurrentModificationException ConcurrentModificationException}.
- * However, iterators are designed to be used by only one thread at a time.
- * Bear in mind that the results of aggregate status methods including
- * {@code size}, {@code isEmpty}, and {@code containsValue} are typically
- * useful only when a map is not undergoing concurrent updates in other threads.
+ * ConcurrentModificationException}.  However, iterators are designed
+ * to be used by only one thread at a time.  Bear in mind that the
+ * results of aggregate status methods including {@code size}, {@code
+ * isEmpty}, and {@code containsValue} are typically useful only when
+ * a map is not undergoing concurrent updates in other threads.
  * Otherwise the results of these methods reflect transient states
  * that may be adequate for monitoring or estimation purposes, but not
  * for program control.
@@ -100,19 +86,6 @@
  * hash table. To ameliorate impact, when keys are {@link Comparable},
  * this class may use comparison order among keys to help break ties.
  *
- * <p>A {@link Set} projection of a ConcurrentHashMap may be created
- * (using {@link #newKeySet()} or {@link #newKeySet(int)}), or viewed
- * (using {@link #keySet(Object)} when only keys are of interest, and the
- * mapped values are (perhaps transiently) not used or all take the
- * same mapping value.
- *
- * <p>A ConcurrentHashMap can be used as a scalable frequency map (a
- * form of histogram or multiset) by using {@link
- * java.util.concurrent.atomic.LongAdder} values and initializing via
- * {@link #computeIfAbsent computeIfAbsent}. For example, to add a count
- * to a {@code ConcurrentHashMap<String,LongAdder> freqs}, you can use
- * {@code freqs.computeIfAbsent(key, k -> new LongAdder()).increment();}
- *
  * <p>This class and its views and iterators implement all of the
  * <em>optional</em> methods of the {@link Map} and {@link Iterator}
  * interfaces.
@@ -120,121 +93,15 @@
  * <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
  * does <em>not</em> allow {@code null} to be used as a key or value.
  *
- * <p>ConcurrentHashMaps support a set of sequential and parallel bulk
- * operations that, unlike most (TODO(streams): link to Stream) methods, are designed
- * to be safely, and often sensibly, applied even with maps that are
- * 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) 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: Performs a given action on each element.
- * A variant form applies a given transformation on each element
- * before performing the action.
- *
- * <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>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
- * (key, value) function arguments since there is no corresponding
- * return type.)
- *
- * <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.
- *
- * </ul>
- * </ul>
- *
- * <p>These bulk operations accept a {@code parallelismThreshold}
- * argument. Methods proceed sequentially if the current map size is
- * estimated to be less than the given threshold. Using a value of
- * {@code Long.MAX_VALUE} suppresses all parallelism.  Using a value
- * of {@code 1} results in maximal parallelism by partitioning into
- * enough subtasks to fully utilize the {@link
- * ForkJoinPool#commonPool()} that is used for all parallel
- * computations. Normally, you would initially choose one of these
- * extreme values, and then measure performance of using in-between
- * values that trade off overhead versus throughput.
- *
- * <p>The concurrency properties of bulk operations follow
- * from those of ConcurrentHashMap: Any non-null result returned
- * from {@code get(key)} and related access methods bears a
- * happens-before relation with the associated insertion or
- * update.  The result of any bulk operation reflects the
- * composition of these per-element relations (but is not
- * necessarily atomic with respect to the map as a whole unless it
- * is somehow known to be quiescent).  Conversely, because keys
- * and values in the map are never null, null serves as a reliable
- * atomic indicator of the current lack of any result.  To
- * maintain this property, null serves as an implicit basis for
- * all non-scalar reduction operations. For the double, long, and
- * int versions, the basis should be one that, when combined with
- * any other value, returns that other value (more formally, it
- * should be the identity element for the reduction). Most common
- * reductions have these properties; for example, computing a sum
- * with basis 0 or a minimum with basis MAX_VALUE.
- *
- * <p>Search and transformation functions provided as arguments
- * should similarly return null to indicate the lack of any result
- * (in which case it is not used). In the case of mapped
- * reductions, this also enables transformations to serve as
- * filters, returning null (or, in the case of primitive
- * specializations, the identity basis) if the element should not
- * be combined. You can create compound transformations and
- * filterings by composing them yourself under this "null means
- * there is nothing there now" rule before using them in search or
- * reduce operations.
- *
- * <p>Methods accepting and/or returning Entry arguments maintain
- * key-value associations. They may be useful for example when
- * finding the key for the greatest value. Note that "plain" Entry
- * arguments can be supplied using {@code new
- * AbstractMap.SimpleEntry(k,v)}.
- *
- * <p>Bulk operations may complete abruptly, throwing an
- * exception encountered in the application of a supplied
- * function. Bear in mind when handling such exceptions that other
- * concurrently executing functions could also have thrown
- * exceptions, or would have done so if the first exception had
- * not occurred.
- *
- * <p>Speedups for parallel compared to sequential forms are common
- * but not guaranteed.  Parallel operations involving brief functions
- * on small maps may execute more slowly than sequential forms if the
- * underlying work to parallelize the computation is more expensive
- * than the computation itself.  Similarly, parallelization may not
- * lead to much actual parallelism if all processors are busy
- * performing unrelated tasks.
- *
- * <p>All arguments to all task methods must be non-null.
- *
  * @since 1.5
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
  */
-public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
-    implements ConcurrentMap<K,V>, Serializable {
+// android-note: removed documentation about hidden newKeySet and newKeySet(int) APIs.
+// android-note: Added "extends AbstractMap<K, V>.
+public class ConcurrentHashMap<K,V> extends AbstractMap<K, V>
+        implements ConcurrentMap<K,V>, Serializable {
     private static final long serialVersionUID = 7249069246763182397L;
 
     /*
@@ -449,7 +316,7 @@
      *
      * Maintaining API and serialization compatibility with previous
      * versions of this class introduces several oddities. Mainly: We
-     * leave untouched but unused constructor arguments referring to
+     * leave untouched but unused constructor arguments refering to
      * concurrencyLevel. We accept a loadFactor constructor argument,
      * but apply it only to initial table capacity (which is the only
      * time that we can guarantee to honor it.) We also declare an
@@ -468,6 +335,7 @@
      * bulk operations.
      */
 
+
     /* ---------------- Constants -------------- */
 
     /**
@@ -544,7 +412,7 @@
      * The number of bits used for generation stamp in sizeCtl.
      * Must be at least 6 for 32bit arrays.
      */
-    private static final int RESIZE_STAMP_BITS = 16;
+    private static int RESIZE_STAMP_BITS = 16;
 
     /**
      * The maximum number of threads that can help resize.
@@ -560,28 +428,19 @@
     /*
      * Encodings for Node hash fields. See above for explanation.
      */
-    static final int MOVED     = -1; // hash for forwarding nodes
-    static final int TREEBIN   = -2; // hash for roots of trees
-    static final int RESERVED  = -3; // hash for transient reservations
+    static final int MOVED     = 0x8fffffff; // (-1) hash for forwarding nodes
+    static final int TREEBIN   = 0x80000000; // hash for roots of trees
+    static final int RESERVED  = 0x80000001; // hash for transient reservations
     static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash
 
     /** Number of CPUS, to place bounds on some sizings */
     static final int NCPU = Runtime.getRuntime().availableProcessors();
 
-    /**
-     * Serialized pseudo-fields, provided only for jdk7 compatibility.
-     * @serialField segments Segment[]
-     *   The segments, each of which is a specialized hash table.
-     * @serialField segmentMask int
-     *   Mask value for indexing into segments. The upper bits of a
-     *   key's hash code are used to choose the segment.
-     * @serialField segmentShift int
-     *   Shift value for indexing within segments.
-     */
+    /** For serialization compatibility. */
     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 -------------- */
@@ -598,7 +457,7 @@
         final int hash;
         final K key;
         volatile V val;
-        volatile Node<K,V> next;
+        Node<K,V> next;
 
         Node(int hash, K key, V val, Node<K,V> next) {
             this.hash = hash;
@@ -607,12 +466,10 @@
             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 Helpers.mapEntryToString(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 key + "=" + val; }
         public final V setValue(V value) {
             throw new UnsupportedOperationException();
         }
@@ -725,9 +582,8 @@
      * errors by users, these checks must operate on local variables,
      * which accounts for some odd-looking inline assignments below.
      * Note that calls to setTabAt always occur within locked regions,
-     * and so in principle require only release ordering, not
-     * full volatile semantics, but are currently coded as volatile
-     * writes to be conservative.
+     * and so do not need full volatile semantics, but still require
+     * ordering to maintain concurrent readability.
      */
 
     @SuppressWarnings("unchecked")
@@ -741,7 +597,7 @@
     }
 
     static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
-        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
+        U.putOrderedObject(tab, ((long)i << ASHIFT) + ABASE, v);
     }
 
     /* ---------------- Fields -------------- */
@@ -1036,8 +892,6 @@
                                     p.val = value;
                             }
                         }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (binCount != 0) {
@@ -1140,8 +994,6 @@
                                 }
                             }
                         }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
                     }
                 }
                 if (validated) {
@@ -1202,15 +1054,16 @@
      * operations.  It does not support the {@code add} or
      * {@code addAll} operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#DISTINCT}, and {@link Spliterator#NONNULL}.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * @return the set view
      */
-    public KeySetView<K,V> keySet() {
+    // android-note : changed KeySetView<K,V> to Set<K> to maintain API compatibility.
+    public Set<K> keySet() {
         KeySetView<K,V> ks;
         return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
     }
@@ -1225,11 +1078,11 @@
      * {@code retainAll}, and {@code clear} operations.  It does not
      * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}
-     * and {@link Spliterator#NONNULL}.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * @return the collection view
      */
@@ -1247,11 +1100,11 @@
      * {@code removeAll}, {@code retainAll}, and {@code clear}
      * operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#DISTINCT}, and {@link Spliterator#NONNULL}.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * @return the set view
      */
@@ -1349,7 +1202,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;
@@ -1361,10 +1214,9 @@
      * Saves the state of the {@code ConcurrentHashMap} instance to a
      * stream (i.e., serializes it).
      * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData
-     * the serialized fields, followed by the key (Object) and value
-     * (Object) for each key-value mapping, followed by a null pair.
+     * the key (Object) and value (Object)
+     * for each key-value mapping, followed by a null pair.
      * The key-value mappings are emitted in no particular order.
      */
     private void writeObject(java.io.ObjectOutputStream s)
@@ -1379,8 +1231,7 @@
         }
         int segmentShift = 32 - sshift;
         int segmentMask = ssize - 1;
-        @SuppressWarnings("unchecked")
-        Segment<K,V>[] segments = (Segment<K,V>[])
+        @SuppressWarnings("unchecked") Segment<K,V>[] segments = (Segment<K,V>[])
             new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
         for (int i = 0; i < segments.length; ++i)
             segments[i] = new Segment<K,V>(LOAD_FACTOR);
@@ -1400,14 +1251,12 @@
         }
         s.writeObject(null);
         s.writeObject(null);
+        segments = null; // throw away
     }
 
     /**
      * Reconstitutes the instance 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 {
@@ -1423,10 +1272,8 @@
         long size = 0L;
         Node<K,V> p = null;
         for (;;) {
-            @SuppressWarnings("unchecked")
-            K k = (K) s.readObject();
-            @SuppressWarnings("unchecked")
-            V v = (V) s.readObject();
+            @SuppressWarnings("unchecked") K k = (K) s.readObject();
+            @SuppressWarnings("unchecked") V v = (V) s.readObject();
             if (k != null && v != null) {
                 p = new Node<K,V>(spread(k.hashCode()), k, v, p);
                 ++size;
@@ -1445,7 +1292,7 @@
                 n = tableSizeFor(sz + (sz >>> 1) + 1);
             }
             @SuppressWarnings("unchecked")
-            Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
+                Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
             int mask = n - 1;
             long added = 0L;
             while (p != null) {
@@ -1553,544 +1400,17 @@
             throw new NullPointerException();
         return replaceNode(key, value, null);
     }
-
-    // Overrides of JDK8+ Map extension method defaults
-
-    /**
-     * Returns the value to which the specified key is mapped, or the
-     * given default value if this map contains no mapping for the
-     * key.
-     *
-     * @param key the key whose associated value is to be returned
-     * @param defaultValue the value to return if this map contains
-     * no mapping for the given key
-     * @return the mapping for the key, if present; else the default value
-     * @throws NullPointerException if the specified key is null
-     */
-    public V getOrDefault(Object key, V defaultValue) {
-        V v;
-        return (v = get(key)) == null ? defaultValue : v;
-    }
-
-    public void forEach(BiConsumer<? super K, ? super V> action) {
-        if (action == null) throw new NullPointerException();
-        Node<K,V>[] t;
-        if ((t = table) != null) {
-            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-            for (Node<K,V> p; (p = it.advance()) != null; ) {
-                action.accept(p.key, p.val);
-            }
-        }
-    }
-
-    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-        if (function == null) throw new NullPointerException();
-        Node<K,V>[] t;
-        if ((t = table) != null) {
-            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-            for (Node<K,V> p; (p = it.advance()) != null; ) {
-                V oldValue = p.val;
-                for (K key = p.key;;) {
-                    V newValue = function.apply(key, oldValue);
-                    if (newValue == null)
-                        throw new NullPointerException();
-                    if (replaceNode(key, newValue, oldValue) != null ||
-                        (oldValue = get(key)) == null)
-                        break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Helper method for EntrySetView.removeIf.
-     */
-    boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
-        if (function == null) throw new NullPointerException();
-        Node<K,V>[] t;
-        boolean removed = false;
-        if ((t = table) != null) {
-            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-            for (Node<K,V> p; (p = it.advance()) != null; ) {
-                K k = p.key;
-                V v = p.val;
-                Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
-                if (function.test(e) && replaceNode(k, null, v) != null)
-                    removed = true;
-            }
-        }
-        return removed;
-    }
-
-    /**
-     * Helper method for ValuesView.removeIf.
-     */
-    boolean removeValueIf(Predicate<? super V> function) {
-        if (function == null) throw new NullPointerException();
-        Node<K,V>[] t;
-        boolean removed = false;
-        if ((t = table) != null) {
-            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-            for (Node<K,V> p; (p = it.advance()) != null; ) {
-                K k = p.key;
-                V v = p.val;
-                if (function.test(v) && replaceNode(k, null, v) != null)
-                    removed = true;
-            }
-        }
-        return removed;
-    }
-
-    /**
-     * If the specified key is not already associated with a value,
-     * attempts to compute its value using the given mapping function
-     * and enters it into this map unless {@code null}.  The entire
-     * method invocation is performed atomically, so the function is
-     * applied at most once per key.  Some attempted update operations
-     * on this map by other threads may be blocked while computation
-     * is in progress, so the computation should be short and simple,
-     * and must not attempt to update any other mappings of this map.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param mappingFunction the function to compute a value
-     * @return the current (existing or computed) value associated with
-     *         the specified key, or null if the computed value is null
-     * @throws NullPointerException if the specified key or mappingFunction
-     *         is null
-     * @throws IllegalStateException if the computation detectably
-     *         attempts a recursive update to this map that would
-     *         otherwise never complete
-     * @throws RuntimeException or Error if the mappingFunction does so,
-     *         in which case the mapping is left unestablished
-     */
-    public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
-        if (key == null || mappingFunction == null)
-            throw new NullPointerException();
-        int h = spread(key.hashCode());
-        V val = null;
-        int binCount = 0;
-        for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
-            if (tab == null || (n = tab.length) == 0)
-                tab = initTable();
-            else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
-                Node<K,V> r = new ReservationNode<K,V>();
-                synchronized (r) {
-                    if (casTabAt(tab, i, null, r)) {
-                        binCount = 1;
-                        Node<K,V> node = null;
-                        try {
-                            if ((val = mappingFunction.apply(key)) != null)
-                                node = new Node<K,V>(h, key, val, null);
-                        } finally {
-                            setTabAt(tab, i, node);
-                        }
-                    }
-                }
-                if (binCount != 0)
-                    break;
-            }
-            else if ((fh = f.hash) == MOVED)
-                tab = helpTransfer(tab, f);
-            else {
-                boolean added = false;
-                synchronized (f) {
-                    if (tabAt(tab, i) == f) {
-                        if (fh >= 0) {
-                            binCount = 1;
-                            for (Node<K,V> e = f;; ++binCount) {
-                                K ek;
-                                if (e.hash == h &&
-                                    ((ek = e.key) == key ||
-                                     (ek != null && key.equals(ek)))) {
-                                    val = e.val;
-                                    break;
-                                }
-                                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);
-                                    }
-                                    break;
-                                }
-                            }
-                        }
-                        else if (f instanceof TreeBin) {
-                            binCount = 2;
-                            TreeBin<K,V> t = (TreeBin<K,V>)f;
-                            TreeNode<K,V> r, p;
-                            if ((r = t.root) != null &&
-                                (p = r.findTreeNode(h, key, null)) != null)
-                                val = p.val;
-                            else if ((val = mappingFunction.apply(key)) != null) {
-                                added = true;
-                                t.putTreeVal(h, key, val);
-                            }
-                        }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
-                    }
-                }
-                if (binCount != 0) {
-                    if (binCount >= TREEIFY_THRESHOLD)
-                        treeifyBin(tab, i);
-                    if (!added)
-                        return val;
-                    break;
-                }
-            }
-        }
-        if (val != null)
-            addCount(1L, binCount);
-        return val;
-    }
-
-    /**
-     * If the value for the specified key is present, attempts to
-     * compute a new mapping given the key and its current mapped
-     * value.  The entire method invocation is performed atomically.
-     * Some attempted update operations on this map by other threads
-     * may be blocked while computation is in progress, so the
-     * computation should be short and simple, and must not attempt to
-     * update any other mappings of this map.
-     *
-     * @param key key with which a value may be associated
-     * @param remappingFunction the function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key or remappingFunction
-     *         is null
-     * @throws IllegalStateException if the computation detectably
-     *         attempts a recursive update to this map that would
-     *         otherwise never complete
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
-     */
-    public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        if (key == null || remappingFunction == null)
-            throw new NullPointerException();
-        int h = spread(key.hashCode());
-        V val = null;
-        int delta = 0;
-        int binCount = 0;
-        for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
-            if (tab == null || (n = tab.length) == 0)
-                tab = initTable();
-            else if ((f = tabAt(tab, i = (n - 1) & h)) == null)
-                break;
-            else if ((fh = f.hash) == MOVED)
-                tab = helpTransfer(tab, f);
-            else {
-                synchronized (f) {
-                    if (tabAt(tab, i) == f) {
-                        if (fh >= 0) {
-                            binCount = 1;
-                            for (Node<K,V> e = f, pred = null;; ++binCount) {
-                                K ek;
-                                if (e.hash == h &&
-                                    ((ek = e.key) == key ||
-                                     (ek != null && key.equals(ek)))) {
-                                    val = remappingFunction.apply(key, e.val);
-                                    if (val != null)
-                                        e.val = val;
-                                    else {
-                                        delta = -1;
-                                        Node<K,V> en = e.next;
-                                        if (pred != null)
-                                            pred.next = en;
-                                        else
-                                            setTabAt(tab, i, en);
-                                    }
-                                    break;
-                                }
-                                pred = e;
-                                if ((e = e.next) == null)
-                                    break;
-                            }
-                        }
-                        else if (f instanceof TreeBin) {
-                            binCount = 2;
-                            TreeBin<K,V> t = (TreeBin<K,V>)f;
-                            TreeNode<K,V> r, p;
-                            if ((r = t.root) != null &&
-                                (p = r.findTreeNode(h, key, null)) != null) {
-                                val = remappingFunction.apply(key, p.val);
-                                if (val != null)
-                                    p.val = val;
-                                else {
-                                    delta = -1;
-                                    if (t.removeTreeNode(p))
-                                        setTabAt(tab, i, untreeify(t.first));
-                                }
-                            }
-                        }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
-                    }
-                }
-                if (binCount != 0)
-                    break;
-            }
-        }
-        if (delta != 0)
-            addCount((long)delta, binCount);
-        return val;
-    }
-
-    /**
-     * Attempts to compute a mapping for the specified key and its
-     * current mapped value (or {@code null} if there is no current
-     * mapping). The entire method invocation is performed atomically.
-     * Some attempted update operations on this map by other threads
-     * may be blocked while computation is in progress, so the
-     * computation should be short and simple, and must not attempt to
-     * update any other mappings of this Map.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param remappingFunction the function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key or remappingFunction
-     *         is null
-     * @throws IllegalStateException if the computation detectably
-     *         attempts a recursive update to this map that would
-     *         otherwise never complete
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
-     */
-    public V compute(K key,
-                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        if (key == null || remappingFunction == null)
-            throw new NullPointerException();
-        int h = spread(key.hashCode());
-        V val = null;
-        int delta = 0;
-        int binCount = 0;
-        for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
-            if (tab == null || (n = tab.length) == 0)
-                tab = initTable();
-            else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
-                Node<K,V> r = new ReservationNode<K,V>();
-                synchronized (r) {
-                    if (casTabAt(tab, i, null, r)) {
-                        binCount = 1;
-                        Node<K,V> node = null;
-                        try {
-                            if ((val = remappingFunction.apply(key, null)) != null) {
-                                delta = 1;
-                                node = new Node<K,V>(h, key, val, null);
-                            }
-                        } finally {
-                            setTabAt(tab, i, node);
-                        }
-                    }
-                }
-                if (binCount != 0)
-                    break;
-            }
-            else if ((fh = f.hash) == MOVED)
-                tab = helpTransfer(tab, f);
-            else {
-                synchronized (f) {
-                    if (tabAt(tab, i) == f) {
-                        if (fh >= 0) {
-                            binCount = 1;
-                            for (Node<K,V> e = f, pred = null;; ++binCount) {
-                                K ek;
-                                if (e.hash == h &&
-                                    ((ek = e.key) == key ||
-                                     (ek != null && key.equals(ek)))) {
-                                    val = remappingFunction.apply(key, e.val);
-                                    if (val != null)
-                                        e.val = val;
-                                    else {
-                                        delta = -1;
-                                        Node<K,V> en = e.next;
-                                        if (pred != null)
-                                            pred.next = en;
-                                        else
-                                            setTabAt(tab, i, en);
-                                    }
-                                    break;
-                                }
-                                pred = e;
-                                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);
-                                    }
-                                    break;
-                                }
-                            }
-                        }
-                        else if (f instanceof TreeBin) {
-                            binCount = 1;
-                            TreeBin<K,V> t = (TreeBin<K,V>)f;
-                            TreeNode<K,V> r, p;
-                            if ((r = t.root) != null)
-                                p = r.findTreeNode(h, key, null);
-                            else
-                                p = null;
-                            V pv = (p == null) ? null : p.val;
-                            val = remappingFunction.apply(key, pv);
-                            if (val != null) {
-                                if (p != null)
-                                    p.val = val;
-                                else {
-                                    delta = 1;
-                                    t.putTreeVal(h, key, val);
-                                }
-                            }
-                            else if (p != null) {
-                                delta = -1;
-                                if (t.removeTreeNode(p))
-                                    setTabAt(tab, i, untreeify(t.first));
-                            }
-                        }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
-                    }
-                }
-                if (binCount != 0) {
-                    if (binCount >= TREEIFY_THRESHOLD)
-                        treeifyBin(tab, i);
-                    break;
-                }
-            }
-        }
-        if (delta != 0)
-            addCount((long)delta, binCount);
-        return val;
-    }
-
-    /**
-     * If the specified key is not already associated with a
-     * (non-null) value, associates it with the given value.
-     * Otherwise, replaces the value with the results of the given
-     * remapping function, or removes if {@code null}. The entire
-     * method invocation is performed atomically.  Some attempted
-     * update operations on this map by other threads may be blocked
-     * while computation is in progress, so the computation should be
-     * short and simple, and must not attempt to update any other
-     * mappings of this Map.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param value the value to use if absent
-     * @param remappingFunction the function to recompute a value if present
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key or the
-     *         remappingFunction is null
-     * @throws RuntimeException or Error if the remappingFunction does so,
-     *         in which case the mapping is unchanged
-     */
-    public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
-        if (key == null || value == null || remappingFunction == null)
-            throw new NullPointerException();
-        int h = spread(key.hashCode());
-        V val = null;
-        int delta = 0;
-        int binCount = 0;
-        for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
-            if (tab == null || (n = tab.length) == 0)
-                tab = initTable();
-            else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
-                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
-                    delta = 1;
-                    val = value;
-                    break;
-                }
-            }
-            else if ((fh = f.hash) == MOVED)
-                tab = helpTransfer(tab, f);
-            else {
-                synchronized (f) {
-                    if (tabAt(tab, i) == f) {
-                        if (fh >= 0) {
-                            binCount = 1;
-                            for (Node<K,V> e = f, pred = null;; ++binCount) {
-                                K ek;
-                                if (e.hash == h &&
-                                    ((ek = e.key) == key ||
-                                     (ek != null && key.equals(ek)))) {
-                                    val = remappingFunction.apply(e.val, value);
-                                    if (val != null)
-                                        e.val = val;
-                                    else {
-                                        delta = -1;
-                                        Node<K,V> en = e.next;
-                                        if (pred != null)
-                                            pred.next = en;
-                                        else
-                                            setTabAt(tab, i, en);
-                                    }
-                                    break;
-                                }
-                                pred = e;
-                                if ((e = e.next) == null) {
-                                    delta = 1;
-                                    val = value;
-                                    pred.next =
-                                        new Node<K,V>(h, key, val, null);
-                                    break;
-                                }
-                            }
-                        }
-                        else if (f instanceof TreeBin) {
-                            binCount = 2;
-                            TreeBin<K,V> t = (TreeBin<K,V>)f;
-                            TreeNode<K,V> r = t.root;
-                            TreeNode<K,V> p = (r == null) ? null :
-                                r.findTreeNode(h, key, null);
-                            val = (p == null) ? value :
-                                remappingFunction.apply(p.val, value);
-                            if (val != null) {
-                                if (p != null)
-                                    p.val = val;
-                                else {
-                                    delta = 1;
-                                    t.putTreeVal(h, key, val);
-                                }
-                            }
-                            else if (p != null) {
-                                delta = -1;
-                                if (t.removeTreeNode(p))
-                                    setTabAt(tab, i, untreeify(t.first));
-                            }
-                        }
-                        else if (f instanceof ReservationNode)
-                            throw new IllegalStateException("Recursive update");
-                    }
-                }
-                if (binCount != 0) {
-                    if (binCount >= TREEIFY_THRESHOLD)
-                        treeifyBin(tab, i);
-                    break;
-                }
-            }
-        }
-        if (delta != 0)
-            addCount((long)delta, binCount);
-        return val;
-    }
-
     // Hashtable legacy methods
 
     /**
-     * Tests if some key maps into the specified value in this table.
+     * Legacy method testing if some key maps into the specified value
+     * in this table.
      *
-     * <p>Note that this method is identical in functionality to
+     * 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
@@ -2099,7 +1419,11 @@
      *         {@code false} otherwise
      * @throws NullPointerException if the specified value is null
      */
+    // android-note : removed @deprecated tag from javadoc.
     public boolean contains(Object value) {
+        // BEGIN android-note
+        // removed deprecation
+        // END android-note
         return containsValue(value);
     }
 
@@ -2138,6 +1462,8 @@
      *
      * @return the number of mappings
      * @since 1.8
+     *
+     * @hide
      */
     public long mappingCount() {
         long n = sumCount();
@@ -2151,6 +1477,8 @@
      * @param <K> the element type of the returned set
      * @return the new set
      * @since 1.8
+     *
+     * @hide
      */
     public static <K> KeySetView<K,Boolean> newKeySet() {
         return new KeySetView<K,Boolean>
@@ -2168,6 +1496,8 @@
      * @throws IllegalArgumentException if the initial capacity of
      * elements is negative
      * @since 1.8
+     *
+     * @hide
      */
     public static <K> KeySetView<K,Boolean> newKeySet(int initialCapacity) {
         return new KeySetView<K,Boolean>
@@ -2184,6 +1514,8 @@
      * @param mappedValue the mapped value to use for any additions
      * @return the set view
      * @throws NullPointerException if the mappedValue is null
+     *
+     * @hide
      */
     public KeySetView<K,V> keySet(V mappedValue) {
         if (mappedValue == null)
@@ -2204,34 +1536,25 @@
         }
 
         Node<K,V> find(int h, Object k) {
-            // loop to avoid arbitrarily deep recursion on forwarding nodes
-            outer: for (Node<K,V>[] tab = nextTable;;) {
-                Node<K,V> e; int n;
-                if (k == null || tab == null || (n = tab.length) == 0 ||
-                    (e = tabAt(tab, (n - 1) & h)) == null)
-                    return null;
-                for (;;) {
+            Node<K,V> e; int n;
+            Node<K,V>[] tab = nextTable;
+            if (k != null && tab != null && (n = tab.length) > 0 &&
+                (e = tabAt(tab, (n - 1) & h)) != null) {
+                do {
                     int eh; K ek;
                     if ((eh = e.hash) == h &&
                         ((ek = e.key) == k || (ek != null && k.equals(ek))))
                         return e;
-                    if (eh < 0) {
-                        if (e instanceof ForwardingNode) {
-                            tab = ((ForwardingNode<K,V>)e).nextTable;
-                            continue outer;
-                        }
-                        else
-                            return e.find(h, k);
-                    }
-                    if ((e = e.next) == null)
-                        return null;
-                }
+                    if (eh < 0)
+                        return e.find(h, k);
+                } while ((e = e.next) != null);
             }
+            return null;
         }
     }
 
     /**
-     * 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() {
@@ -2293,13 +1616,14 @@
         CounterCell[] as; long b, s;
         if ((as = counterCells) != null ||
             !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
-            CounterCell a; long v; int m;
+            CounterHashCode hc; CounterCell a; long v; int m;
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
+            if ((hc = threadCounterHashCode.get()) == null ||
+                as == null || (m = as.length - 1) < 0 ||
+                (a = as[m & hc.code]) == null ||
                 !(uncontended =
                   U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
-                fullAddCount(x, uncontended);
+                fullAddCount(x, hc, uncontended);
                 return;
             }
             if (check <= 1)
@@ -2380,8 +1704,17 @@
                 break;
             else if (tab == table) {
                 int rs = resizeStamp(n);
-                if (U.compareAndSwapInt(this, SIZECTL, sc,
-                                        (rs << RESIZE_STAMP_SHIFT) + 2))
+                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))
                     transfer(tab, null);
             }
         }
@@ -2524,112 +1857,6 @@
         }
     }
 
-    /* ---------------- Counter support -------------- */
-
-    /**
-     * A padded cell for distributing counts.  Adapted from LongAdder
-     * and Striped64.  See their internal docs for explanation.
-     */
-    //@jdk.internal.vm.annotation.Contended // android-removed
-    static final class CounterCell {
-        volatile long value;
-        CounterCell(long x) { value = x; }
-    }
-
-    final long sumCount() {
-        CounterCell[] as = counterCells; CounterCell a;
-        long sum = baseCount;
-        if (as != null) {
-            for (int i = 0; i < as.length; ++i) {
-                if ((a = as[i]) != null)
-                    sum += a.value;
-            }
-        }
-        return sum;
-    }
-
-    // See LongAdder version for explanation
-    private final void fullAddCount(long x, boolean wasUncontended) {
-        int h;
-        if ((h = ThreadLocalRandom.getProbe()) == 0) {
-            ThreadLocalRandom.localInit();      // force initialization
-            h = ThreadLocalRandom.getProbe();
-            wasUncontended = true;
-        }
-        boolean collide = false;                // True if last slot nonempty
-        for (;;) {
-            CounterCell[] as; CounterCell a; int n; long v;
-            if ((as = counterCells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
-                    if (cellsBusy == 0) {            // Try to attach new Cell
-                        CounterCell r = new CounterCell(x); // Optimistic create
-                        if (cellsBusy == 0 &&
-                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
-                            boolean created = false;
-                            try {               // Recheck under lock
-                                CounterCell[] rs; int m, j;
-                                if ((rs = counterCells) != null &&
-                                    (m = rs.length) > 0 &&
-                                    rs[j = (m - 1) & h] == null) {
-                                    rs[j] = r;
-                                    created = true;
-                                }
-                            } finally {
-                                cellsBusy = 0;
-                            }
-                            if (created)
-                                break;
-                            continue;           // Slot is now non-empty
-                        }
-                    }
-                    collide = false;
-                }
-                else if (!wasUncontended)       // CAS already known to fail
-                    wasUncontended = true;      // Continue after rehash
-                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
-                    break;
-                else if (counterCells != as || n >= NCPU)
-                    collide = false;            // At max size or stale
-                else if (!collide)
-                    collide = true;
-                else if (cellsBusy == 0 &&
-                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
-                    try {
-                        if (counterCells == as) {// Expand table unless stale
-                            CounterCell[] rs = new CounterCell[n << 1];
-                            for (int i = 0; i < n; ++i)
-                                rs[i] = as[i];
-                            counterCells = rs;
-                        }
-                    } finally {
-                        cellsBusy = 0;
-                    }
-                    collide = false;
-                    continue;                   // Retry with expanded table
-                }
-                h = ThreadLocalRandom.advanceProbe(h);
-            }
-            else if (cellsBusy == 0 && counterCells == as &&
-                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
-                boolean init = false;
-                try {                           // Initialize table
-                    if (counterCells == as) {
-                        CounterCell[] rs = new CounterCell[2];
-                        rs[h & 1] = new CounterCell(x);
-                        counterCells = rs;
-                        init = true;
-                    }
-                } finally {
-                    cellsBusy = 0;
-                }
-                if (init)
-                    break;
-            }
-            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
-                break;                          // Fall back on using base
-        }
-    }
-
     /* ---------------- Conversion from/to TreeBins -------------- */
 
     /**
@@ -2637,7 +1864,7 @@
      * too small, in which case resizes instead.
      */
     private final void treeifyBin(Node<K,V>[] tab, int index) {
-        Node<K,V> b; int n;
+        Node<K,V> b; int n, sc;
         if (tab != null) {
             if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
                 tryPresize(n << 1);
@@ -2681,7 +1908,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
@@ -2734,6 +1961,7 @@
         }
     }
 
+
     /* ---------------- TreeBins -------------- */
 
     /**
@@ -2800,7 +2028,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)
@@ -2878,9 +2106,13 @@
                             p = ((r = root) == null ? null :
                                  r.findTreeNode(h, k, null));
                         } finally {
+
                             Thread w;
-                            if (U.getAndAddInt(this, LOCKSTATE, -READER) ==
-                                (READER|WAITER) && (w = waiter) != null)
+                            int ls;
+                            do {} while (!U.compareAndSwapInt
+                                         (this, LOCKSTATE,
+                                          ls = lockState, ls - READER));
+                            if (ls == (READER|WAITER) && (w = waiter) != null)
                                 LockSupport.unpark(w);
                         }
                         return p;
@@ -2894,6 +2126,10 @@
          * Finds or adds a node.
          * @return null if added
          */
+        /**
+         * Finds or adds a node.
+         * @return null if added
+         */
         final TreeNode<K,V> putTreeVal(int h, K k, V v) {
             Class<?> kc = null;
             boolean searched = false;
@@ -3244,7 +2480,7 @@
         }
 
         /**
-         * Checks invariants recursively for the tree of Nodes rooted at t.
+         * Recursive invariant check
          */
         static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
             TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
@@ -3268,13 +2504,15 @@
             return true;
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final sun.misc.Unsafe U;
         private static final long LOCKSTATE;
         static {
             try {
+                U = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = TreeBin.class;
                 LOCKSTATE = U.objectFieldOffset
-                    (TreeBin.class.getDeclaredField("lockState"));
-            } catch (ReflectiveOperationException e) {
+                    (k.getDeclaredField("lockState"));
+            } catch (Exception e) {
                 throw new Error(e);
             }
         }
@@ -3489,7 +2727,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
@@ -3503,9 +2741,7 @@
         public K getKey()        { return key; }
         public V getValue()      { return val; }
         public int hashCode()    { return key.hashCode() ^ val.hashCode(); }
-        public String toString() {
-            return Helpers.mapEntryToString(key, val);
-        }
+        public String toString() { return key + "=" + val; }
 
         public boolean equals(Object o) {
             Object k, v; Map.Entry<?,?> e;
@@ -3533,866 +2769,6 @@
         }
     }
 
-    static final class KeySpliterator<K,V> extends Traverser<K,V>
-        implements Spliterator<K> {
-        long est;               // size estimate
-        KeySpliterator(Node<K,V>[] tab, int size, int index, int limit,
-                       long est) {
-            super(tab, size, index, limit);
-            this.est = est;
-        }
-
-        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,
-                                        f, est >>>= 1);
-        }
-
-        public void forEachRemaining(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            for (Node<K,V> p; (p = advance()) != null;)
-                action.accept(p.key);
-        }
-
-        public boolean tryAdvance(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V> p;
-            if ((p = advance()) == null)
-                return false;
-            action.accept(p.key);
-            return true;
-        }
-
-        public long estimateSize() { return est; }
-
-        public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.CONCURRENT |
-                Spliterator.NONNULL;
-        }
-    }
-
-    static final class ValueSpliterator<K,V> extends Traverser<K,V>
-        implements Spliterator<V> {
-        long est;               // size estimate
-        ValueSpliterator(Node<K,V>[] tab, int size, int index, int limit,
-                         long est) {
-            super(tab, size, index, limit);
-            this.est = est;
-        }
-
-        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,
-                                          f, est >>>= 1);
-        }
-
-        public void forEachRemaining(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            for (Node<K,V> p; (p = advance()) != null;)
-                action.accept(p.val);
-        }
-
-        public boolean tryAdvance(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V> p;
-            if ((p = advance()) == null)
-                return false;
-            action.accept(p.val);
-            return true;
-        }
-
-        public long estimateSize() { return est; }
-
-        public int characteristics() {
-            return Spliterator.CONCURRENT | Spliterator.NONNULL;
-        }
-    }
-
-    static final class EntrySpliterator<K,V> extends Traverser<K,V>
-        implements Spliterator<Map.Entry<K,V>> {
-        final ConcurrentHashMap<K,V> map; // To export MapEntry
-        long est;               // size estimate
-        EntrySpliterator(Node<K,V>[] tab, int size, int index, int limit,
-                         long est, ConcurrentHashMap<K,V> map) {
-            super(tab, size, index, limit);
-            this.map = map;
-            this.est = est;
-        }
-
-        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,
-                                          f, est >>>= 1, map);
-        }
-
-        public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
-            if (action == null) throw new NullPointerException();
-            for (Node<K,V> p; (p = advance()) != null; )
-                action.accept(new MapEntry<K,V>(p.key, p.val, map));
-        }
-
-        public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V> p;
-            if ((p = advance()) == null)
-                return false;
-            action.accept(new MapEntry<K,V>(p.key, p.val, map));
-            return true;
-        }
-
-        public long estimateSize() { return est; }
-
-        public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.CONCURRENT |
-                Spliterator.NONNULL;
-        }
-    }
-
-    // Parallel bulk operations
-
-    /**
-     * Computes initial batch value for bulk tasks. The returned value
-     * is approximately exp2 of the number of times (minus one) to
-     * split task by two before executing leaf action. This value is
-     * faster to compute and more convenient to use as a guide to
-     * splitting than is the depth, since it is used while dividing by
-     * two anyway.
-     */
-    final int batchFor(long b) {
-        long n;
-        if (b == Long.MAX_VALUE || (n = sumCount()) <= 1L || n < b)
-            return 0;
-        int sp = ForkJoinPool.getCommonPoolParallelism() << 2; // slack of 4
-        return (b <= 0L || (n /= b) >= sp) ? sp : (int)n;
-    }
-
-    /**
-     * Performs the given action for each (key, value).
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param action the action
-     * @since 1.8
-     */
-    public void forEach(long parallelismThreshold,
-                        BiConsumer<? super K,? super V> action) {
-        if (action == null) throw new NullPointerException();
-        new ForEachMappingTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             action).invoke();
-    }
-
-    /**
-     * Performs the given action for each non-null transformation
-     * of each (key, value).
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case the action is not applied)
-     * @param action the action
-     * @param <U> the return type of the transformer
-     * @since 1.8
-     */
-    public <U> void forEach(long parallelismThreshold,
-                            BiFunction<? super K, ? super V, ? extends U> transformer,
-                            Consumer<? super U> action) {
-        if (transformer == null || action == null)
-            throw new NullPointerException();
-        new ForEachTransformedMappingTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             transformer, action).invoke();
-    }
-
-    /**
-     * Returns a non-null result from applying the given search
-     * function on each (key, value), or null if none.  Upon
-     * success, further element processing is suppressed and the
-     * results of any other parallel invocations of the search
-     * function are ignored.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param searchFunction a function returning a non-null
-     * result on success, else null
-     * @param <U> the return type of the search function
-     * @return a non-null result from applying the given search
-     * function on each (key, value), or null if none
-     * @since 1.8
-     */
-    public <U> U search(long parallelismThreshold,
-                        BiFunction<? super K, ? super V, ? extends U> searchFunction) {
-        if (searchFunction == null) throw new NullPointerException();
-        return new SearchMappingsTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             searchFunction, new AtomicReference<U>()).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all (key, value) pairs using the given reducer to
-     * combine values, or null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case it is not combined)
-     * @param reducer a commutative associative combining function
-     * @param <U> the return type of the transformer
-     * @return the result of accumulating the given transformation
-     * of all (key, value) pairs
-     * @since 1.8
-     */
-    public <U> U reduce(long parallelismThreshold,
-                        BiFunction<? super K, ? super V, ? extends U> transformer,
-                        BiFunction<? super U, ? super U, ? extends U> reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceMappingsTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all (key, value) pairs using the given reducer to
-     * combine values, and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all (key, value) pairs
-     * @since 1.8
-     */
-    public double reduceToDouble(long parallelismThreshold,
-                                 ToDoubleBiFunction<? super K, ? super V> transformer,
-                                 double basis,
-                                 DoubleBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceMappingsToDoubleTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all (key, value) pairs using the given reducer to
-     * combine values, and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all (key, value) pairs
-     * @since 1.8
-     */
-    public long reduceToLong(long parallelismThreshold,
-                             ToLongBiFunction<? super K, ? super V> transformer,
-                             long basis,
-                             LongBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceMappingsToLongTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all (key, value) pairs using the given reducer to
-     * combine values, and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all (key, value) pairs
-     * @since 1.8
-     */
-    public int reduceToInt(long parallelismThreshold,
-                           ToIntBiFunction<? super K, ? super V> transformer,
-                           int basis,
-                           IntBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceMappingsToIntTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Performs the given action for each key.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param action the action
-     * @since 1.8
-     */
-    public void forEachKey(long parallelismThreshold,
-                           Consumer<? super K> action) {
-        if (action == null) throw new NullPointerException();
-        new ForEachKeyTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             action).invoke();
-    }
-
-    /**
-     * Performs the given action for each non-null transformation
-     * of each key.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case the action is not applied)
-     * @param action the action
-     * @param <U> the return type of the transformer
-     * @since 1.8
-     */
-    public <U> void forEachKey(long parallelismThreshold,
-                               Function<? super K, ? extends U> transformer,
-                               Consumer<? super U> action) {
-        if (transformer == null || action == null)
-            throw new NullPointerException();
-        new ForEachTransformedKeyTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             transformer, action).invoke();
-    }
-
-    /**
-     * Returns a non-null result from applying the given search
-     * function on each key, or null if none. Upon success,
-     * further element processing is suppressed and the results of
-     * any other parallel invocations of the search function are
-     * ignored.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param searchFunction a function returning a non-null
-     * result on success, else null
-     * @param <U> the return type of the search function
-     * @return a non-null result from applying the given search
-     * function on each key, or null if none
-     * @since 1.8
-     */
-    public <U> U searchKeys(long parallelismThreshold,
-                            Function<? super K, ? extends U> searchFunction) {
-        if (searchFunction == null) throw new NullPointerException();
-        return new SearchKeysTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             searchFunction, new AtomicReference<U>()).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating all keys using the given
-     * reducer to combine values, or null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating all keys using the given
-     * reducer to combine values, or null if none
-     * @since 1.8
-     */
-    public K reduceKeys(long parallelismThreshold,
-                        BiFunction<? super K, ? super K, ? extends K> reducer) {
-        if (reducer == null) throw new NullPointerException();
-        return new ReduceKeysTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all keys using the given reducer to combine values, or
-     * null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case it is not combined)
-     * @param reducer a commutative associative combining function
-     * @param <U> the return type of the transformer
-     * @return the result of accumulating the given transformation
-     * of all keys
-     * @since 1.8
-     */
-    public <U> U reduceKeys(long parallelismThreshold,
-                            Function<? super K, ? extends U> transformer,
-         BiFunction<? super U, ? super U, ? extends U> reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceKeysTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all keys using the given reducer to combine values, and
-     * the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all keys
-     * @since 1.8
-     */
-    public double reduceKeysToDouble(long parallelismThreshold,
-                                     ToDoubleFunction<? super K> transformer,
-                                     double basis,
-                                     DoubleBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceKeysToDoubleTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all keys using the given reducer to combine values, and
-     * the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all keys
-     * @since 1.8
-     */
-    public long reduceKeysToLong(long parallelismThreshold,
-                                 ToLongFunction<? super K> transformer,
-                                 long basis,
-                                 LongBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceKeysToLongTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all keys using the given reducer to combine values, and
-     * the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all keys
-     * @since 1.8
-     */
-    public int reduceKeysToInt(long parallelismThreshold,
-                               ToIntFunction<? super K> transformer,
-                               int basis,
-                               IntBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceKeysToIntTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Performs the given action for each value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param action the action
-     * @since 1.8
-     */
-    public void forEachValue(long parallelismThreshold,
-                             Consumer<? super V> action) {
-        if (action == null)
-            throw new NullPointerException();
-        new ForEachValueTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             action).invoke();
-    }
-
-    /**
-     * Performs the given action for each non-null transformation
-     * of each value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case the action is not applied)
-     * @param action the action
-     * @param <U> the return type of the transformer
-     * @since 1.8
-     */
-    public <U> void forEachValue(long parallelismThreshold,
-                                 Function<? super V, ? extends U> transformer,
-                                 Consumer<? super U> action) {
-        if (transformer == null || action == null)
-            throw new NullPointerException();
-        new ForEachTransformedValueTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             transformer, action).invoke();
-    }
-
-    /**
-     * Returns a non-null result from applying the given search
-     * function on each value, or null if none.  Upon success,
-     * further element processing is suppressed and the results of
-     * any other parallel invocations of the search function are
-     * ignored.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param searchFunction a function returning a non-null
-     * result on success, else null
-     * @param <U> the return type of the search function
-     * @return a non-null result from applying the given search
-     * function on each value, or null if none
-     * @since 1.8
-     */
-    public <U> U searchValues(long parallelismThreshold,
-                              Function<? super V, ? extends U> searchFunction) {
-        if (searchFunction == null) throw new NullPointerException();
-        return new SearchValuesTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             searchFunction, new AtomicReference<U>()).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating all values using the
-     * given reducer to combine values, or null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating all values
-     * @since 1.8
-     */
-    public V reduceValues(long parallelismThreshold,
-                          BiFunction<? super V, ? super V, ? extends V> reducer) {
-        if (reducer == null) throw new NullPointerException();
-        return new ReduceValuesTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all values using the given reducer to combine values, or
-     * null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case it is not combined)
-     * @param reducer a commutative associative combining function
-     * @param <U> the return type of the transformer
-     * @return the result of accumulating the given transformation
-     * of all values
-     * @since 1.8
-     */
-    public <U> U reduceValues(long parallelismThreshold,
-                              Function<? super V, ? extends U> transformer,
-                              BiFunction<? super U, ? super U, ? extends U> reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceValuesTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all values using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all values
-     * @since 1.8
-     */
-    public double reduceValuesToDouble(long parallelismThreshold,
-                                       ToDoubleFunction<? super V> transformer,
-                                       double basis,
-                                       DoubleBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceValuesToDoubleTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all values using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all values
-     * @since 1.8
-     */
-    public long reduceValuesToLong(long parallelismThreshold,
-                                   ToLongFunction<? super V> transformer,
-                                   long basis,
-                                   LongBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceValuesToLongTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all values using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all values
-     * @since 1.8
-     */
-    public int reduceValuesToInt(long parallelismThreshold,
-                                 ToIntFunction<? super V> transformer,
-                                 int basis,
-                                 IntBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceValuesToIntTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Performs the given action for each entry.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param action the action
-     * @since 1.8
-     */
-    public void forEachEntry(long parallelismThreshold,
-                             Consumer<? super Map.Entry<K,V>> action) {
-        if (action == null) throw new NullPointerException();
-        new ForEachEntryTask<K,V>(null, batchFor(parallelismThreshold), 0, 0, table,
-                                  action).invoke();
-    }
-
-    /**
-     * Performs the given action for each non-null transformation
-     * of each entry.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case the action is not applied)
-     * @param action the action
-     * @param <U> the return type of the transformer
-     * @since 1.8
-     */
-    public <U> void forEachEntry(long parallelismThreshold,
-                                 Function<Map.Entry<K,V>, ? extends U> transformer,
-                                 Consumer<? super U> action) {
-        if (transformer == null || action == null)
-            throw new NullPointerException();
-        new ForEachTransformedEntryTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             transformer, action).invoke();
-    }
-
-    /**
-     * Returns a non-null result from applying the given search
-     * function on each entry, or null if none.  Upon success,
-     * further element processing is suppressed and the results of
-     * any other parallel invocations of the search function are
-     * ignored.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param searchFunction a function returning a non-null
-     * result on success, else null
-     * @param <U> the return type of the search function
-     * @return a non-null result from applying the given search
-     * function on each entry, or null if none
-     * @since 1.8
-     */
-    public <U> U searchEntries(long parallelismThreshold,
-                               Function<Map.Entry<K,V>, ? extends U> searchFunction) {
-        if (searchFunction == null) throw new NullPointerException();
-        return new SearchEntriesTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             searchFunction, new AtomicReference<U>()).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating all entries using the
-     * given reducer to combine values, or null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating all entries
-     * @since 1.8
-     */
-    public Map.Entry<K,V> reduceEntries(long parallelismThreshold,
-                                        BiFunction<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
-        if (reducer == null) throw new NullPointerException();
-        return new ReduceEntriesTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all entries using the given reducer to combine values,
-     * or null if none.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element, or null if there is no transformation (in
-     * which case it is not combined)
-     * @param reducer a commutative associative combining function
-     * @param <U> the return type of the transformer
-     * @return the result of accumulating the given transformation
-     * of all entries
-     * @since 1.8
-     */
-    public <U> U reduceEntries(long parallelismThreshold,
-                               Function<Map.Entry<K,V>, ? extends U> transformer,
-                               BiFunction<? super U, ? super U, ? extends U> reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceEntriesTask<K,V,U>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all entries using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all entries
-     * @since 1.8
-     */
-    public double reduceEntriesToDouble(long parallelismThreshold,
-                                        ToDoubleFunction<Map.Entry<K,V>> transformer,
-                                        double basis,
-                                        DoubleBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceEntriesToDoubleTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all entries using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all entries
-     * @since 1.8
-     */
-    public long reduceEntriesToLong(long parallelismThreshold,
-                                    ToLongFunction<Map.Entry<K,V>> transformer,
-                                    long basis,
-                                    LongBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceEntriesToLongTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-    /**
-     * Returns the result of accumulating the given transformation
-     * of all entries using the given reducer to combine values,
-     * and the given basis as an identity value.
-     *
-     * @param parallelismThreshold the (estimated) number of elements
-     * needed for this operation to be executed in parallel
-     * @param transformer a function returning the transformation
-     * for an element
-     * @param basis the identity (initial default value) for the reduction
-     * @param reducer a commutative associative combining function
-     * @return the result of accumulating the given transformation
-     * of all entries
-     * @since 1.8
-     */
-    public int reduceEntriesToInt(long parallelismThreshold,
-                                  ToIntFunction<Map.Entry<K,V>> transformer,
-                                  int basis,
-                                  IntBinaryOperator reducer) {
-        if (transformer == null || reducer == null)
-            throw new NullPointerException();
-        return new MapReduceEntriesToIntTask<K,V>
-            (null, batchFor(parallelismThreshold), 0, 0, table,
-             null, transformer, basis, reducer).invoke();
-    }
-
-
     /* ----------------Views -------------- */
 
     /**
@@ -4422,30 +2798,30 @@
         // implementations below rely on concrete classes supplying these
         // abstract methods
         /**
-         * Returns an iterator over the elements in this collection.
-         *
-         * <p>The returned iterator is
-         * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-         *
-         * @return an iterator over the elements in this collection
+         * Returns a "weakly consistent" iterator that will never
+         * throw {@link ConcurrentModificationException}, and
+         * guarantees to traverse elements as they existed upon
+         * construction of the iterator, and may (but is not
+         * guaranteed to) reflect any modifications subsequent to
+         * construction.
          */
         public abstract Iterator<E> iterator();
         public abstract boolean contains(Object o);
         public abstract boolean remove(Object o);
 
-        private static final String OOME_MSG = "Required array size too large";
+        private static final String oomeMsg = "Required array size too large";
 
         public final Object[] toArray() {
             long sz = map.mappingCount();
             if (sz > MAX_ARRAY_SIZE)
-                throw new OutOfMemoryError(OOME_MSG);
+                throw new OutOfMemoryError(oomeMsg);
             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(OOME_MSG);
+                        throw new OutOfMemoryError(oomeMsg);
                     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
                         n = MAX_ARRAY_SIZE;
                     else
@@ -4461,7 +2837,7 @@
         public final <T> T[] toArray(T[] a) {
             long sz = map.mappingCount();
             if (sz > MAX_ARRAY_SIZE)
-                throw new OutOfMemoryError(OOME_MSG);
+                throw new OutOfMemoryError(oomeMsg);
             int m = (int)sz;
             T[] r = (a.length >= m) ? a :
                 (T[])java.lang.reflect.Array
@@ -4471,7 +2847,7 @@
             for (E e : this) {
                 if (i == n) {
                     if (n >= MAX_ARRAY_SIZE)
-                        throw new OutOfMemoryError(OOME_MSG);
+                        throw new OutOfMemoryError(oomeMsg);
                     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
                         n = MAX_ARRAY_SIZE;
                     else
@@ -4525,7 +2901,6 @@
         }
 
         public final boolean removeAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
             boolean modified = false;
             for (Iterator<E> it = iterator(); it.hasNext();) {
                 if (c.contains(it.next())) {
@@ -4537,7 +2912,6 @@
         }
 
         public final boolean retainAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
             boolean modified = false;
             for (Iterator<E> it = iterator(); it.hasNext();) {
                 if (!c.contains(it.next())) {
@@ -4556,11 +2930,12 @@
      * common value.  This class cannot be directly instantiated.
      * See {@link #keySet() keySet()},
      * {@link #keySet(Object) keySet(V)},
-     * {@link #newKeySet() newKeySet()},
-     * {@link #newKeySet(int) newKeySet(int)}.
      *
      * @since 1.8
+     *
+     * @hide
      */
+    // android-note: removed references to hidden APIs.
     public static class KeySetView<K,V> extends CollectionView<K,V,K>
         implements Set<K>, java.io.Serializable {
         private static final long serialVersionUID = 7249069246763182397L;
@@ -4660,23 +3035,6 @@
                      (containsAll(c) && c.containsAll(this))));
         }
 
-        public Spliterator<K> spliterator() {
-            Node<K,V>[] t;
-            ConcurrentHashMap<K,V> m = map;
-            long n = m.sumCount();
-            int f = (t = m.table) == null ? 0 : t.length;
-            return new KeySpliterator<K,V>(t, f, 0, f, n < 0L ? 0L : n);
-        }
-
-        public void forEach(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V>[] t;
-            if ((t = map.table) != null) {
-                Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-                for (Node<K,V> p; (p = it.advance()) != null; )
-                    action.accept(p.key);
-            }
-        }
     }
 
     /**
@@ -4718,27 +3076,6 @@
             throw new UnsupportedOperationException();
         }
 
-        public boolean removeIf(Predicate<? super V> filter) {
-            return map.removeValueIf(filter);
-        }
-
-        public Spliterator<V> spliterator() {
-            Node<K,V>[] t;
-            ConcurrentHashMap<K,V> m = map;
-            long n = m.sumCount();
-            int f = (t = m.table) == null ? 0 : t.length;
-            return new ValueSpliterator<K,V>(t, f, 0, f, n < 0L ? 0L : n);
-        }
-
-        public void forEach(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V>[] t;
-            if ((t = map.table) != null) {
-                Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-                for (Node<K,V> p; (p = it.advance()) != null; )
-                    action.accept(p.val);
-            }
-        }
     }
 
     /**
@@ -4791,10 +3128,6 @@
             return added;
         }
 
-        public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
-            return map.removeEntryIf(filter);
-        }
-
         public final int hashCode() {
             int h = 0;
             Node<K,V>[] t;
@@ -4814,1532 +3147,181 @@
                      (containsAll(c) && c.containsAll(this))));
         }
 
-        public Spliterator<Map.Entry<K,V>> spliterator() {
-            Node<K,V>[] t;
-            ConcurrentHashMap<K,V> m = map;
-            long n = m.sumCount();
-            int f = (t = m.table) == null ? 0 : t.length;
-            return new EntrySpliterator<K,V>(t, f, 0, f, n < 0L ? 0L : n, m);
-        }
-
-        public void forEach(Consumer<? super Map.Entry<K,V>> action) {
-            if (action == null) throw new NullPointerException();
-            Node<K,V>[] t;
-            if ((t = map.table) != null) {
-                Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
-                for (Node<K,V> p; (p = it.advance()) != null; )
-                    action.accept(new MapEntry<K,V>(p.key, p.val, map));
-            }
-        }
-
     }
 
-    // -------------------------------------------------------
+
+    /* ---------------- Counters -------------- */
+
+    // Adapted from LongAdder and Striped64.
+    // See their internal docs for explanation.
+
+    // A padded cell for distributing counts
+    static final class CounterCell {
+        volatile long p0, p1, p2, p3, p4, p5, p6;
+        volatile long value;
+        volatile long q0, q1, q2, q3, q4, q5, q6;
+        CounterCell(long x) { value = x; }
+    }
 
     /**
-     * Base class for bulk tasks. Repeats some fields and code from
-     * class Traverser, because we need to subclass CountedCompleter.
+     * Holder for the thread-local hash code determining which
+     * CounterCell to use. The code is initialized via the
+     * counterHashCodeGenerator, but may be moved upon collisions.
      */
-    @SuppressWarnings("serial")
-    abstract static class BulkTask<K,V,R> extends CountedCompleter<R> {
-        Node<K,V>[] tab;        // same as Traverser
-        Node<K,V> next;
-        TableStack<K,V> stack, spare;
-        int index;
-        int baseIndex;
-        int baseLimit;
-        final int baseSize;
-        int batch;              // split control
-
-        BulkTask(BulkTask<K,V,?> par, int b, int i, int f, Node<K,V>[] t) {
-            super(par);
-            this.batch = b;
-            this.index = this.baseIndex = i;
-            if ((this.tab = t) == null)
-                this.baseSize = this.baseLimit = 0;
-            else if (par == null)
-                this.baseSize = this.baseLimit = t.length;
-            else {
-                this.baseLimit = f;
-                this.baseSize = par.baseSize;
-            }
-        }
-
-        /**
-         * Same as Traverser version.
-         */
-        final Node<K,V> advance() {
-            Node<K,V> e;
-            if ((e = next) != null)
-                e = e.next;
-            for (;;) {
-                Node<K,V>[] t; int i, n;
-                if (e != null)
-                    return next = e;
-                if (baseIndex >= baseLimit || (t = tab) == null ||
-                    (n = t.length) <= (i = index) || i < 0)
-                    return next = null;
-                if ((e = tabAt(t, i)) != null && e.hash < 0) {
-                    if (e instanceof ForwardingNode) {
-                        tab = ((ForwardingNode<K,V>)e).nextTable;
-                        e = null;
-                        pushState(t, i, n);
-                        continue;
-                    }
-                    else if (e instanceof TreeBin)
-                        e = ((TreeBin<K,V>)e).first;
-                    else
-                        e = null;
-                }
-                if (stack != null)
-                    recoverState(n);
-                else if ((index = i + baseSize) >= n)
-                    index = ++baseIndex;
-            }
-        }
-
-        private void pushState(Node<K,V>[] t, int i, int n) {
-            TableStack<K,V> s = spare;
-            if (s != null)
-                spare = s.next;
-            else
-                s = new TableStack<K,V>();
-            s.tab = t;
-            s.length = n;
-            s.index = i;
-            s.next = stack;
-            stack = s;
-        }
-
-        private void recoverState(int n) {
-            TableStack<K,V> s; int len;
-            while ((s = stack) != null && (index += (len = s.length)) >= n) {
-                n = len;
-                index = s.index;
-                tab = s.tab;
-                s.tab = null;
-                TableStack<K,V> next = s.next;
-                s.next = spare; // save for reuse
-                stack = next;
-                spare = s;
-            }
-            if (s == null && (index += baseSize) >= n)
-                index = ++baseIndex;
-        }
+    static final class CounterHashCode {
+        int code;
     }
 
-    /*
-     * Task classes. Coded in a regular but ugly format/style to
-     * simplify checks that each variant differs in the right way from
-     * others. The null screenings exist because compilers cannot tell
-     * that we've already null-checked task arguments, so we force
-     * simplest hoisted bypass to help avoid convoluted traps.
+    /**
+     * Generates initial value for per-thread CounterHashCodes.
      */
-    @SuppressWarnings("serial")
-    static final class ForEachKeyTask<K,V>
-        extends BulkTask<K,V,Void> {
-        final Consumer<? super K> action;
-        ForEachKeyTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Consumer<? super K> action) {
-            super(p, b, i, f, t);
-            this.action = action;
-        }
-        public final void compute() {
-            final Consumer<? super K> action;
-            if ((action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachKeyTask<K,V>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null;)
-                    action.accept(p.key);
-                propagateCompletion();
+    static final AtomicInteger counterHashCodeGenerator = new AtomicInteger();
+
+    /**
+     * Increment for counterHashCodeGenerator. See class ThreadLocal
+     * for explanation.
+     */
+    static final int SEED_INCREMENT = 0x61c88647;
+
+    /**
+     * Per-thread counter hash codes. Shared across all instances.
+     */
+    static final ThreadLocal<CounterHashCode> threadCounterHashCode =
+        new ThreadLocal<CounterHashCode>();
+
+    final long sumCount() {
+        CounterCell[] as = counterCells; CounterCell a;
+        long sum = baseCount;
+        if (as != null) {
+            for (int i = 0; i < as.length; ++i) {
+                if ((a = as[i]) != null)
+                    sum += a.value;
             }
         }
+        return sum;
     }
 
-    @SuppressWarnings("serial")
-    static final class ForEachValueTask<K,V>
-        extends BulkTask<K,V,Void> {
-        final Consumer<? super V> action;
-        ForEachValueTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Consumer<? super V> action) {
-            super(p, b, i, f, t);
-            this.action = action;
+    // See LongAdder version for explanation
+    private final void fullAddCount(long x, CounterHashCode hc,
+                                    boolean wasUncontended) {
+        int h;
+        if (hc == null) {
+            hc = new CounterHashCode();
+            int s = counterHashCodeGenerator.addAndGet(SEED_INCREMENT);
+            h = hc.code = (s == 0) ? 1 : s; // Avoid zero
+            threadCounterHashCode.set(hc);
         }
-        public final void compute() {
-            final Consumer<? super V> action;
-            if ((action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachValueTask<K,V>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null;)
-                    action.accept(p.val);
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachEntryTask<K,V>
-        extends BulkTask<K,V,Void> {
-        final Consumer<? super Entry<K,V>> action;
-        ForEachEntryTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Consumer<? super Entry<K,V>> action) {
-            super(p, b, i, f, t);
-            this.action = action;
-        }
-        public final void compute() {
-            final Consumer<? super Entry<K,V>> action;
-            if ((action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachEntryTask<K,V>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    action.accept(p);
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachMappingTask<K,V>
-        extends BulkTask<K,V,Void> {
-        final BiConsumer<? super K, ? super V> action;
-        ForEachMappingTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             BiConsumer<? super K,? super V> action) {
-            super(p, b, i, f, t);
-            this.action = action;
-        }
-        public final void compute() {
-            final BiConsumer<? super K, ? super V> action;
-            if ((action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachMappingTask<K,V>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    action.accept(p.key, p.val);
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachTransformedKeyTask<K,V,U>
-        extends BulkTask<K,V,Void> {
-        final Function<? super K, ? extends U> transformer;
-        final Consumer<? super U> action;
-        ForEachTransformedKeyTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<? super K, ? extends U> transformer, Consumer<? super U> action) {
-            super(p, b, i, f, t);
-            this.transformer = transformer; this.action = action;
-        }
-        public final void compute() {
-            final Function<? super K, ? extends U> transformer;
-            final Consumer<? super U> action;
-            if ((transformer = this.transformer) != null &&
-                (action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachTransformedKeyTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         transformer, action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.key)) != null)
-                        action.accept(u);
-                }
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachTransformedValueTask<K,V,U>
-        extends BulkTask<K,V,Void> {
-        final Function<? super V, ? extends U> transformer;
-        final Consumer<? super U> action;
-        ForEachTransformedValueTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<? super V, ? extends U> transformer, Consumer<? super U> action) {
-            super(p, b, i, f, t);
-            this.transformer = transformer; this.action = action;
-        }
-        public final void compute() {
-            final Function<? super V, ? extends U> transformer;
-            final Consumer<? super U> action;
-            if ((transformer = this.transformer) != null &&
-                (action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachTransformedValueTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         transformer, action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.val)) != null)
-                        action.accept(u);
-                }
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachTransformedEntryTask<K,V,U>
-        extends BulkTask<K,V,Void> {
-        final Function<Map.Entry<K,V>, ? extends U> transformer;
-        final Consumer<? super U> action;
-        ForEachTransformedEntryTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<Map.Entry<K,V>, ? extends U> transformer, Consumer<? super U> action) {
-            super(p, b, i, f, t);
-            this.transformer = transformer; this.action = action;
-        }
-        public final void compute() {
-            final Function<Map.Entry<K,V>, ? extends U> transformer;
-            final Consumer<? super U> action;
-            if ((transformer = this.transformer) != null &&
-                (action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachTransformedEntryTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         transformer, action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p)) != null)
-                        action.accept(u);
-                }
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ForEachTransformedMappingTask<K,V,U>
-        extends BulkTask<K,V,Void> {
-        final BiFunction<? super K, ? super V, ? extends U> transformer;
-        final Consumer<? super U> action;
-        ForEachTransformedMappingTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             BiFunction<? super K, ? super V, ? extends U> transformer,
-             Consumer<? super U> action) {
-            super(p, b, i, f, t);
-            this.transformer = transformer; this.action = action;
-        }
-        public final void compute() {
-            final BiFunction<? super K, ? super V, ? extends U> transformer;
-            final Consumer<? super U> action;
-            if ((transformer = this.transformer) != null &&
-                (action = this.action) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    new ForEachTransformedMappingTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         transformer, action).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.key, p.val)) != null)
-                        action.accept(u);
-                }
-                propagateCompletion();
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class SearchKeysTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<? super K, ? extends U> searchFunction;
-        final AtomicReference<U> result;
-        SearchKeysTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<? super K, ? extends U> searchFunction,
-             AtomicReference<U> result) {
-            super(p, b, i, f, t);
-            this.searchFunction = searchFunction; this.result = result;
-        }
-        public final U getRawResult() { return result.get(); }
-        public final void compute() {
-            final Function<? super K, ? extends U> searchFunction;
-            final AtomicReference<U> result;
-            if ((searchFunction = this.searchFunction) != null &&
-                (result = this.result) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    if (result.get() != null)
-                        return;
-                    addToPendingCount(1);
-                    new SearchKeysTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         searchFunction, result).fork();
-                }
-                while (result.get() == null) {
-                    U u;
-                    Node<K,V> p;
-                    if ((p = advance()) == null) {
-                        propagateCompletion();
-                        break;
+        else
+            h = hc.code;
+        boolean collide = false;                // True if last slot nonempty
+        for (;;) {
+            CounterCell[] as; CounterCell a; int n; long v;
+            if ((as = counterCells) != null && (n = as.length) > 0) {
+                if ((a = as[(n - 1) & h]) == null) {
+                    if (cellsBusy == 0) {            // Try to attach new Cell
+                        CounterCell r = new CounterCell(x); // Optimistic create
+                        if (cellsBusy == 0 &&
+                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+                            boolean created = false;
+                            try {               // Recheck under lock
+                                CounterCell[] rs; int m, j;
+                                if ((rs = counterCells) != null &&
+                                    (m = rs.length) > 0 &&
+                                    rs[j = (m - 1) & h] == null) {
+                                    rs[j] = r;
+                                    created = true;
+                                }
+                            } finally {
+                                cellsBusy = 0;
+                            }
+                            if (created)
+                                break;
+                            continue;           // Slot is now non-empty
+                        }
                     }
-                    if ((u = searchFunction.apply(p.key)) != null) {
-                        if (result.compareAndSet(null, u))
-                            quietlyCompleteRoot();
-                        break;
-                    }
+                    collide = false;
                 }
+                else if (!wasUncontended)       // CAS already known to fail
+                    wasUncontended = true;      // Continue after rehash
+                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
+                    break;
+                else if (counterCells != as || n >= NCPU)
+                    collide = false;            // At max size or stale
+                else if (!collide)
+                    collide = true;
+                else if (cellsBusy == 0 &&
+                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+                    try {
+                        if (counterCells == as) {// Expand table unless stale
+                            CounterCell[] rs = new CounterCell[n << 1];
+                            for (int i = 0; i < n; ++i)
+                                rs[i] = as[i];
+                            counterCells = rs;
+                        }
+                    } finally {
+                        cellsBusy = 0;
+                    }
+                    collide = false;
+                    continue;                   // Retry with expanded table
+                }
+                h ^= h << 13;                   // Rehash
+                h ^= h >>> 17;
+                h ^= h << 5;
             }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class SearchValuesTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<? super V, ? extends U> searchFunction;
-        final AtomicReference<U> result;
-        SearchValuesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<? super V, ? extends U> searchFunction,
-             AtomicReference<U> result) {
-            super(p, b, i, f, t);
-            this.searchFunction = searchFunction; this.result = result;
-        }
-        public final U getRawResult() { return result.get(); }
-        public final void compute() {
-            final Function<? super V, ? extends U> searchFunction;
-            final AtomicReference<U> result;
-            if ((searchFunction = this.searchFunction) != null &&
-                (result = this.result) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    if (result.get() != null)
-                        return;
-                    addToPendingCount(1);
-                    new SearchValuesTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         searchFunction, result).fork();
-                }
-                while (result.get() == null) {
-                    U u;
-                    Node<K,V> p;
-                    if ((p = advance()) == null) {
-                        propagateCompletion();
-                        break;
+            else if (cellsBusy == 0 && counterCells == as &&
+                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+                boolean init = false;
+                try {                           // Initialize table
+                    if (counterCells == as) {
+                        CounterCell[] rs = new CounterCell[2];
+                        rs[h & 1] = new CounterCell(x);
+                        counterCells = rs;
+                        init = true;
                     }
-                    if ((u = searchFunction.apply(p.val)) != null) {
-                        if (result.compareAndSet(null, u))
-                            quietlyCompleteRoot();
-                        break;
-                    }
+                } finally {
+                    cellsBusy = 0;
                 }
+                if (init)
+                    break;
             }
+            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
+                break;                          // Fall back on using base
         }
-    }
-
-    @SuppressWarnings("serial")
-    static final class SearchEntriesTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<Entry<K,V>, ? extends U> searchFunction;
-        final AtomicReference<U> result;
-        SearchEntriesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             Function<Entry<K,V>, ? extends U> searchFunction,
-             AtomicReference<U> result) {
-            super(p, b, i, f, t);
-            this.searchFunction = searchFunction; this.result = result;
-        }
-        public final U getRawResult() { return result.get(); }
-        public final void compute() {
-            final Function<Entry<K,V>, ? extends U> searchFunction;
-            final AtomicReference<U> result;
-            if ((searchFunction = this.searchFunction) != null &&
-                (result = this.result) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    if (result.get() != null)
-                        return;
-                    addToPendingCount(1);
-                    new SearchEntriesTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         searchFunction, result).fork();
-                }
-                while (result.get() == null) {
-                    U u;
-                    Node<K,V> p;
-                    if ((p = advance()) == null) {
-                        propagateCompletion();
-                        break;
-                    }
-                    if ((u = searchFunction.apply(p)) != null) {
-                        if (result.compareAndSet(null, u))
-                            quietlyCompleteRoot();
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class SearchMappingsTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final BiFunction<? super K, ? super V, ? extends U> searchFunction;
-        final AtomicReference<U> result;
-        SearchMappingsTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             BiFunction<? super K, ? super V, ? extends U> searchFunction,
-             AtomicReference<U> result) {
-            super(p, b, i, f, t);
-            this.searchFunction = searchFunction; this.result = result;
-        }
-        public final U getRawResult() { return result.get(); }
-        public final void compute() {
-            final BiFunction<? super K, ? super V, ? extends U> searchFunction;
-            final AtomicReference<U> result;
-            if ((searchFunction = this.searchFunction) != null &&
-                (result = this.result) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    if (result.get() != null)
-                        return;
-                    addToPendingCount(1);
-                    new SearchMappingsTask<K,V,U>
-                        (this, batch >>>= 1, baseLimit = h, f, tab,
-                         searchFunction, result).fork();
-                }
-                while (result.get() == null) {
-                    U u;
-                    Node<K,V> p;
-                    if ((p = advance()) == null) {
-                        propagateCompletion();
-                        break;
-                    }
-                    if ((u = searchFunction.apply(p.key, p.val)) != null) {
-                        if (result.compareAndSet(null, u))
-                            quietlyCompleteRoot();
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ReduceKeysTask<K,V>
-        extends BulkTask<K,V,K> {
-        final BiFunction<? super K, ? super K, ? extends K> reducer;
-        K result;
-        ReduceKeysTask<K,V> rights, nextRight;
-        ReduceKeysTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             ReduceKeysTask<K,V> nextRight,
-             BiFunction<? super K, ? super K, ? extends K> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.reducer = reducer;
-        }
-        public final K getRawResult() { return result; }
-        public final void compute() {
-            final BiFunction<? super K, ? super K, ? extends K> reducer;
-            if ((reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new ReduceKeysTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, reducer)).fork();
-                }
-                K r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    K u = p.key;
-                    r = (r == null) ? u : u == null ? r : reducer.apply(r, u);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    ReduceKeysTask<K,V>
-                        t = (ReduceKeysTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        K tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ReduceValuesTask<K,V>
-        extends BulkTask<K,V,V> {
-        final BiFunction<? super V, ? super V, ? extends V> reducer;
-        V result;
-        ReduceValuesTask<K,V> rights, nextRight;
-        ReduceValuesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             ReduceValuesTask<K,V> nextRight,
-             BiFunction<? super V, ? super V, ? extends V> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.reducer = reducer;
-        }
-        public final V getRawResult() { return result; }
-        public final void compute() {
-            final BiFunction<? super V, ? super V, ? extends V> reducer;
-            if ((reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new ReduceValuesTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, reducer)).fork();
-                }
-                V r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    V v = p.val;
-                    r = (r == null) ? v : reducer.apply(r, v);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    ReduceValuesTask<K,V>
-                        t = (ReduceValuesTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        V tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class ReduceEntriesTask<K,V>
-        extends BulkTask<K,V,Map.Entry<K,V>> {
-        final BiFunction<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer;
-        Map.Entry<K,V> result;
-        ReduceEntriesTask<K,V> rights, nextRight;
-        ReduceEntriesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             ReduceEntriesTask<K,V> nextRight,
-             BiFunction<Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.reducer = reducer;
-        }
-        public final Map.Entry<K,V> getRawResult() { return result; }
-        public final void compute() {
-            final BiFunction<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer;
-            if ((reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new ReduceEntriesTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, reducer)).fork();
-                }
-                Map.Entry<K,V> r = null;
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = (r == null) ? p : reducer.apply(r, p);
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    ReduceEntriesTask<K,V>
-                        t = (ReduceEntriesTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        Map.Entry<K,V> tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceKeysTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<? super K, ? extends U> transformer;
-        final BiFunction<? super U, ? super U, ? extends U> reducer;
-        U result;
-        MapReduceKeysTask<K,V,U> rights, nextRight;
-        MapReduceKeysTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceKeysTask<K,V,U> nextRight,
-             Function<? super K, ? extends U> transformer,
-             BiFunction<? super U, ? super U, ? extends U> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.reducer = reducer;
-        }
-        public final U getRawResult() { return result; }
-        public final void compute() {
-            final Function<? super K, ? extends U> transformer;
-            final BiFunction<? super U, ? super U, ? extends U> reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceKeysTask<K,V,U>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, reducer)).fork();
-                }
-                U r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.key)) != null)
-                        r = (r == null) ? u : reducer.apply(r, u);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceKeysTask<K,V,U>
-                        t = (MapReduceKeysTask<K,V,U>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        U tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceValuesTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<? super V, ? extends U> transformer;
-        final BiFunction<? super U, ? super U, ? extends U> reducer;
-        U result;
-        MapReduceValuesTask<K,V,U> rights, nextRight;
-        MapReduceValuesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceValuesTask<K,V,U> nextRight,
-             Function<? super V, ? extends U> transformer,
-             BiFunction<? super U, ? super U, ? extends U> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.reducer = reducer;
-        }
-        public final U getRawResult() { return result; }
-        public final void compute() {
-            final Function<? super V, ? extends U> transformer;
-            final BiFunction<? super U, ? super U, ? extends U> reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceValuesTask<K,V,U>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, reducer)).fork();
-                }
-                U r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.val)) != null)
-                        r = (r == null) ? u : reducer.apply(r, u);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceValuesTask<K,V,U>
-                        t = (MapReduceValuesTask<K,V,U>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        U tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceEntriesTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final Function<Map.Entry<K,V>, ? extends U> transformer;
-        final BiFunction<? super U, ? super U, ? extends U> reducer;
-        U result;
-        MapReduceEntriesTask<K,V,U> rights, nextRight;
-        MapReduceEntriesTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceEntriesTask<K,V,U> nextRight,
-             Function<Map.Entry<K,V>, ? extends U> transformer,
-             BiFunction<? super U, ? super U, ? extends U> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.reducer = reducer;
-        }
-        public final U getRawResult() { return result; }
-        public final void compute() {
-            final Function<Map.Entry<K,V>, ? extends U> transformer;
-            final BiFunction<? super U, ? super U, ? extends U> reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceEntriesTask<K,V,U>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, reducer)).fork();
-                }
-                U r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p)) != null)
-                        r = (r == null) ? u : reducer.apply(r, u);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceEntriesTask<K,V,U>
-                        t = (MapReduceEntriesTask<K,V,U>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        U tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceMappingsTask<K,V,U>
-        extends BulkTask<K,V,U> {
-        final BiFunction<? super K, ? super V, ? extends U> transformer;
-        final BiFunction<? super U, ? super U, ? extends U> reducer;
-        U result;
-        MapReduceMappingsTask<K,V,U> rights, nextRight;
-        MapReduceMappingsTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceMappingsTask<K,V,U> nextRight,
-             BiFunction<? super K, ? super V, ? extends U> transformer,
-             BiFunction<? super U, ? super U, ? extends U> reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.reducer = reducer;
-        }
-        public final U getRawResult() { return result; }
-        public final void compute() {
-            final BiFunction<? super K, ? super V, ? extends U> transformer;
-            final BiFunction<? super U, ? super U, ? extends U> reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceMappingsTask<K,V,U>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, reducer)).fork();
-                }
-                U r = null;
-                for (Node<K,V> p; (p = advance()) != null; ) {
-                    U u;
-                    if ((u = transformer.apply(p.key, p.val)) != null)
-                        r = (r == null) ? u : reducer.apply(r, u);
-                }
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceMappingsTask<K,V,U>
-                        t = (MapReduceMappingsTask<K,V,U>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        U tr, sr;
-                        if ((sr = s.result) != null)
-                            t.result = (((tr = t.result) == null) ? sr :
-                                        reducer.apply(tr, sr));
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceKeysToDoubleTask<K,V>
-        extends BulkTask<K,V,Double> {
-        final ToDoubleFunction<? super K> transformer;
-        final DoubleBinaryOperator reducer;
-        final double basis;
-        double result;
-        MapReduceKeysToDoubleTask<K,V> rights, nextRight;
-        MapReduceKeysToDoubleTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceKeysToDoubleTask<K,V> nextRight,
-             ToDoubleFunction<? super K> transformer,
-             double basis,
-             DoubleBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Double getRawResult() { return result; }
-        public final void compute() {
-            final ToDoubleFunction<? super K> transformer;
-            final DoubleBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                double r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceKeysToDoubleTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(p.key));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceKeysToDoubleTask<K,V>
-                        t = (MapReduceKeysToDoubleTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsDouble(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceValuesToDoubleTask<K,V>
-        extends BulkTask<K,V,Double> {
-        final ToDoubleFunction<? super V> transformer;
-        final DoubleBinaryOperator reducer;
-        final double basis;
-        double result;
-        MapReduceValuesToDoubleTask<K,V> rights, nextRight;
-        MapReduceValuesToDoubleTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceValuesToDoubleTask<K,V> nextRight,
-             ToDoubleFunction<? super V> transformer,
-             double basis,
-             DoubleBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Double getRawResult() { return result; }
-        public final void compute() {
-            final ToDoubleFunction<? super V> transformer;
-            final DoubleBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                double r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceValuesToDoubleTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceValuesToDoubleTask<K,V>
-                        t = (MapReduceValuesToDoubleTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsDouble(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceEntriesToDoubleTask<K,V>
-        extends BulkTask<K,V,Double> {
-        final ToDoubleFunction<Map.Entry<K,V>> transformer;
-        final DoubleBinaryOperator reducer;
-        final double basis;
-        double result;
-        MapReduceEntriesToDoubleTask<K,V> rights, nextRight;
-        MapReduceEntriesToDoubleTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceEntriesToDoubleTask<K,V> nextRight,
-             ToDoubleFunction<Map.Entry<K,V>> transformer,
-             double basis,
-             DoubleBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Double getRawResult() { return result; }
-        public final void compute() {
-            final ToDoubleFunction<Map.Entry<K,V>> transformer;
-            final DoubleBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                double r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceEntriesToDoubleTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(p));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceEntriesToDoubleTask<K,V>
-                        t = (MapReduceEntriesToDoubleTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsDouble(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceMappingsToDoubleTask<K,V>
-        extends BulkTask<K,V,Double> {
-        final ToDoubleBiFunction<? super K, ? super V> transformer;
-        final DoubleBinaryOperator reducer;
-        final double basis;
-        double result;
-        MapReduceMappingsToDoubleTask<K,V> rights, nextRight;
-        MapReduceMappingsToDoubleTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceMappingsToDoubleTask<K,V> nextRight,
-             ToDoubleBiFunction<? super K, ? super V> transformer,
-             double basis,
-             DoubleBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Double getRawResult() { return result; }
-        public final void compute() {
-            final ToDoubleBiFunction<? super K, ? super V> transformer;
-            final DoubleBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                double r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceMappingsToDoubleTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(p.key, p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceMappingsToDoubleTask<K,V>
-                        t = (MapReduceMappingsToDoubleTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsDouble(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceKeysToLongTask<K,V>
-        extends BulkTask<K,V,Long> {
-        final ToLongFunction<? super K> transformer;
-        final LongBinaryOperator reducer;
-        final long basis;
-        long result;
-        MapReduceKeysToLongTask<K,V> rights, nextRight;
-        MapReduceKeysToLongTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceKeysToLongTask<K,V> nextRight,
-             ToLongFunction<? super K> transformer,
-             long basis,
-             LongBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Long getRawResult() { return result; }
-        public final void compute() {
-            final ToLongFunction<? super K> transformer;
-            final LongBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                long r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceKeysToLongTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsLong(r, transformer.applyAsLong(p.key));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceKeysToLongTask<K,V>
-                        t = (MapReduceKeysToLongTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsLong(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceValuesToLongTask<K,V>
-        extends BulkTask<K,V,Long> {
-        final ToLongFunction<? super V> transformer;
-        final LongBinaryOperator reducer;
-        final long basis;
-        long result;
-        MapReduceValuesToLongTask<K,V> rights, nextRight;
-        MapReduceValuesToLongTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceValuesToLongTask<K,V> nextRight,
-             ToLongFunction<? super V> transformer,
-             long basis,
-             LongBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Long getRawResult() { return result; }
-        public final void compute() {
-            final ToLongFunction<? super V> transformer;
-            final LongBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                long r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceValuesToLongTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsLong(r, transformer.applyAsLong(p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceValuesToLongTask<K,V>
-                        t = (MapReduceValuesToLongTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsLong(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceEntriesToLongTask<K,V>
-        extends BulkTask<K,V,Long> {
-        final ToLongFunction<Map.Entry<K,V>> transformer;
-        final LongBinaryOperator reducer;
-        final long basis;
-        long result;
-        MapReduceEntriesToLongTask<K,V> rights, nextRight;
-        MapReduceEntriesToLongTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceEntriesToLongTask<K,V> nextRight,
-             ToLongFunction<Map.Entry<K,V>> transformer,
-             long basis,
-             LongBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Long getRawResult() { return result; }
-        public final void compute() {
-            final ToLongFunction<Map.Entry<K,V>> transformer;
-            final LongBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                long r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceEntriesToLongTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsLong(r, transformer.applyAsLong(p));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceEntriesToLongTask<K,V>
-                        t = (MapReduceEntriesToLongTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsLong(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceMappingsToLongTask<K,V>
-        extends BulkTask<K,V,Long> {
-        final ToLongBiFunction<? super K, ? super V> transformer;
-        final LongBinaryOperator reducer;
-        final long basis;
-        long result;
-        MapReduceMappingsToLongTask<K,V> rights, nextRight;
-        MapReduceMappingsToLongTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceMappingsToLongTask<K,V> nextRight,
-             ToLongBiFunction<? super K, ? super V> transformer,
-             long basis,
-             LongBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Long getRawResult() { return result; }
-        public final void compute() {
-            final ToLongBiFunction<? super K, ? super V> transformer;
-            final LongBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                long r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceMappingsToLongTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsLong(r, transformer.applyAsLong(p.key, p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceMappingsToLongTask<K,V>
-                        t = (MapReduceMappingsToLongTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsLong(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceKeysToIntTask<K,V>
-        extends BulkTask<K,V,Integer> {
-        final ToIntFunction<? super K> transformer;
-        final IntBinaryOperator reducer;
-        final int basis;
-        int result;
-        MapReduceKeysToIntTask<K,V> rights, nextRight;
-        MapReduceKeysToIntTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceKeysToIntTask<K,V> nextRight,
-             ToIntFunction<? super K> transformer,
-             int basis,
-             IntBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Integer getRawResult() { return result; }
-        public final void compute() {
-            final ToIntFunction<? super K> transformer;
-            final IntBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                int r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceKeysToIntTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsInt(r, transformer.applyAsInt(p.key));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceKeysToIntTask<K,V>
-                        t = (MapReduceKeysToIntTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsInt(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceValuesToIntTask<K,V>
-        extends BulkTask<K,V,Integer> {
-        final ToIntFunction<? super V> transformer;
-        final IntBinaryOperator reducer;
-        final int basis;
-        int result;
-        MapReduceValuesToIntTask<K,V> rights, nextRight;
-        MapReduceValuesToIntTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceValuesToIntTask<K,V> nextRight,
-             ToIntFunction<? super V> transformer,
-             int basis,
-             IntBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Integer getRawResult() { return result; }
-        public final void compute() {
-            final ToIntFunction<? super V> transformer;
-            final IntBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                int r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceValuesToIntTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsInt(r, transformer.applyAsInt(p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceValuesToIntTask<K,V>
-                        t = (MapReduceValuesToIntTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsInt(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceEntriesToIntTask<K,V>
-        extends BulkTask<K,V,Integer> {
-        final ToIntFunction<Map.Entry<K,V>> transformer;
-        final IntBinaryOperator reducer;
-        final int basis;
-        int result;
-        MapReduceEntriesToIntTask<K,V> rights, nextRight;
-        MapReduceEntriesToIntTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceEntriesToIntTask<K,V> nextRight,
-             ToIntFunction<Map.Entry<K,V>> transformer,
-             int basis,
-             IntBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Integer getRawResult() { return result; }
-        public final void compute() {
-            final ToIntFunction<Map.Entry<K,V>> transformer;
-            final IntBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                int r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceEntriesToIntTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsInt(r, transformer.applyAsInt(p));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceEntriesToIntTask<K,V>
-                        t = (MapReduceEntriesToIntTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsInt(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("serial")
-    static final class MapReduceMappingsToIntTask<K,V>
-        extends BulkTask<K,V,Integer> {
-        final ToIntBiFunction<? super K, ? super V> transformer;
-        final IntBinaryOperator reducer;
-        final int basis;
-        int result;
-        MapReduceMappingsToIntTask<K,V> rights, nextRight;
-        MapReduceMappingsToIntTask
-            (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
-             MapReduceMappingsToIntTask<K,V> nextRight,
-             ToIntBiFunction<? super K, ? super V> transformer,
-             int basis,
-             IntBinaryOperator reducer) {
-            super(p, b, i, f, t); this.nextRight = nextRight;
-            this.transformer = transformer;
-            this.basis = basis; this.reducer = reducer;
-        }
-        public final Integer getRawResult() { return result; }
-        public final void compute() {
-            final ToIntBiFunction<? super K, ? super V> transformer;
-            final IntBinaryOperator reducer;
-            if ((transformer = this.transformer) != null &&
-                (reducer = this.reducer) != null) {
-                int r = this.basis;
-                for (int i = baseIndex, f, h; batch > 0 &&
-                         (h = ((f = baseLimit) + i) >>> 1) > i;) {
-                    addToPendingCount(1);
-                    (rights = new MapReduceMappingsToIntTask<K,V>
-                     (this, batch >>>= 1, baseLimit = h, f, tab,
-                      rights, transformer, r, reducer)).fork();
-                }
-                for (Node<K,V> p; (p = advance()) != null; )
-                    r = reducer.applyAsInt(r, transformer.applyAsInt(p.key, p.val));
-                result = r;
-                CountedCompleter<?> c;
-                for (c = firstComplete(); c != null; c = c.nextComplete()) {
-                    @SuppressWarnings("unchecked")
-                    MapReduceMappingsToIntTask<K,V>
-                        t = (MapReduceMappingsToIntTask<K,V>)c,
-                        s = t.rights;
-                    while (s != null) {
-                        t.result = reducer.applyAsInt(t.result, s.result);
-                        s = t.rights = s.nextRight;
-                    }
-                }
-            }
-        }
+        hc.code = h;                            // Record index for next time
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final sun.misc.Unsafe U;
     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 int ABASE;
+    private static final long ABASE;
     private static final int ASHIFT;
 
     static {
         try {
+            U = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ConcurrentHashMap.class;
             SIZECTL = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
+                (k.getDeclaredField("sizeCtl"));
             TRANSFERINDEX = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
+                (k.getDeclaredField("transferIndex"));
             BASECOUNT = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
+                (k.getDeclaredField("baseCount"));
             CELLSBUSY = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
-
+                (k.getDeclaredField("cellsBusy"));
+            Class<?> ck = CounterCell.class;
             CELLVALUE = U.objectFieldOffset
-                (CounterCell.class.getDeclaredField("value"));
-
-            ABASE = U.arrayBaseOffset(Node[].class);
-            int scale = U.arrayIndexScale(Node[].class);
+                (ck.getDeclaredField("value"));
+            Class<?> ak = Node[].class;
+            ABASE = U.arrayBaseOffset(ak);
+            int scale = U.arrayIndexScale(ak);
             if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
+                throw new Error("data type scale not a power of two");
             ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
+        } catch (Exception e) {
             throw new Error(e);
         }
 
@@ -6347,4 +3329,5 @@
         // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
         Class<?> ensureLoaded = LockSupport.class;
     }
+
 }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
index 7084d14..b38d6a5 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -7,16 +7,12 @@
 package java.util.concurrent;
 
 import java.util.AbstractCollection;
-import java.util.Arrays;
+import java.util.ArrayList;
 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;
-import java.util.function.Consumer;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -31,8 +27,12 @@
  * Like most other concurrent collection implementations, this class
  * does not permit the use of {@code null} elements.
  *
- * <p>Iterators and spliterators are
- * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+ * <p>Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the deque at some point at or since the
+ * creation of the iterator.  They do <em>not</em> throw {@link
+ * java.util.ConcurrentModificationException
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations.
  *
  * <p>Beware that, unlike in most collections, the {@code size} method
  * is <em>NOT</em> a constant-time operation. Because of the
@@ -59,7 +59,7 @@
  * @since 1.7
  * @author Doug Lea
  * @author Martin Buchholz
- * @param <E> the type of elements held in this deque
+ * @param <E> the type of elements held in this collection
  */
 public class ConcurrentLinkedDeque<E>
     extends AbstractCollection<E>
@@ -272,45 +272,47 @@
          * only be seen after publication via casNext or casPrev.
          */
         Node(E item) {
-            U.putObject(this, ITEM, item);
+            UNSAFE.putObject(this, itemOffset, item);
         }
 
         boolean casItem(E cmp, E val) {
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
         }
 
         void lazySetNext(Node<E> val) {
-            U.putOrderedObject(this, NEXT, val);
+            UNSAFE.putOrderedObject(this, nextOffset, val);
         }
 
         boolean casNext(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
         }
 
         void lazySetPrev(Node<E> val) {
-            U.putOrderedObject(this, PREV, val);
+            UNSAFE.putOrderedObject(this, prevOffset, val);
         }
 
         boolean casPrev(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, PREV, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
         }
 
         // Unsafe mechanics
 
-        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;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long prevOffset;
+        private static final long itemOffset;
+        private static final long nextOffset;
 
         static {
             try {
-                PREV = U.objectFieldOffset
-                    (Node.class.getDeclaredField("prev"));
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-            } catch (ReflectiveOperationException e) {
+                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) {
                 throw new Error(e);
             }
         }
@@ -320,7 +322,8 @@
      * Links e as first element.
      */
     private void linkFirst(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
 
         restartFromHead:
         for (;;)
@@ -352,7 +355,8 @@
      * Links e as last element.
      */
     private void linkLast(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
 
         restartFromTail:
         for (;;)
@@ -757,6 +761,16 @@
     // 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.
      *
@@ -770,6 +784,22 @@
     }
 
     /**
+     * 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() {
@@ -789,7 +819,8 @@
         // Copy c into a private chain of Nodes
         Node<E> h = null, t = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
             if (h == null)
                 h = t = newNode;
             else {
@@ -964,42 +995,23 @@
     }
 
     public E poll()           { return pollFirst(); }
-    public E peek()           { return peekFirst(); }
-
-    /**
-     * @throws NoSuchElementException {@inheritDoc}
-     */
     public E remove()         { return removeFirst(); }
-
-    /**
-     * @throws NoSuchElementException {@inheritDoc}
-     */
+    public E peek()           { return peekFirst(); }
+    public E element()        { return getFirst(); }
+    public void push(E e)     { addFirst(e); }
     public E pop()            { return removeFirst(); }
 
     /**
-     * @throws NoSuchElementException {@inheritDoc}
-     */
-    public E element()        { return getFirst(); }
-
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
-    public void push(E e)     { addFirst(e); }
-
-    /**
-     * Removes the first occurrence of the specified element from this deque.
+     * Removes the first element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in 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) {
-        Objects.requireNonNull(o);
+        checkNotNull(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)) {
@@ -1011,19 +1023,16 @@
     }
 
     /**
-     * Removes the last occurrence of the specified element from this deque.
+     * Removes the last element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in 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) {
-        Objects.requireNonNull(o);
+        checkNotNull(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)) {
@@ -1035,20 +1044,18 @@
     }
 
     /**
-     * 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)}.
+     * Returns {@code true} 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) {
-            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) return false;
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null && o.equals(item))
+                return true;
         }
         return false;
     }
@@ -1079,28 +1086,19 @@
      * @return the number of elements in this deque
      */
     public int size() {
-        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;
-        }
+        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;
     }
 
     /**
-     * Removes the first occurrence of the specified element from this deque.
+     * Removes the first element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in 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
@@ -1130,7 +1128,8 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
@@ -1181,62 +1180,6 @@
             ;
     }
 
-    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).
@@ -1251,7 +1194,7 @@
      * @return an array containing all of the elements in this deque
      */
     public Object[] toArray() {
-        return toArrayInternal(null);
+        return toArrayList().toArray();
     }
 
     /**
@@ -1277,7 +1220,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()}.
@@ -1291,18 +1234,20 @@
      *         this deque
      * @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);
+        return toArrayList().toArray(a);
     }
 
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this deque in proper sequence
      */
@@ -1315,8 +1260,12 @@
      * sequential order.  The elements will be returned in order from
      * last (tail) to first (head).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this deque in reverse order
      */
@@ -1361,7 +1310,7 @@
             Node<E> p = (nextNode == null) ? startNode() : nextNode(nextNode);
             for (;; p = nextNode(p)) {
                 if (p == null) {
-                    // might be at active end or TERMINATOR node; both are OK
+                    // p might be active end or TERMINATOR node; both are OK
                     nextNode = null;
                     nextItem = null;
                     break;
@@ -1407,121 +1356,9 @@
         Node<E> nextNode(Node<E> p) { return pred(p); }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class CLDSpliterator<E> implements Spliterator<E> {
-        static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final ConcurrentLinkedDeque<E> queue;
-        Node<E> current;    // current node; null until initialized
-        int batch;          // batch size for splits
-        boolean exhausted;  // true when no more nodes
-        CLDSpliterator(ConcurrentLinkedDeque<E> queue) {
-            this.queue = queue;
-        }
-
-        public Spliterator<E> trySplit() {
-            Node<E> p;
-            final ConcurrentLinkedDeque<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.first()) != null)) {
-                if (p.item == null && p == (p = p.next))
-                    current = p = q.first();
-                if (p != null && p.next != null) {
-                    Object[] a = new Object[n];
-                    int i = 0;
-                    do {
-                        if ((a[i] = p.item) != null)
-                            ++i;
-                        if (p == (p = p.next))
-                            p = q.first();
-                    } while (p != null && i < n);
-                    if ((current = p) == null)
-                        exhausted = true;
-                    if (i > 0) {
-                        batch = i;
-                        return Spliterators.spliterator
-                            (a, 0, i, (Spliterator.ORDERED |
-                                       Spliterator.NONNULL |
-                                       Spliterator.CONCURRENT));
-                    }
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super E> action) {
-            Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedDeque<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
-                exhausted = true;
-                do {
-                    E e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedDeque<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
-                E e;
-                do {
-                    e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                } while (e == null && p != null);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (e != null) {
-                    action.accept(e);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public long estimateSize() { return Long.MAX_VALUE; }
-
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
-        }
-    }
-
-    /**
-     * Returns a {@link Spliterator} over the elements in this deque.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this deque
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new CLDSpliterator<E>(this);
-    }
-
     /**
      * 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 All of the elements (each an {@code E}) in
      * the proper order, followed by a null
      */
@@ -1544,10 +1381,6 @@
 
     /**
      * 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 {
@@ -1555,7 +1388,8 @@
 
         // Read in elements until trailing null sentinel found
         Node<E> h = null, t = null;
-        for (Object item; (item = s.readObject()) != null; ) {
+        Object item;
+        while ((item = s.readObject()) != null) {
             @SuppressWarnings("unchecked")
             Node<E> newNode = new Node<E>((E) item);
             if (h == null)
@@ -1570,29 +1404,31 @@
     }
 
     private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
 
     private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
     }
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long headOffset;
+    private static final long tailOffset;
     static {
         PREV_TERMINATOR = new Node<Object>();
         PREV_TERMINATOR.next = PREV_TERMINATOR;
         NEXT_TERMINATOR = new Node<Object>();
         NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("tail"));
-        } catch (ReflectiveOperationException e) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ConcurrentLinkedDeque.class;
+            headOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("head"));
+            tailOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("tail"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index e96b1b8..9010cbe 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -7,15 +7,11 @@
 package java.util.concurrent;
 
 import java.util.AbstractQueue;
-import java.util.Arrays;
+import java.util.ArrayList;
 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;
-import java.util.function.Consumer;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -72,7 +68,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
         implements Queue<E>, java.io.Serializable {
@@ -152,28 +148,45 @@
     private static class Node<E> {
         volatile E item;
         volatile Node<E> next;
-    }
 
-    /**
-     * 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;
-    }
+        /**
+         * 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);
+        }
 
-    static <E> boolean casItem(Node<E> node, E cmp, E val) {
-        return U.compareAndSwapObject(node, ITEM, cmp, val);
-    }
+        boolean casItem(E cmp, E val) {
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+        }
 
-    static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putOrderedObject(node, NEXT, val);
-    }
+        void lazySetNext(Node<E> val) {
+            UNSAFE.putOrderedObject(this, nextOffset, val);
+        }
 
-    static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(node, NEXT, cmp, 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;
+
+        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);
+            }
+        }
     }
 
     /**
@@ -188,7 +201,7 @@
      * - it is permitted for tail to lag behind head, that is, for tail
      *   to not be reachable from head!
      */
-    transient volatile Node<E> head;
+    private transient volatile Node<E> head;
 
     /**
      * A node from which the last node on list (that is, the unique
@@ -208,7 +221,7 @@
      * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
     public ConcurrentLinkedQueue() {
-        head = tail = newNode(null);
+        head = tail = new Node<E>(null);
     }
 
     /**
@@ -223,16 +236,17 @@
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
         Node<E> h = null, t = null;
         for (E e : c) {
-            Node<E> newNode = newNode(Objects.requireNonNull(e));
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                t.lazySetNext(newNode);
                 t = newNode;
             }
         }
         if (h == null)
-            h = t = newNode(null);
+            h = t = new Node<E>(null);
         head = h;
         tail = t;
     }
@@ -256,9 +270,8 @@
      * 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))
-            lazySetNext(h, h);
+            h.lazySetNext(h);
     }
 
     /**
@@ -279,13 +292,14 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        final Node<E> newNode = newNode(Objects.requireNonNull(e));
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
 
         for (Node<E> t = tail, p = t;;) {
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, newNode)) {
+                if (p.casNext(null, newNode)) {
                     // Successful CAS is the linearization point
                     // for e to become an element of this queue,
                     // and for newNode to become "live".
@@ -313,7 +327,7 @@
             for (Node<E> h = head, p = h, q;;) {
                 E item = p.item;
 
-                if (item != null && casItem(p, item, null)) {
+                if (item != null && p.casItem(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
@@ -400,17 +414,13 @@
      * @return the number of elements in this queue
      */
     public int size() {
-        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;
-        }
+        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;
     }
 
     /**
@@ -422,12 +432,11 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        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;
-            }
+        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;
         }
         return false;
     }
@@ -444,25 +453,19 @@
      * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
-        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;
+        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;
             }
+            pred = p;
         }
         return false;
     }
@@ -487,11 +490,12 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            Node<E> newNode = newNode(Objects.requireNonNull(e));
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                lazySetNext(last, newNode);
+                last.lazySetNext(newNode);
                 last = newNode;
             }
         }
@@ -503,7 +507,7 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, beginningOfTheEnd)) {
+                if (p.casNext(null, beginningOfTheEnd)) {
                     // Successful CAS is the linearization point
                     // for all elements to be added to this queue.
                     if (!casTail(t, last)) {
@@ -529,62 +533,6 @@
         }
     }
 
-    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.
@@ -599,7 +547,14 @@
      * @return an array containing all of the elements in this queue
      */
     public Object[] toArray() {
-        return toArrayInternal(null);
+        // 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();
     }
 
     /**
@@ -623,7 +578,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()}.
@@ -639,16 +594,40 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        if (a == null) throw new NullPointerException();
-        return (T[]) toArrayInternal(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);
     }
 
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this queue in proper sequence
      */
@@ -676,47 +655,54 @@
         private Node<E> lastRet;
 
         Itr() {
-            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;
+            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;
                 }
-                updateHead(h, p);
-                return;
+                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;
+                }
             }
         }
 
         public boolean hasNext() {
-            return nextItem != null;
+            return nextNode != null;
         }
 
         public E next() {
-            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);
-            }
+            if (nextNode == null) throw new NoSuchElementException();
+            return advance();
         }
 
         public void remove() {
@@ -731,8 +717,6 @@
     /**
      * Saves this queue to a stream (that is, serializes it).
      *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
      */
@@ -755,10 +739,6 @@
 
     /**
      * Reconstitutes this queue 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 {
@@ -766,156 +746,55 @@
 
         // Read in elements until trailing null sentinel found
         Node<E> h = null, t = null;
-        for (Object item; (item = s.readObject()) != null; ) {
+        Object item;
+        while ((item = s.readObject()) != null) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = newNode((E) item);
+            Node<E> newNode = new Node<E>((E) item);
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                t.lazySetNext(newNode);
                 t = newNode;
             }
         }
         if (h == null)
-            h = t = newNode(null);
+            h = t = new Node<E>(null);
         head = h;
         tail = t;
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class CLQSpliterator<E> implements Spliterator<E> {
-        static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final ConcurrentLinkedQueue<E> queue;
-        Node<E> current;    // current node; null until initialized
-        int batch;          // batch size for splits
-        boolean exhausted;  // true when no more nodes
-        CLQSpliterator(ConcurrentLinkedQueue<E> queue) {
-            this.queue = queue;
-        }
-
-        public Spliterator<E> trySplit() {
-            Node<E> p;
-            final ConcurrentLinkedQueue<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.first()) != null) &&
-                p.next != null) {
-                Object[] a = new Object[n];
-                int i = 0;
-                do {
-                    if ((a[i] = p.item) != null)
-                        ++i;
-                    if (p == (p = p.next))
-                        p = q.first();
-                } while (p != null && i < n);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (i > 0) {
-                    batch = i;
-                    return Spliterators.spliterator
-                        (a, 0, i, (Spliterator.ORDERED |
-                                   Spliterator.NONNULL |
-                                   Spliterator.CONCURRENT));
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super E> action) {
-            Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedQueue<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
-                exhausted = true;
-                do {
-                    E e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedQueue<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
-                E e;
-                do {
-                    e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                } while (e == null && p != null);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (e != null) {
-                    action.accept(e);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public long estimateSize() { return Long.MAX_VALUE; }
-
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
-        }
-    }
-
     /**
-     * Returns a {@link Spliterator} over the elements in this queue.
+     * Throws NullPointerException if argument is null.
      *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this queue
-     * @since 1.8
+     * @param v the element
      */
-    @Override
-    public Spliterator<E> spliterator() {
-        return new CLQSpliterator<E>(this);
+    private static void checkNotNull(Object v) {
+        if (v == null)
+            throw new NullPointerException();
     }
 
     private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
     }
 
     private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
 
     // Unsafe mechanics
 
-    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;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long headOffset;
+    private static final long tailOffset;
     static {
         try {
-            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) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ConcurrentLinkedQueue.class;
+            headOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("head"));
+            tailOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("tail"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
index ae4d221..1391f04 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -7,27 +7,14 @@
 package java.util.concurrent;
 
 import java.util.Map;
-import java.util.Objects;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Function;
 
 // BEGIN android-note
 // removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
 // END android-note
 
 /**
- * A {@link java.util.Map} providing thread safety and atomicity
- * guarantees.
- *
- * <p>To maintain the specified guarantees, default implementations of
- * methods including {@link #putIfAbsent} inherited from {@link Map}
- * must be overridden by implementations of this interface. Similarly,
- * implementations of the collections returned by methods {@link
- * #keySet}, {@link #values}, and {@link #entrySet} must override
- * methods such as {@code removeIf} when necessary to
- * preserve atomicity guarantees.
+ * A {@link java.util.Map} providing additional atomic
+ * {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
  *
  * <p>Memory consistency effects: As with other concurrent
  * collections, actions in a thread prior to placing an object into a
@@ -42,65 +29,11 @@
  * @param <V> the type of mapped values
  */
 public interface ConcurrentMap<K,V> extends Map<K,V> {
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implNote This implementation assumes that the ConcurrentMap cannot
-     * contain null values and {@code get()} returning null unambiguously means
-     * the key is absent. Implementations which support null values
-     * <strong>must</strong> override this default implementation.
-     *
-     * @throws ClassCastException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default V getOrDefault(Object key, V defaultValue) {
-        V v;
-        return ((v = get(key)) != null) ? v : defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec The default implementation is equivalent to, for this
-     * {@code map}:
-     * <pre> {@code
-     * for (Map.Entry<K,V> entry : map.entrySet()) {
-     *   action.accept(entry.getKey(), entry.getValue());
-     * }}</pre>
-     *
-     * @implNote The default implementation assumes that
-     * {@code IllegalStateException} thrown by {@code getKey()} or
-     * {@code getValue()} indicates that the entry has been removed and cannot
-     * be processed. Operation continues for subsequent entries.
-     *
-     * @throws NullPointerException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default void forEach(BiConsumer<? super K, ? super V> action) {
-        Objects.requireNonNull(action);
-        for (Map.Entry<K,V> entry : entrySet()) {
-            K k;
-            V v;
-            try {
-                k = entry.getKey();
-                v = entry.getValue();
-            } catch (IllegalStateException ise) {
-                // this usually means the entry is no longer in the map.
-                continue;
-            }
-            action.accept(k, v);
-        }
-    }
-
     /**
      * If the specified key is not already associated
-     * with a value, associates it with the given value.
-     * This is equivalent to, for this {@code map}:
-     * <pre> {@code
+     * with a value, associate it with the given value.
+     * This is equivalent to
+     *  <pre> {@code
      * if (!map.containsKey(key))
      *   return map.put(key, value);
      * else
@@ -108,9 +41,6 @@
      *
      * except that the action is performed atomically.
      *
-     * @implNote This implementation intentionally re-abstracts the
-     * inappropriate default provided in {@code Map}.
-     *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -131,21 +61,16 @@
 
     /**
      * Removes the entry for a key only if currently mapped to a given value.
-     * This is equivalent to, for this {@code map}:
-     * <pre> {@code
-     * if (map.containsKey(key)
-     *     && Objects.equals(map.get(key), value)) {
+     * This is equivalent to
+     *  <pre> {@code
+     * if (map.containsKey(key) && map.get(key).equals(value)) {
      *   map.remove(key);
      *   return true;
-     * } else {
-     *   return false;
-     * }}</pre>
+     * } else
+     *   return false;}</pre>
      *
      * except that the action is performed atomically.
      *
-     * @implNote This implementation intentionally re-abstracts the
-     * inappropriate default provided in {@code Map}.
-     *
      * @param key key with which the specified value is associated
      * @param value value expected to be associated with the specified key
      * @return {@code true} if the value was removed
@@ -153,30 +78,25 @@
      *         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="../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="../Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object key, Object value);
 
     /**
      * Replaces the entry for a key only if currently mapped to a given value.
-     * This is equivalent to, for this {@code map}:
-     * <pre> {@code
-     * if (map.containsKey(key)
-     *     && Objects.equals(map.get(key), oldValue)) {
+     * This is equivalent to
+     *  <pre> {@code
+     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
      *   map.put(key, newValue);
      *   return true;
-     * } else {
-     *   return false;
-     * }}</pre>
+     * } else
+     *   return false;}</pre>
      *
      * except that the action is performed atomically.
      *
-     * @implNote This implementation intentionally re-abstracts the
-     * inappropriate default provided in {@code Map}.
-     *
      * @param key key with which the specified value is associated
      * @param oldValue value expected to be associated with the specified key
      * @param newValue value to be associated with the specified key
@@ -194,18 +114,15 @@
 
     /**
      * Replaces the entry for a key only if currently mapped to some value.
-     * This is equivalent to, for this {@code map}:
-     * <pre> {@code
-     * if (map.containsKey(key))
+     * This is equivalent to
+     *  <pre> {@code
+     * if (map.containsKey(key)) {
      *   return map.put(key, value);
-     * else
+     * } else
      *   return null;}</pre>
      *
      * except that the action is performed atomically.
      *
-     * @implNote This implementation intentionally re-abstracts the
-     * inappropriate default provided in {@code Map}.
-     *
      * @param key key with which the specified value is associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
@@ -223,251 +140,4 @@
      *         or value prevents it from being stored in this map
      */
     V replace(K key, V value);
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec
-     * <p>The default implementation is equivalent to, for this {@code map}:
-     * <pre> {@code
-     * for (Map.Entry<K,V> entry : map.entrySet()) {
-     *   K k;
-     *   V v;
-     *   do {
-     *     k = entry.getKey();
-     *     v = entry.getValue();
-     *   } while (!map.replace(k, v, function.apply(k, v)));
-     * }}</pre>
-     *
-     * The default implementation may retry these steps when multiple
-     * threads attempt updates including potentially calling the function
-     * repeatedly for a given key.
-     *
-     * <p>This implementation assumes that the ConcurrentMap cannot contain null
-     * values and {@code get()} returning null unambiguously means the key is
-     * absent. Implementations which support null values <strong>must</strong>
-     * override this default implementation.
-     *
-     * @throws UnsupportedOperationException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @throws ClassCastException {@inheritDoc}
-     * @throws IllegalArgumentException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-        Objects.requireNonNull(function);
-        forEach((k,v) -> {
-            while (!replace(k, v, function.apply(k, v))) {
-                // v changed or k is gone
-                if ( (v = get(k)) == null) {
-                    // k is no longer in the map.
-                    break;
-                }
-            }
-        });
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec
-     * The default implementation is equivalent to the following steps for this
-     * {@code map}:
-     *
-     * <pre> {@code
-     * V oldValue, newValue;
-     * return ((oldValue = map.get(key)) == null
-     *         && (newValue = mappingFunction.apply(key)) != null
-     *         && (oldValue = map.putIfAbsent(key, newValue)) == null)
-     *   ? newValue
-     *   : oldValue;}</pre>
-     *
-     * <p>This implementation assumes that the ConcurrentMap cannot contain null
-     * values and {@code get()} returning null unambiguously means the key is
-     * absent. Implementations which support null values <strong>must</strong>
-     * override this default implementation.
-     *
-     * @throws UnsupportedOperationException {@inheritDoc}
-     * @throws ClassCastException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @throws IllegalArgumentException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default V computeIfAbsent(K key,
-            Function<? super K, ? extends V> mappingFunction) {
-        Objects.requireNonNull(mappingFunction);
-        V oldValue, newValue;
-        return ((oldValue = get(key)) == null
-                && (newValue = mappingFunction.apply(key)) != null
-                && (oldValue = putIfAbsent(key, newValue)) == null)
-            ? newValue
-            : oldValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}:
-     *
-     * <pre> {@code
-     * for (V oldValue; (oldValue = map.get(key)) != null; ) {
-     *   V newValue = remappingFunction.apply(key, oldValue);
-     *   if ((newValue == null)
-     *       ? map.remove(key, oldValue)
-     *       : map.replace(key, oldValue, newValue))
-     *     return newValue;
-     * }
-     * return null;}</pre>
-     * When multiple threads attempt updates, map operations and the
-     * remapping function may be called multiple times.
-     *
-     * <p>This implementation assumes that the ConcurrentMap cannot contain null
-     * values and {@code get()} returning null unambiguously means the key is
-     * absent. Implementations which support null values <strong>must</strong>
-     * override this default implementation.
-     *
-     * @throws UnsupportedOperationException {@inheritDoc}
-     * @throws ClassCastException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @throws IllegalArgumentException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default V computeIfPresent(K key,
-            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        for (V oldValue; (oldValue = get(key)) != null; ) {
-            V newValue = remappingFunction.apply(key, oldValue);
-            if ((newValue == null)
-                ? remove(key, oldValue)
-                : replace(key, oldValue, newValue))
-                return newValue;
-        }
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}:
-     *
-     * <pre> {@code
-     * for (;;) {
-     *   V oldValue = map.get(key);
-     *   V newValue = remappingFunction.apply(key, oldValue);
-     *   if (newValue != null) {
-     *     if ((oldValue != null)
-     *       ? map.replace(key, oldValue, newValue)
-     *       : map.putIfAbsent(key, newValue) == null)
-     *       return newValue;
-     *   } else if (oldValue == null || map.remove(key, oldValue)) {
-     *     return null;
-     *   }
-     * }}</pre>
-     * When multiple threads attempt updates, map operations and the
-     * remapping function may be called multiple times.
-     *
-     * <p>This implementation assumes that the ConcurrentMap cannot contain null
-     * values and {@code get()} returning null unambiguously means the key is
-     * absent. Implementations which support null values <strong>must</strong>
-     * override this default implementation.
-     *
-     * @throws UnsupportedOperationException {@inheritDoc}
-     * @throws ClassCastException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @throws IllegalArgumentException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default V compute(K key,
-                      BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        retry: for (;;) {
-            V oldValue = get(key);
-            // if putIfAbsent fails, opportunistically use its return value
-            haveOldValue: for (;;) {
-                V newValue = remappingFunction.apply(key, oldValue);
-                if (newValue != null) {
-                    if (oldValue != null) {
-                        if (replace(key, oldValue, newValue))
-                            return newValue;
-                    }
-                    else if ((oldValue = putIfAbsent(key, newValue)) == null)
-                        return newValue;
-                    else continue haveOldValue;
-                } else if (oldValue == null || remove(key, oldValue)) {
-                    return null;
-                }
-                continue retry;
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}:
-     *
-     * <pre> {@code
-     * for (;;) {
-     *   V oldValue = map.get(key);
-     *   if (oldValue != null) {
-     *     V newValue = remappingFunction.apply(oldValue, value);
-     *     if (newValue != null) {
-     *       if (map.replace(key, oldValue, newValue))
-     *         return newValue;
-     *     } else if (map.remove(key, oldValue)) {
-     *       return null;
-     *     }
-     *   } else if (map.putIfAbsent(key, value) == null) {
-     *     return value;
-     *   }
-     * }}</pre>
-     * When multiple threads attempt updates, map operations and the
-     * remapping function may be called multiple times.
-     *
-     * <p>This implementation assumes that the ConcurrentMap cannot contain null
-     * values and {@code get()} returning null unambiguously means the key is
-     * absent. Implementations which support null values <strong>must</strong>
-     * override this default implementation.
-     *
-     * @throws UnsupportedOperationException {@inheritDoc}
-     * @throws ClassCastException {@inheritDoc}
-     * @throws NullPointerException {@inheritDoc}
-     * @throws IllegalArgumentException {@inheritDoc}
-     * @since 1.8
-     */
-    @Override
-    default V merge(K key, V value,
-            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        Objects.requireNonNull(value);
-        retry: for (;;) {
-            V oldValue = get(key);
-            // if putIfAbsent fails, opportunistically use its return value
-            haveOldValue: for (;;) {
-                if (oldValue != null) {
-                    V newValue = remappingFunction.apply(oldValue, value);
-                    if (newValue != null) {
-                        if (replace(key, oldValue, newValue))
-                            return newValue;
-                    } else if (remove(key, oldValue)) {
-                        return null;
-                    }
-                    continue retry;
-                } else {
-                    if ((oldValue = putIfAbsent(key, value)) == null)
-                        return value;
-                    continue haveOldValue;
-                }
-            }
-        }
-    }
 }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
index 0d795b4..17890ff 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent;
 
-import java.util.NavigableMap;
-import java.util.NavigableSet;
+import java.util.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -74,7 +73,7 @@
      * reflected in the descending map, and vice-versa.
      *
      * <p>The returned map has an ordering equivalent to
-     * {@link java.util.Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
+     * {@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}.
      *
@@ -93,12 +92,15 @@
      * operations.  It does not support the {@code add} or {@code addAll}
      * operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * @return a navigable set view of the keys in this map
      */
-    NavigableSet<K> navigableKeySet();
+    public NavigableSet<K> navigableKeySet();
 
     /**
      * Returns a {@link NavigableSet} view of the keys contained in this map.
@@ -111,8 +113,11 @@
      * operations.  It does not support the {@code add} or {@code addAll}
      * operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * <p>This method is equivalent to method {@code navigableKeySet}.
      *
@@ -131,10 +136,13 @@
      * operations.  It does not support the {@code add} or {@code addAll}
      * operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * @return a reverse order navigable set view of the keys in this map
      */
-    NavigableSet<K> descendingKeySet();
+    public NavigableSet<K> descendingKeySet();
 }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index 359d4f1..0e8b64a 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -6,28 +6,7 @@
 
 package java.util.concurrent;
 
-import java.io.Serializable;
-import java.util.AbstractCollection;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.Spliterator;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
+import java.util.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -45,13 +24,12 @@
  * {@code containsKey}, {@code get}, {@code put} and
  * {@code remove} operations and their variants.  Insertion, removal,
  * update, and access operations safely execute concurrently by
- * multiple threads.
- *
- * <p>Iterators and spliterators are
- * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
- *
- * <p>Ascending key ordered views and their iterators are faster than
- * descending ones.
+ * multiple threads.  Iterators are <i>weakly consistent</i>, returning
+ * elements reflecting the state of the map at some point at or since
+ * the creation of the iterator.  They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations. Ascending key ordered views and their iterators
+ * are faster than descending ones.
  *
  * <p>All {@code Map.Entry} pairs returned by methods in this class
  * and its views represent snapshots of mappings at the time they were
@@ -83,8 +61,11 @@
  * @param <V> the type of mapped values
  * @since 1.6
  */
+@SuppressWarnings("unchecked")
 public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
-    implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {
+    implements ConcurrentNavigableMap<K,V>,
+               Cloneable,
+               java.io.Serializable {
     /*
      * This class implements a tree-like two-dimensionally linked skip
      * list in which the index levels are represented in separate
@@ -248,7 +229,7 @@
      *
      * Indexing uses skip list parameters that maintain good search
      * performance while using sparser-than-usual indices: The
-     * hardwired parameters k=1, p=0.5 (see method doPut) mean
+     * hardwired parameters k=1, p=0.5 (see method randomLevel) mean
      * that about one-quarter of the nodes have indices. Of those that
      * do, half have one level, a quarter have two, and so on (see
      * Pugh's Skip List Cookbook, sec 3.4).  The expected total space
@@ -286,20 +267,6 @@
      * there is a fair amount of near-duplication of code to handle
      * variants.
      *
-     * To produce random values without interference across threads,
-     * we use within-JDK thread local random support (via the
-     * "secondary seed", to avoid interference with user-level
-     * ThreadLocalRandom.)
-     *
-     * A previous version of this class wrapped non-comparable keys
-     * with their comparators to emulate Comparables when using
-     * comparators vs Comparables.  However, JVMs now appear to better
-     * handle infusing comparator-vs-comparable choice into search
-     * loops. Static method cpr(comparator, x, y) is used for all
-     * comparisons, which works well as long as the comparator
-     * argument is set up outside of loops (thus sometimes passed as
-     * an argument to internal methods) to avoid field re-reads.
-     *
      * For explanation of algorithms sharing at least a couple of
      * features with this one, see Mikhail Fomitchev's thesis
      * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
@@ -327,10 +294,18 @@
 
     private static final long serialVersionUID = -8627078645895051609L;
 
+//  BEGIN android-removed
+//  /**
+//   * Generates the initial random seed for the cheaper per-instance
+//   * random number generators used in randomLevel.
+//   */
+//  private static final Random seedGenerator = new Random();
+//  END android-removed
+
     /**
-     * Special value used to identify base-level header.
+     * Special value used to identify base-level header
      */
-    static final Object BASE_HEADER = new Object();
+    private static final Object BASE_HEADER = new Object();
 
     /**
      * The topmost head index of the skiplist.
@@ -338,19 +313,24 @@
     private transient volatile HeadIndex<K,V> head;
 
     /**
-     * The comparator used to maintain order in this map, or null if
-     * using natural ordering.  (Non-private to simplify access in
-     * nested classes.)
+     * The comparator used to maintain order in this map, or null
+     * if using natural ordering.
      * @serial
      */
-    final Comparator<? super K> comparator;
+    private final Comparator<? super K> comparator;
+
+    /**
+     * Seed for simple random number generator.  Not volatile since it
+     * doesn't matter too much if different threads don't see updates.
+     */
+    private transient int randomSeed;
 
     /** Lazily initialized key set */
-    private transient KeySet<K,V> keySet;
+    private transient KeySet<K> keySet;
     /** Lazily initialized entry set */
     private transient EntrySet<K,V> entrySet;
     /** Lazily initialized values collection */
-    private transient Values<K,V> values;
+    private transient Values<V> values;
     /** Lazily initialized descending key set */
     private transient ConcurrentNavigableMap<K,V> descendingMap;
 
@@ -359,20 +339,27 @@
      * clear, readObject. and ConcurrentSkipListSet.clone.
      * (Note that comparator must be separately initialized.)
      */
-    private void initialize() {
+    final void initialize() {
         keySet = null;
         entrySet = null;
         values = null;
         descendingMap = null;
+        // BEGIN android-changed
+        //
+        // Most processes are forked from the zygote, so they'll end up
+        // with the same random seed unless we take additional post fork
+        // measures.
+        randomSeed = Math.randomIntInternal() | 0x0100; // ensure nonzero
+        // END android-changed
         head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
                                   null, null, 1);
     }
 
     /**
-     * compareAndSet head node.
+     * compareAndSet head node
      */
     private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
 
     /* ---------------- Nodes -------------- */
@@ -412,17 +399,17 @@
         }
 
         /**
-         * compareAndSet value field.
+         * compareAndSet value field
          */
         boolean casValue(Object cmp, Object val) {
-            return U.compareAndSwapObject(this, VALUE, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
         }
 
         /**
-         * compareAndSet next field.
+         * compareAndSet next field
          */
         boolean casNext(Node<K,V> cmp, Node<K,V> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
         }
 
         /**
@@ -470,7 +457,7 @@
              */
             if (f == next && this == b.next) {
                 if (f == null || f.value != f) // not already marked
-                    casNext(f, new Node<K,V>(f));
+                    appendMarker(f);
                 else
                     b.casNext(this, f.next);
             }
@@ -486,8 +473,7 @@
             Object v = value;
             if (v == this || v == BASE_HEADER)
                 return null;
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return vv;
+            return (V)v;
         }
 
         /**
@@ -496,26 +482,27 @@
          * @return new entry or null
          */
         AbstractMap.SimpleImmutableEntry<K,V> createSnapshot() {
-            Object v = value;
-            if (v == null || v == this || v == BASE_HEADER)
+            V v = getValidValue();
+            if (v == null)
                 return null;
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
+            return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
         }
 
-        // Unsafe mechanics
+        // UNSAFE mechanics
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
-        private static final long NEXT;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long valueOffset;
+        private static final long nextOffset;
 
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Node.class.getDeclaredField("value"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-            } catch (ReflectiveOperationException e) {
+                UNSAFE = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = Node.class;
+                valueOffset = UNSAFE.objectFieldOffset
+                    (k.getDeclaredField("value"));
+                nextOffset = UNSAFE.objectFieldOffset
+                    (k.getDeclaredField("next"));
+            } catch (Exception e) {
                 throw new Error(e);
             }
         }
@@ -545,10 +532,10 @@
         }
 
         /**
-         * compareAndSet right field.
+         * compareAndSet right field
          */
         final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
-            return U.compareAndSwapObject(this, RIGHT, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val);
         }
 
         /**
@@ -581,17 +568,19 @@
          * @return true if successful
          */
         final boolean unlink(Index<K,V> succ) {
-            return node.value != null && casRight(succ, succ.right);
+            return !indexesDeletedNode() && casRight(succ, succ.right);
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long RIGHT;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long rightOffset;
         static {
             try {
-                RIGHT = U.objectFieldOffset
-                    (Index.class.getDeclaredField("right"));
-            } catch (ReflectiveOperationException e) {
+                UNSAFE = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = Index.class;
+                rightOffset = UNSAFE.objectFieldOffset
+                    (k.getDeclaredField("right"));
+            } catch (Exception e) {
                 throw new Error(e);
             }
         }
@@ -613,12 +602,80 @@
     /* ---------------- Comparison utilities -------------- */
 
     /**
-     * Compares using comparator or natural ordering if null.
-     * Called only by methods that have performed required type checks.
+     * Represents a key with a comparator as a Comparable.
+     *
+     * Because most sorted collections seem to use natural ordering on
+     * Comparables (Strings, Integers, etc), most internal methods are
+     * geared to use them. This is generally faster than checking
+     * per-comparison whether to use comparator or comparable because
+     * it doesn't require a (Comparable) cast for each comparison.
+     * (Optimizers can only sometimes remove such redundant checks
+     * themselves.) When Comparators are used,
+     * ComparableUsingComparators are created so that they act in the
+     * same way as natural orderings. This penalizes use of
+     * Comparators vs Comparables, which seems like the right
+     * tradeoff.
      */
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    static final int cpr(Comparator c, Object x, Object y) {
-        return (c != null) ? c.compare(x, y) : ((Comparable)x).compareTo(y);
+    static final class ComparableUsingComparator<K> implements Comparable<K> {
+        final K actualKey;
+        final Comparator<? super K> cmp;
+        ComparableUsingComparator(K key, Comparator<? super K> cmp) {
+            this.actualKey = key;
+            this.cmp = cmp;
+        }
+        public int compareTo(K k2) {
+            return cmp.compare(actualKey, k2);
+        }
+    }
+
+    /**
+     * If using comparator, return a ComparableUsingComparator, else
+     * cast key as Comparable, which may cause ClassCastException,
+     * which is propagated back to caller.
+     */
+    private Comparable<? super K> comparable(Object key)
+            throws ClassCastException {
+        if (key == null)
+            throw new NullPointerException();
+        if (comparator != null)
+            return new ComparableUsingComparator<K>((K)key, comparator);
+        else
+            return (Comparable<? super K>)key;
+    }
+
+    /**
+     * Compares using comparator or natural ordering. Used when the
+     * ComparableUsingComparator approach doesn't apply.
+     */
+    int compare(K k1, K k2) throws ClassCastException {
+        Comparator<? super K> cmp = comparator;
+        if (cmp != null)
+            return cmp.compare(k1, k2);
+        else
+            return ((Comparable<? super K>)k1).compareTo(k2);
+    }
+
+    /**
+     * Returns true if given key greater than or equal to least and
+     * strictly less than fence, bypassing either test if least or
+     * fence are null. Needed mainly in submap operations.
+     */
+    boolean inHalfOpenRange(K key, K least, K fence) {
+        if (key == null)
+            throw new NullPointerException();
+        return ((least == null || compare(key, least) >= 0) &&
+                (fence == null || compare(key, fence) <  0));
+    }
+
+    /**
+     * Returns true if given key greater than or equal to least and less
+     * or equal to fence. Needed mainly in submap operations.
+     */
+    boolean inOpenRange(K key, K least, K fence) {
+        if (key == null)
+            throw new NullPointerException();
+        return ((least == null || compare(key, least) >= 0) &&
+                (fence == null || compare(key, fence) <= 0));
     }
 
     /* ---------------- Traversal -------------- */
@@ -631,11 +688,13 @@
      * @param key the key
      * @return a predecessor of key
      */
-    private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
+    private Node<K,V> findPredecessor(Comparable<? super K> key) {
         if (key == null)
             throw new NullPointerException(); // don't postpone errors
         for (;;) {
-            for (Index<K,V> q = head, r = q.right, d;;) {
+            Index<K,V> q = head;
+            Index<K,V> r = q.right;
+            for (;;) {
                 if (r != null) {
                     Node<K,V> n = r.node;
                     K k = n.key;
@@ -645,16 +704,18 @@
                         r = q.right;         // reread r
                         continue;
                     }
-                    if (cpr(cmp, key, k) > 0) {
+                    if (key.compareTo(k) > 0) {
                         q = r;
                         r = r.right;
                         continue;
                     }
                 }
-                if ((d = q.down) == null)
+                Index<K,V> d = q.down;
+                if (d != null) {
+                    q = d;
+                    r = d.right;
+                } else
                     return q.node;
-                q = d;
-                r = d.right;
             }
         }
     }
@@ -695,79 +756,62 @@
      *
      * 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
      */
-    private Node<K,V> findNode(Object key) {
-        if (key == null)
-            throw new NullPointerException(); // don't postpone errors
-        Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
+    private Node<K,V> findNode(Comparable<? super K> key) {
+        for (;;) {
+            Node<K,V> b = findPredecessor(key);
+            Node<K,V> n = b.next;
+            for (;;) {
                 if (n == null)
-                    break outer;
+                    return null;
                 Node<K,V> f = n.next;
                 if (n != b.next)                // inconsistent read
                     break;
-                if ((v = n.value) == null) {    // n is deleted
+                Object v = n.value;
+                if (v == null) {                // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (b.value == null || v == n)  // b is deleted
+                if (v == n || b.value == null)  // b is deleted
                     break;
-                if ((c = cpr(cmp, key, n.key)) == 0)
+                int c = key.compareTo(n.key);
+                if (c == 0)
                     return n;
                 if (c < 0)
-                    break outer;
+                    return null;
                 b = n;
                 n = f;
             }
         }
-        return null;
     }
 
     /**
-     * Gets value for key. Almost the same as findNode, but returns
-     * the found value (to avoid retries during re-reads)
-     *
-     * @param key the key
+     * Gets value for key using findNode.
+     * @param okey the key
      * @return the value, or null if absent
      */
-    private V doGet(Object key) {
-        if (key == null)
-            throw new NullPointerException();
-        Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
-                if (n == null)
-                    break outer;
-                Node<K,V> f = n.next;
-                if (n != b.next)                // inconsistent read
-                    break;
-                if ((v = n.value) == null) {    // n is deleted
-                    n.helpDelete(b, f);
-                    break;
-                }
-                if (b.value == null || v == n)  // b is deleted
-                    break;
-                if ((c = cpr(cmp, key, n.key)) == 0) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    return vv;
-                }
-                if (c < 0)
-                    break outer;
-                b = n;
-                n = f;
-            }
+    private V doGet(Object okey) {
+        Comparable<? super K> key = comparable(okey);
+        /*
+         * Loop needed here and elsewhere in case value field goes
+         * null just as it is about to be returned, in which case we
+         * lost a race with a deletion, so must retry.
+         */
+        for (;;) {
+            Node<K,V> n = findNode(key);
+            if (n == null)
+                return null;
+            Object v = n.value;
+            if (v != null)
+                return (V)v;
         }
-        return null;
     }
 
     /* ---------------- Insertion -------------- */
@@ -775,126 +819,187 @@
     /**
      * Main insertion method.  Adds element if not present, or
      * replaces value if present and onlyIfAbsent is false.
-     * @param key the key
+     * @param kkey the key
      * @param value the value that must be associated with key
      * @param onlyIfAbsent if should not insert if already present
      * @return the old value, or null if newly inserted
      */
-    private V doPut(K key, V value, boolean onlyIfAbsent) {
-        Node<K,V> z;             // added node
-        if (key == null)
-            throw new NullPointerException();
-        Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
+    private V doPut(K kkey, V value, boolean onlyIfAbsent) {
+        Comparable<? super K> key = comparable(kkey);
+        for (;;) {
+            Node<K,V> b = findPredecessor(key);
+            Node<K,V> n = b.next;
+            for (;;) {
                 if (n != null) {
-                    Object v; int c;
                     Node<K,V> f = n.next;
                     if (n != b.next)               // inconsistent read
                         break;
-                    if ((v = n.value) == null) {   // n is deleted
+                    Object v = n.value;
+                    if (v == null) {               // n is deleted
                         n.helpDelete(b, f);
                         break;
                     }
-                    if (b.value == null || v == n) // b is deleted
+                    if (v == n || b.value == null) // b is deleted
                         break;
-                    if ((c = cpr(cmp, key, n.key)) > 0) {
+                    int c = key.compareTo(n.key);
+                    if (c > 0) {
                         b = n;
                         n = f;
                         continue;
                     }
                     if (c == 0) {
-                        if (onlyIfAbsent || n.casValue(v, value)) {
-                            @SuppressWarnings("unchecked") V vv = (V)v;
-                            return vv;
-                        }
-                        break; // restart if lost race to replace value
+                        if (onlyIfAbsent || n.casValue(v, value))
+                            return (V)v;
+                        else
+                            break; // restart if lost race to replace value
                     }
                     // else c < 0; fall through
                 }
 
-                z = new Node<K,V>(key, value, n);
+                Node<K,V> z = new Node<K,V>(kkey, value, n);
                 if (!b.casNext(n, z))
                     break;         // restart if lost race to append to b
-                break outer;
+                int level = randomLevel();
+                if (level > 0)
+                    insertIndex(z, level);
+                return null;
             }
         }
+    }
 
-        int rnd = ThreadLocalRandom.nextSecondarySeed();
-        if ((rnd & 0x80000001) == 0) { // test highest and lowest bits
-            int level = 1, max;
-            while (((rnd >>>= 1) & 1) != 0)
-                ++level;
+    /**
+     * Returns a random level for inserting a new node.
+     * Hardwired to k=1, p=0.5, max 31 (see above and
+     * Pugh's "Skip List Cookbook", sec 3.4).
+     *
+     * This uses the simplest of the generators described in George
+     * Marsaglia's "Xorshift RNGs" paper.  This is not a high-quality
+     * generator but is acceptable here.
+     */
+    private int randomLevel() {
+        int x = randomSeed;
+        x ^= x << 13;
+        x ^= x >>> 17;
+        randomSeed = x ^= x << 5;
+        if ((x & 0x80000001) != 0) // test highest and lowest bits
+            return 0;
+        int level = 1;
+        while (((x >>>= 1) & 1) != 0) ++level;
+        return level;
+    }
+
+    /**
+     * Creates and adds index nodes for the given node.
+     * @param z the node
+     * @param level the level of the index
+     */
+    private void insertIndex(Node<K,V> z, int level) {
+        HeadIndex<K,V> h = head;
+        int max = h.level;
+
+        if (level <= max) {
             Index<K,V> idx = null;
-            HeadIndex<K,V> h = head;
-            if (level <= (max = h.level)) {
-                for (int i = 1; i <= level; ++i)
-                    idx = new Index<K,V>(z, idx, null);
-            }
-            else { // try to grow by one level
-                level = max + 1; // hold in array and later pick the one to use
-                @SuppressWarnings("unchecked")Index<K,V>[] idxs =
-                    (Index<K,V>[])new Index<?,?>[level+1];
-                for (int i = 1; i <= level; ++i)
-                    idxs[i] = idx = new Index<K,V>(z, idx, null);
-                for (;;) {
-                    h = head;
-                    int oldLevel = h.level;
-                    if (level <= oldLevel) // lost race to add level
-                        break;
-                    HeadIndex<K,V> newh = h;
-                    Node<K,V> oldbase = h.node;
-                    for (int j = oldLevel+1; j <= level; ++j)
-                        newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
-                    if (casHead(h, newh)) {
-                        h = newh;
-                        idx = idxs[level = oldLevel];
-                        break;
-                    }
+            for (int i = 1; i <= level; ++i)
+                idx = new Index<K,V>(z, idx, null);
+            addIndex(idx, h, level);
+
+        } else { // Add a new level
+            /*
+             * To reduce interference by other threads checking for
+             * empty levels in tryReduceLevel, new levels are added
+             * with initialized right pointers. Which in turn requires
+             * keeping levels in an array to access them while
+             * creating new head index nodes from the opposite
+             * direction.
+             */
+            level = max + 1;
+            Index<K,V>[] idxs = (Index<K,V>[])new Index<?,?>[level+1];
+            Index<K,V> idx = null;
+            for (int i = 1; i <= level; ++i)
+                idxs[i] = idx = new Index<K,V>(z, idx, null);
+
+            HeadIndex<K,V> oldh;
+            int k;
+            for (;;) {
+                oldh = head;
+                int oldLevel = oldh.level;
+                if (level <= oldLevel) { // lost race to add level
+                    k = level;
+                    break;
+                }
+                HeadIndex<K,V> newh = oldh;
+                Node<K,V> oldbase = oldh.node;
+                for (int j = oldLevel+1; j <= level; ++j)
+                    newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
+                if (casHead(oldh, newh)) {
+                    k = oldLevel;
+                    break;
                 }
             }
-            // find insertion points and splice in
-            splice: for (int insertionLevel = level;;) {
-                int j = h.level;
-                for (Index<K,V> q = h, r = q.right, t = idx;;) {
-                    if (q == null || t == null)
-                        break splice;
-                    if (r != null) {
-                        Node<K,V> n = r.node;
-                        // compare before deletion check avoids needing recheck
-                        int c = cpr(cmp, key, n.key);
-                        if (n.value == null) {
-                            if (!q.unlink(r))
-                                break;
-                            r = q.right;
-                            continue;
-                        }
-                        if (c > 0) {
-                            q = r;
-                            r = r.right;
-                            continue;
-                        }
-                    }
+            addIndex(idxs[k], oldh, k);
+        }
+    }
 
-                    if (j == insertionLevel) {
-                        if (!q.link(r, t))
-                            break; // restart
-                        if (t.node.value == null) {
+    /**
+     * Adds given index nodes from given level down to 1.
+     * @param idx the topmost index node being inserted
+     * @param h the value of head to use to insert. This must be
+     * snapshotted by callers to provide correct insertion level.
+     * @param indexLevel the level of the index
+     */
+    private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
+        // Track next level to insert in case of retries
+        int insertionLevel = indexLevel;
+        Comparable<? super K> key = comparable(idx.node.key);
+        if (key == null) throw new NullPointerException();
+
+        // Similar to findPredecessor, but adding index nodes along
+        // path to key.
+        for (;;) {
+            int j = h.level;
+            Index<K,V> q = h;
+            Index<K,V> r = q.right;
+            Index<K,V> t = idx;
+            for (;;) {
+                if (r != null) {
+                    Node<K,V> n = r.node;
+                    // compare before deletion check avoids needing recheck
+                    int c = key.compareTo(n.key);
+                    if (n.value == null) {
+                        if (!q.unlink(r))
+                            break;
+                        r = q.right;
+                        continue;
+                    }
+                    if (c > 0) {
+                        q = r;
+                        r = r.right;
+                        continue;
+                    }
+                }
+
+                if (j == insertionLevel) {
+                    // Don't insert index if node already deleted
+                    if (t.indexesDeletedNode()) {
+                        findNode(key); // cleans up
+                        return;
+                    }
+                    if (!q.link(r, t))
+                        break; // restart
+                    if (--insertionLevel == 0) {
+                        // need final deletion check before return
+                        if (t.indexesDeletedNode())
                             findNode(key);
-                            break splice;
-                        }
-                        if (--insertionLevel == 0)
-                            break splice;
+                        return;
                     }
-
-                    if (--j >= insertionLevel && j < level)
-                        t = t.down;
-                    q = q.down;
-                    r = q.right;
                 }
+
+                if (--j >= insertionLevel && j < indexLevel)
+                    t = t.down;
+                q = q.down;
+                r = q.right;
             }
         }
-        return null;
     }
 
     /* ---------------- Deletion -------------- */
@@ -913,52 +1018,51 @@
      * search for it, and we'd like to ensure lack of garbage
      * retention, so must call to be sure.
      *
-     * @param key the key
+     * @param okey the key
      * @param value if non-null, the value that must be
      * associated with key
      * @return the node, or null if not found
      */
-    final V doRemove(Object key, Object value) {
-        if (key == null)
-            throw new NullPointerException();
-        Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
+    final V doRemove(Object okey, Object value) {
+        Comparable<? super K> key = comparable(okey);
+        for (;;) {
+            Node<K,V> b = findPredecessor(key);
+            Node<K,V> n = b.next;
+            for (;;) {
                 if (n == null)
-                    break outer;
+                    return null;
                 Node<K,V> f = n.next;
                 if (n != b.next)                    // inconsistent read
                     break;
-                if ((v = n.value) == null) {        // n is deleted
+                Object v = n.value;
+                if (v == null) {                    // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (b.value == null || v == n)      // b is deleted
+                if (v == n || b.value == null)      // b is deleted
                     break;
-                if ((c = cpr(cmp, key, n.key)) < 0)
-                    break outer;
+                int c = key.compareTo(n.key);
+                if (c < 0)
+                    return null;
                 if (c > 0) {
                     b = n;
                     n = f;
                     continue;
                 }
                 if (value != null && !value.equals(v))
-                    break outer;
+                    return null;
                 if (!n.casValue(v, null))
                     break;
                 if (!n.appendMarker(f) || !b.casNext(n, f))
-                    findNode(key);                  // retry via findNode
+                    findNode(key);                  // Retry via findNode
                 else {
-                    findPredecessor(key, cmp);      // clean index
+                    findPredecessor(key);           // Clean index
                     if (head.right == null)
                         tryReduceLevel();
                 }
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return vv;
+                return (V)v;
             }
         }
-        return null;
     }
 
     /**
@@ -1002,9 +1106,11 @@
      * Specialized variant of findNode to get first valid node.
      * @return first node or null if empty
      */
-    final Node<K,V> findFirst() {
-        for (Node<K,V> b, n;;) {
-            if ((n = (b = head.node).next) == null)
+    Node<K,V> findFirst() {
+        for (;;) {
+            Node<K,V> b = head.node;
+            Node<K,V> n = b.next;
+            if (n == null)
                 return null;
             if (n.value != null)
                 return n;
@@ -1016,9 +1122,11 @@
      * Removes first entry; returns its snapshot.
      * @return null if empty, else snapshot of first entry
      */
-    private Map.Entry<K,V> doRemoveFirstEntry() {
-        for (Node<K,V> b, n;;) {
-            if ((n = (b = head.node).next) == null)
+    Map.Entry<K,V> doRemoveFirstEntry() {
+        for (;;) {
+            Node<K,V> b = head.node;
+            Node<K,V> n = b.next;
+            if (n == null)
                 return null;
             Node<K,V> f = n.next;
             if (n != b.next)
@@ -1033,8 +1141,7 @@
             if (!n.appendMarker(f) || !b.casNext(n, f))
                 findFirst(); // retry
             clearIndexToFirst();
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, vv);
+            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, (V)v);
         }
     }
 
@@ -1043,7 +1150,8 @@
      */
     private void clearIndexToFirst() {
         for (;;) {
-            for (Index<K,V> q = head;;) {
+            Index<K,V> q = head;
+            for (;;) {
                 Index<K,V> r = q.right;
                 if (r != null && r.indexesDeletedNode() && !q.unlink(r))
                     break;
@@ -1056,52 +1164,6 @@
         }
     }
 
-    /**
-     * Removes last entry; returns its snapshot.
-     * Specialized variant of doRemove.
-     * @return null if empty, else snapshot of last entry
-     */
-    private Map.Entry<K,V> doRemoveLastEntry() {
-        for (;;) {
-            Node<K,V> b = findPredecessorOfLast();
-            Node<K,V> n = b.next;
-            if (n == null) {
-                if (b.isBaseHeader())               // empty
-                    return null;
-                else
-                    continue; // all b's successors are deleted; retry
-            }
-            for (;;) {
-                Node<K,V> f = n.next;
-                if (n != b.next)                    // inconsistent read
-                    break;
-                Object v = n.value;
-                if (v == null) {                    // n is deleted
-                    n.helpDelete(b, f);
-                    break;
-                }
-                if (b.value == null || v == n)      // b is deleted
-                    break;
-                if (f != null) {
-                    b = n;
-                    n = f;
-                    continue;
-                }
-                if (!n.casValue(v, null))
-                    break;
-                K key = n.key;
-                if (!n.appendMarker(f) || !b.casNext(n, f))
-                    findNode(key);                  // retry via findNode
-                else {                              // clean index
-                    findPredecessor(key, comparator);
-                    if (head.right == null)
-                        tryReduceLevel();
-                }
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
-            }
-        }
-    }
 
     /* ---------------- Finding and removing last element -------------- */
 
@@ -1109,7 +1171,7 @@
      * Specialized version of find to get last valid node.
      * @return last node or null if empty
      */
-    final Node<K,V> findLast() {
+    Node<K,V> findLast() {
         /*
          * findPredecessor can't be used to traverse index level
          * because this doesn't use comparisons.  So traversals of
@@ -1128,7 +1190,9 @@
             } else if ((d = q.down) != null) {
                 q = d;
             } else {
-                for (Node<K,V> b = q.node, n = b.next;;) {
+                Node<K,V> b = q.node;
+                Node<K,V> n = b.next;
+                for (;;) {
                     if (n == null)
                         return b.isBaseHeader() ? null : b;
                     Node<K,V> f = n.next;            // inconsistent read
@@ -1139,7 +1203,7 @@
                         n.helpDelete(b, f);
                         break;
                     }
-                    if (b.value == null || v == n)      // b is deleted
+                    if (v == n || b.value == null)   // b is deleted
                         break;
                     b = n;
                     n = f;
@@ -1158,7 +1222,8 @@
      */
     private Node<K,V> findPredecessorOfLast() {
         for (;;) {
-            for (Index<K,V> q = head;;) {
+            Index<K,V> q = head;
+            for (;;) {
                 Index<K,V> d, r;
                 if ((r = q.right) != null) {
                     if (r.indexesDeletedNode()) {
@@ -1179,6 +1244,53 @@
         }
     }
 
+    /**
+     * Removes last entry; returns its snapshot.
+     * Specialized variant of doRemove.
+     * @return null if empty, else snapshot of last entry
+     */
+    Map.Entry<K,V> doRemoveLastEntry() {
+        for (;;) {
+            Node<K,V> b = findPredecessorOfLast();
+            Node<K,V> n = b.next;
+            if (n == null) {
+                if (b.isBaseHeader())               // empty
+                    return null;
+                else
+                    continue; // all b's successors are deleted; retry
+            }
+            for (;;) {
+                Node<K,V> f = n.next;
+                if (n != b.next)                    // inconsistent read
+                    break;
+                Object v = n.value;
+                if (v == null) {                    // n is deleted
+                    n.helpDelete(b, f);
+                    break;
+                }
+                if (v == n || b.value == null)      // b is deleted
+                    break;
+                if (f != null) {
+                    b = n;
+                    n = f;
+                    continue;
+                }
+                if (!n.casValue(v, null))
+                    break;
+                K key = n.key;
+                Comparable<? super K> ck = comparable(key);
+                if (!n.appendMarker(f) || !b.casNext(n, f))
+                    findNode(ck);                  // Retry via findNode
+                else {
+                    findPredecessor(ck);           // Clean index
+                    if (head.right == null)
+                        tryReduceLevel();
+                }
+                return new AbstractMap.SimpleImmutableEntry<K,V>(key, (V)v);
+            }
+        }
+    }
+
     /* ---------------- Relational operations -------------- */
 
     // Control values OR'ed as arguments to findNear
@@ -1189,28 +1301,29 @@
 
     /**
      * Utility for ceiling, floor, lower, higher methods.
-     * @param key the key
+     * @param kkey the key
      * @param rel the relation -- OR'ed combination of EQ, LT, GT
      * @return nearest node fitting relation, or null if no such
      */
-    final Node<K,V> findNear(K key, int rel, Comparator<? super K> cmp) {
-        if (key == null)
-            throw new NullPointerException();
+    Node<K,V> findNear(K kkey, int rel) {
+        Comparable<? super K> key = comparable(kkey);
         for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v;
+            Node<K,V> b = findPredecessor(key);
+            Node<K,V> n = b.next;
+            for (;;) {
                 if (n == null)
                     return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b;
                 Node<K,V> f = n.next;
                 if (n != b.next)                  // inconsistent read
                     break;
-                if ((v = n.value) == null) {      // n is deleted
+                Object v = n.value;
+                if (v == null) {                  // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (b.value == null || v == n)      // b is deleted
+                if (v == n || b.value == null)    // b is deleted
                     break;
-                int c = cpr(cmp, key, n.key);
+                int c = key.compareTo(n.key);
                 if ((c == 0 && (rel & EQ) != 0) ||
                     (c <  0 && (rel & LT) == 0))
                     return n;
@@ -1228,10 +1341,9 @@
      * @param rel the relation -- OR'ed combination of EQ, LT, GT
      * @return Entry fitting relation, or null if no such
      */
-    final AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
-        Comparator<? super K> cmp = comparator;
+    AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
         for (;;) {
-            Node<K,V> n = findNear(key, rel, cmp);
+            Node<K,V> n = findNear(key, rel);
             if (n == null)
                 return null;
             AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
@@ -1240,6 +1352,7 @@
         }
     }
 
+
     /* ---------------- Constructors -------------- */
 
     /**
@@ -1329,7 +1442,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<>();
+        ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
 
         // initialize
         for (int i = 0; i <= h.level; ++i)
@@ -1344,14 +1457,8 @@
             map.entrySet().iterator();
         while (it.hasNext()) {
             Map.Entry<? extends K, ? extends V> e = it.next();
-            int rnd = ThreadLocalRandom.current().nextInt();
-            int j = 0;
-            if ((rnd & 0x80000001) == 0) {
-                do {
-                    ++j;
-                } while (((rnd >>>= 1) & 1) != 0);
-                if (j > h.level) j = h.level + 1;
-            }
+            int j = randomLevel();
+            if (j > h.level) j = h.level + 1;
             K k = e.getKey();
             V v = e.getValue();
             if (k == null || v == null)
@@ -1382,8 +1489,6 @@
     /**
      * Saves this map to a stream (that is, serializes it).
      *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData The key (Object) and value (Object) for each
      * key-value mapping represented by the map, followed by
      * {@code null}. The key-value mappings are emitted in key-order
@@ -1408,12 +1513,7 @@
 
     /**
      * Reconstitutes this map 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
      */
-    @SuppressWarnings("unchecked")
     private void readObject(final java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         // Read in the Comparator and any hidden stuff
@@ -1426,12 +1526,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 adapter classes.) It is simpler to just adapt the code.
+         * of adaptor 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<>();
+        ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
         for (int i = 0; i <= h.level; ++i)
             preds.add(null);
         Index<K,V> q = h;
@@ -1449,14 +1549,8 @@
                 throw new NullPointerException();
             K key = (K) k;
             V val = (V) v;
-            int rnd = ThreadLocalRandom.current().nextInt();
-            int j = 0;
-            if ((rnd & 0x80000001) == 0) {
-                do {
-                    ++j;
-                } while (((rnd >>>= 1) & 1) != 0);
-                if (j > h.level) j = h.level + 1;
-            }
+            int j = randomLevel();
+            if (j > h.level) j = h.level + 1;
             Node<K,V> z = new Node<K,V>(key, val, null);
             basepred.next = z;
             basepred = z;
@@ -1513,22 +1607,6 @@
     }
 
     /**
-     * Returns the value to which the specified key is mapped,
-     * or the given defaultValue if this map contains no mapping for the key.
-     *
-     * @param key the key
-     * @param defaultValue the value to return if this map contains
-     * no mapping for the given key
-     * @return the mapping for the key, if present; else the defaultValue
-     * @throws NullPointerException if the specified key is null
-     * @since 1.8
-     */
-    public V getOrDefault(Object key, V defaultValue) {
-        V v;
-        return (v = doGet(key)) == null ? defaultValue : v;
-    }
-
-    /**
      * Associates the specified value with the specified key in this map.
      * If the map previously contained a mapping for the key, the old
      * value is replaced.
@@ -1624,140 +1702,6 @@
         initialize();
     }
 
-    /**
-     * If the specified key is not already associated with a value,
-     * attempts to compute its value using the given mapping function
-     * and enters it into this map unless {@code null}.  The function
-     * is <em>NOT</em> guaranteed to be applied once atomically only
-     * if the value is not present.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param mappingFunction the function to compute a value
-     * @return the current (existing or computed) value associated with
-     *         the specified key, or null if the computed value is null
-     * @throws NullPointerException if the specified key is null
-     *         or the mappingFunction is null
-     * @since 1.8
-     */
-    public V computeIfAbsent(K key,
-                             Function<? super K, ? extends V> mappingFunction) {
-        if (key == null || mappingFunction == null)
-            throw new NullPointerException();
-        V v, p, r;
-        if ((v = doGet(key)) == null &&
-            (r = mappingFunction.apply(key)) != null)
-            v = (p = doPut(key, r, true)) == null ? r : p;
-        return v;
-    }
-
-    /**
-     * If the value for the specified key is present, attempts to
-     * compute a new mapping given the key and its current mapped
-     * value. The function is <em>NOT</em> guaranteed to be applied
-     * once atomically.
-     *
-     * @param key key with which a value may be associated
-     * @param remappingFunction the function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key is null
-     *         or the remappingFunction is null
-     * @since 1.8
-     */
-    public V computeIfPresent(K key,
-                              BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        if (key == null || remappingFunction == null)
-            throw new NullPointerException();
-        Node<K,V> n; Object v;
-        while ((n = findNode(key)) != null) {
-            if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                V r = remappingFunction.apply(key, vv);
-                if (r != null) {
-                    if (n.casValue(vv, r))
-                        return r;
-                }
-                else if (doRemove(key, vv) != null)
-                    break;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Attempts to compute a mapping for the specified key and its
-     * current mapped value (or {@code null} if there is no current
-     * mapping). The function is <em>NOT</em> guaranteed to be applied
-     * once atomically.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param remappingFunction the function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key is null
-     *         or the remappingFunction is null
-     * @since 1.8
-     */
-    public V compute(K key,
-                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        if (key == null || remappingFunction == null)
-            throw new NullPointerException();
-        for (;;) {
-            Node<K,V> n; Object v; V r;
-            if ((n = findNode(key)) == null) {
-                if ((r = remappingFunction.apply(key, null)) == null)
-                    break;
-                if (doPut(key, r, true) == null)
-                    return r;
-            }
-            else if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                if ((r = remappingFunction.apply(key, vv)) != null) {
-                    if (n.casValue(vv, r))
-                        return r;
-                }
-                else if (doRemove(key, vv) != null)
-                    break;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * If the specified key is not already associated with a value,
-     * associates it with the given value.  Otherwise, replaces the
-     * value with the results of the given remapping function, or
-     * removes if {@code null}. The function is <em>NOT</em>
-     * guaranteed to be applied once atomically.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param value the value to use if absent
-     * @param remappingFunction the function to recompute a value if present
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key or value is null
-     *         or the remappingFunction is null
-     * @since 1.8
-     */
-    public V merge(K key, V value,
-                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
-        if (key == null || value == null || remappingFunction == null)
-            throw new NullPointerException();
-        for (;;) {
-            Node<K,V> n; Object v; V r;
-            if ((n = findNode(key)) == null) {
-                if (doPut(key, value, true) == null)
-                    return value;
-            }
-            else if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                if ((r = remappingFunction.apply(vv, value)) != null) {
-                    if (n.casValue(vv, r))
-                        return r;
-                }
-                else if (doRemove(key, vv) != null)
-                    return null;
-            }
-        }
-    }
-
     /* ---------------- View methods -------------- */
 
     /*
@@ -1771,18 +1715,8 @@
 
     /**
      * Returns a {@link NavigableSet} view of the keys contained in this map.
-     *
-     * <p>The set's iterator returns the keys in ascending order.
-     * The set's spliterator additionally reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#NONNULL}, {@link Spliterator#SORTED} and
-     * {@link Spliterator#ORDERED}, with an encounter order that is ascending
-     * key order.  The spliterator's comparator (see
-     * {@link java.util.Spliterator#getComparator()}) is {@code null} if
-     * the map's comparator (see {@link #comparator()}) is {@code null}.
-     * Otherwise, the spliterator's comparator is the same as or imposes the
-     * same total ordering as the map's comparator.
-     *
-     * <p>The set is backed by the map, so changes to the map are
+     * The set's iterator returns the keys in ascending order.
+     * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  The set supports element
      * removal, which removes the corresponding mapping from the map,
      * via the {@code Iterator.remove}, {@code Set.remove},
@@ -1790,32 +1724,31 @@
      * operations.  It does not support the {@code add} or {@code addAll}
      * operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
      * <p>This method is equivalent to method {@code navigableKeySet}.
      *
      * @return a navigable set view of the keys in this map
      */
     public NavigableSet<K> keySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet<K>(this));
     }
 
     public NavigableSet<K> navigableKeySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet<K>(this));
     }
 
     /**
      * Returns a {@link Collection} view of the values contained in this map.
-     * <p>The collection's iterator returns the values in ascending order
-     * of the corresponding keys. The collections's spliterator additionally
-     * reports {@link Spliterator#CONCURRENT}, {@link Spliterator#NONNULL} and
-     * {@link Spliterator#ORDERED}, with an encounter order that is ascending
-     * order of the corresponding keys.
-     *
-     * <p>The collection is backed by the map, so changes to the map are
+     * The collection's iterator returns the values in ascending order
+     * of the corresponding keys.
+     * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  The collection
      * supports element removal, which removes the corresponding
      * mapping from the map, via the {@code Iterator.remove},
@@ -1823,24 +1756,21 @@
      * {@code retainAll} and {@code clear} operations.  It does not
      * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      */
     public Collection<V> values() {
-        Values<K,V> vs = values;
-        return (vs != null) ? vs : (values = new Values<>(this));
+        Values<V> vs = values;
+        return (vs != null) ? vs : (values = new Values<V>(this));
     }
 
     /**
      * Returns a {@link Set} view of the mappings contained in this map.
-     *
-     * <p>The set's iterator returns the entries in ascending key order.  The
-     * set's spliterator additionally reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#NONNULL}, {@link Spliterator#SORTED} and
-     * {@link Spliterator#ORDERED}, with an encounter order that is ascending
-     * key order.
-     *
-     * <p>The set is backed by the map, so changes to the map are
+     * The set's iterator returns the entries in ascending key order.
+     * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  The set supports element
      * removal, which removes the corresponding mapping from the map,
      * via the {@code Iterator.remove}, {@code Set.remove},
@@ -1848,12 +1778,15 @@
      * operations.  It does not support the {@code add} or
      * {@code addAll} operations.
      *
-     * <p>The view's iterators and spliterators are
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
      *
-     * <p>The {@code Map.Entry} elements traversed by the {@code iterator}
-     * or {@code spliterator} do <em>not</em> support the {@code setValue}
-     * operation.
+     * <p>The {@code Map.Entry} elements returned by
+     * {@code iterator.next()} do <em>not</em> support the
+     * {@code setValue} operation.
      *
      * @return a set view of the mappings contained in this map,
      *         sorted in ascending key order
@@ -1938,7 +1871,9 @@
     public boolean remove(Object key, Object value) {
         if (key == null)
             throw new NullPointerException();
-        return value != null && doRemove(key, value) != null;
+        if (value == null)
+            return false;
+        return doRemove(key, value) != null;
     }
 
     /**
@@ -1949,13 +1884,15 @@
      * @throws NullPointerException if any of the arguments are null
      */
     public boolean replace(K key, V oldValue, V newValue) {
-        if (key == null || oldValue == null || newValue == null)
+        if (oldValue == null || newValue == null)
             throw new NullPointerException();
+        Comparable<? super K> k = comparable(key);
         for (;;) {
-            Node<K,V> n; Object v;
-            if ((n = findNode(key)) == null)
+            Node<K,V> n = findNode(k);
+            if (n == null)
                 return false;
-            if ((v = n.value) != null) {
+            Object v = n.value;
+            if (v != null) {
                 if (!oldValue.equals(v))
                     return false;
                 if (n.casValue(v, newValue))
@@ -1974,16 +1911,16 @@
      * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
-        if (key == null || value == null)
+        if (value == null)
             throw new NullPointerException();
+        Comparable<? super K> k = comparable(key);
         for (;;) {
-            Node<K,V> n; Object v;
-            if ((n = findNode(key)) == null)
+            Node<K,V> n = findNode(k);
+            if (n == null)
                 return null;
-            if ((v = n.value) != null && n.casValue(v, value)) {
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return vv;
-            }
+            Object v = n.value;
+            if (v != null && n.casValue(v, value))
+                return (V)v;
         }
     }
 
@@ -2101,7 +2038,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public K lowerKey(K key) {
-        Node<K,V> n = findNear(key, LT, comparator);
+        Node<K,V> n = findNear(key, LT);
         return (n == null) ? null : n.key;
     }
 
@@ -2125,7 +2062,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public K floorKey(K key) {
-        Node<K,V> n = findNear(key, LT|EQ, comparator);
+        Node<K,V> n = findNear(key, LT|EQ);
         return (n == null) ? null : n.key;
     }
 
@@ -2147,7 +2084,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public K ceilingKey(K key) {
-        Node<K,V> n = findNear(key, GT|EQ, comparator);
+        Node<K,V> n = findNear(key, GT|EQ);
         return (n == null) ? null : n.key;
     }
 
@@ -2171,7 +2108,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public K higherKey(K key) {
-        Node<K,V> n = findNear(key, GT, comparator);
+        Node<K,V> n = findNear(key, GT);
         return (n == null) ? null : n.key;
     }
 
@@ -2245,11 +2182,13 @@
 
         /** Initializes ascending iterator for entire range. */
         Iter() {
-            while ((next = findFirst()) != null) {
+            for (;;) {
+                next = findFirst();
+                if (next == null)
+                    break;
                 Object x = next.value;
                 if (x != null && x != next) {
-                    @SuppressWarnings("unchecked") V vv = (V)x;
-                    nextValue = vv;
+                    nextValue = (V) x;
                     break;
                 }
             }
@@ -2264,11 +2203,13 @@
             if (next == null)
                 throw new NoSuchElementException();
             lastReturned = next;
-            while ((next = next.next) != null) {
+            for (;;) {
+                next = next.next;
+                if (next == null)
+                    break;
                 Object x = next.value;
                 if (x != null && x != next) {
-                    @SuppressWarnings("unchecked") V vv = (V)x;
-                    nextValue = vv;
+                    nextValue = (V) x;
                     break;
                 }
             }
@@ -2311,6 +2252,20 @@
         }
     }
 
+    // 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 -------------- */
 
     /*
@@ -2327,34 +2282,35 @@
         return list;
     }
 
-    static final class KeySet<K,V>
-            extends AbstractSet<K> implements NavigableSet<K> {
-        final ConcurrentNavigableMap<K,V> m;
-        KeySet(ConcurrentNavigableMap<K,V> map) { m = map; }
+    static final class KeySet<E>
+            extends AbstractSet<E> implements NavigableSet<E> {
+        private final ConcurrentNavigableMap<E,?> m;
+        KeySet(ConcurrentNavigableMap<E,?> 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 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();
+        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();
             return (e == null) ? null : e.getKey();
         }
-        public K pollLast() {
-            Map.Entry<K,V> e = m.pollLastEntry();
+        public E pollLast() {
+            Map.Entry<E,?> e = m.pollLastEntry();
             return (e == null) ? null : e.getKey();
         }
-        public Iterator<K> iterator() {
-            return (m instanceof ConcurrentSkipListMap)
-                ? ((ConcurrentSkipListMap<K,V>)m).new KeyIterator()
-                : ((SubMap<K,V>)m).new SubMapKeyIterator();
+        public Iterator<E> iterator() {
+            if (m instanceof ConcurrentSkipListMap)
+                return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
+            else
+                return ((ConcurrentSkipListMap.SubMap<E,Object>)m).keyIterator();
         }
         public boolean equals(Object o) {
             if (o == this)
@@ -2372,99 +2328,81 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-        public Iterator<K> descendingIterator() {
+        public Iterator<E> descendingIterator() {
             return descendingSet().iterator();
         }
-        public NavigableSet<K> subSet(K fromElement,
+        public NavigableSet<E> subSet(E fromElement,
                                       boolean fromInclusive,
-                                      K toElement,
+                                      E toElement,
                                       boolean toInclusive) {
-            return new KeySet<>(m.subMap(fromElement, fromInclusive,
-                                         toElement,   toInclusive));
+            return new KeySet<E>(m.subMap(fromElement, fromInclusive,
+                                          toElement,   toInclusive));
         }
-        public NavigableSet<K> headSet(K toElement, boolean inclusive) {
-            return new KeySet<>(m.headMap(toElement, inclusive));
+        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+            return new KeySet<E>(m.headMap(toElement, inclusive));
         }
-        public NavigableSet<K> tailSet(K fromElement, boolean inclusive) {
-            return new KeySet<>(m.tailMap(fromElement, inclusive));
+        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+            return new KeySet<E>(m.tailMap(fromElement, inclusive));
         }
-        public NavigableSet<K> subSet(K fromElement, K toElement) {
+        public NavigableSet<E> subSet(E fromElement, E toElement) {
             return subSet(fromElement, true, toElement, false);
         }
-        public NavigableSet<K> headSet(K toElement) {
+        public NavigableSet<E> headSet(E toElement) {
             return headSet(toElement, false);
         }
-        public NavigableSet<K> tailSet(K fromElement) {
+        public NavigableSet<E> tailSet(E fromElement) {
             return tailSet(fromElement, true);
         }
-        public NavigableSet<K> descendingSet() {
-            return new KeySet<>(m.descendingMap());
-        }
-
-        public Spliterator<K> spliterator() {
-            return (m instanceof ConcurrentSkipListMap)
-                ? ((ConcurrentSkipListMap<K,V>)m).keySpliterator()
-                : ((SubMap<K,V>)m).new SubMapKeyIterator();
+        public NavigableSet<E> descendingSet() {
+            return new KeySet<E>(m.descendingMap());
         }
     }
 
-    static final class Values<K,V> extends AbstractCollection<V> {
-        final ConcurrentNavigableMap<K,V> m;
-        Values(ConcurrentNavigableMap<K,V> map) {
+    static final class Values<E> extends AbstractCollection<E> {
+        private final ConcurrentNavigableMap<?,E> m;
+        Values(ConcurrentNavigableMap<?,E> map) {
             m = map;
         }
-        public Iterator<V> iterator() {
-            return (m instanceof ConcurrentSkipListMap)
-                ? ((ConcurrentSkipListMap<K,V>)m).new ValueIterator()
-                : ((SubMap<K,V>)m).new SubMapValueIterator();
+        public Iterator<E> iterator() {
+            if (m instanceof ConcurrentSkipListMap)
+                return ((ConcurrentSkipListMap<?,E>)m).valueIterator();
+            else
+                return ((SubMap<?,E>)m).valueIterator();
         }
-        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 boolean isEmpty() {
+            return m.isEmpty();
+        }
+        public int size() {
+            return m.size();
+        }
+        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); }
-
-        public Spliterator<V> spliterator() {
-            return (m instanceof ConcurrentSkipListMap)
-                ? ((ConcurrentSkipListMap<K,V>)m).valueSpliterator()
-                : ((SubMap<K,V>)m).new SubMapValueIterator();
-        }
-
-        public boolean removeIf(Predicate<? super V> filter) {
-            if (filter == null) throw new NullPointerException();
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<K,V>)m).removeValueIf(filter);
-            // else use iterator
-            Iterator<Map.Entry<K,V>> it =
-                ((SubMap<K,V>)m).new SubMapEntryIterator();
-            boolean removed = false;
-            while (it.hasNext()) {
-                Map.Entry<K,V> e = it.next();
-                V v = e.getValue();
-                if (filter.test(v) && m.remove(e.getKey(), v))
-                    removed = true;
-            }
-            return removed;
-        }
     }
 
-    static final class EntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> {
-        final ConcurrentNavigableMap<K,V> m;
-        EntrySet(ConcurrentNavigableMap<K,V> map) {
+    static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
+        private final ConcurrentNavigableMap<K1, V1> m;
+        EntrySet(ConcurrentNavigableMap<K1, V1> map) {
             m = map;
         }
-        public Iterator<Map.Entry<K,V>> iterator() {
-            return (m instanceof ConcurrentSkipListMap)
-                ? ((ConcurrentSkipListMap<K,V>)m).new EntryIterator()
-                : ((SubMap<K,V>)m).new SubMapEntryIterator();
+
+        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 boolean contains(Object o) {
             if (!(o instanceof Map.Entry))
                 return false;
             Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-            V v = m.get(e.getKey());
+            V1 v = m.get(e.getKey());
             return v != null && v.equals(e.getValue());
         }
         public boolean remove(Object o) {
@@ -2499,47 +2437,27 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-
-        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<K,V>> filter) {
-            if (filter == null) throw new NullPointerException();
-            if (m instanceof ConcurrentSkipListMap)
-                return ((ConcurrentSkipListMap<K,V>)m).removeEntryIf(filter);
-            // else use iterator
-            Iterator<Map.Entry<K,V>> it =
-                ((SubMap<K,V>)m).new SubMapEntryIterator();
-            boolean removed = false;
-            while (it.hasNext()) {
-                Map.Entry<K,V> e = it.next();
-                if (filter.test(e) && m.remove(e.getKey(), e.getValue()))
-                    removed = true;
-            }
-            return removed;
-        }
     }
 
     /**
      * 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
      */
     static final class SubMap<K,V> extends AbstractMap<K,V>
-        implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {
+        implements ConcurrentNavigableMap<K,V>, Cloneable,
+                   java.io.Serializable {
         private static final long serialVersionUID = -7647078645895051609L;
 
         /** Underlying map */
-        final ConcurrentSkipListMap<K,V> m;
+        private 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 */
@@ -2549,10 +2467,10 @@
         /** inclusion flag for hi */
         private final boolean hiInclusive;
         /** direction */
-        final boolean isDescending;
+        private final boolean isDescending;
 
         // Lazily initialized view holders
-        private transient KeySet<K,V> keySetView;
+        private transient KeySet<K> keySetView;
         private transient Set<Map.Entry<K,V>> entrySetView;
         private transient Collection<V> valuesView;
 
@@ -2563,9 +2481,8 @@
                K fromKey, boolean fromInclusive,
                K toKey, boolean toInclusive,
                boolean isDescending) {
-            Comparator<? super K> cmp = map.comparator;
             if (fromKey != null && toKey != null &&
-                cpr(cmp, fromKey, toKey) > 0)
+                map.compare(fromKey, toKey) > 0)
                 throw new IllegalArgumentException("inconsistent range");
             this.m = map;
             this.lo = fromKey;
@@ -2577,34 +2494,39 @@
 
         /* ----------------  Utilities -------------- */
 
-        boolean tooLow(Object key, Comparator<? super K> cmp) {
-            int c;
-            return (lo != null && ((c = cpr(cmp, key, lo)) < 0 ||
-                                   (c == 0 && !loInclusive)));
+        private boolean tooLow(K key) {
+            if (lo != null) {
+                int c = m.compare(key, lo);
+                if (c < 0 || (c == 0 && !loInclusive))
+                    return true;
+            }
+            return false;
         }
 
-        boolean tooHigh(Object key, Comparator<? super K> cmp) {
-            int c;
-            return (hi != null && ((c = cpr(cmp, key, hi)) > 0 ||
-                                   (c == 0 && !hiInclusive)));
+        private boolean tooHigh(K key) {
+            if (hi != null) {
+                int c = m.compare(key, hi);
+                if (c > 0 || (c == 0 && !hiInclusive))
+                    return true;
+            }
+            return false;
         }
 
-        boolean inBounds(Object key, Comparator<? super K> cmp) {
-            return !tooLow(key, cmp) && !tooHigh(key, cmp);
+        private boolean inBounds(K key) {
+            return !tooLow(key) && !tooHigh(key);
         }
 
-        void checkKeyBounds(K key, Comparator<? super K> cmp) {
+        private void checkKeyBounds(K key) throws IllegalArgumentException {
             if (key == null)
                 throw new NullPointerException();
-            if (!inBounds(key, cmp))
+            if (!inBounds(key))
                 throw new IllegalArgumentException("key out of range");
         }
 
         /**
          * Returns true if node key is less than upper bound of range.
          */
-        boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n,
-                            Comparator<? super K> cmp) {
+        private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
             if (n == null)
                 return false;
             if (hi == null)
@@ -2612,7 +2534,7 @@
             K k = n.key;
             if (k == null) // pass by markers and headers
                 return true;
-            int c = cpr(cmp, k, hi);
+            int c = m.compare(k, hi);
             if (c > 0 || (c == 0 && !hiInclusive))
                 return false;
             return true;
@@ -2622,35 +2544,34 @@
          * Returns lowest node. This node might not be in range, so
          * most usages need to check bounds.
          */
-        ConcurrentSkipListMap.Node<K,V> loNode(Comparator<? super K> cmp) {
+        private ConcurrentSkipListMap.Node<K,V> loNode() {
             if (lo == null)
                 return m.findFirst();
             else if (loInclusive)
-                return m.findNear(lo, GT|EQ, cmp);
+                return m.findNear(lo, GT|EQ);
             else
-                return m.findNear(lo, GT, cmp);
+                return m.findNear(lo, GT);
         }
 
         /**
          * Returns highest node. This node might not be in range, so
          * most usages need to check bounds.
          */
-        ConcurrentSkipListMap.Node<K,V> hiNode(Comparator<? super K> cmp) {
+        private ConcurrentSkipListMap.Node<K,V> hiNode() {
             if (hi == null)
                 return m.findLast();
             else if (hiInclusive)
-                return m.findNear(hi, LT|EQ, cmp);
+                return m.findNear(hi, LT|EQ);
             else
-                return m.findNear(hi, LT, cmp);
+                return m.findNear(hi, LT);
         }
 
         /**
          * Returns lowest absolute key (ignoring directionality).
          */
-        K lowestKey() {
-            Comparator<? super K> cmp = m.comparator;
-            ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-            if (isBeforeEnd(n, cmp))
+        private K lowestKey() {
+            ConcurrentSkipListMap.Node<K,V> n = loNode();
+            if (isBeforeEnd(n))
                 return n.key;
             else
                 throw new NoSuchElementException();
@@ -2659,22 +2580,20 @@
         /**
          * Returns highest absolute key (ignoring directionality).
          */
-        K highestKey() {
-            Comparator<? super K> cmp = m.comparator;
-            ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
+        private K highestKey() {
+            ConcurrentSkipListMap.Node<K,V> n = hiNode();
             if (n != null) {
                 K last = n.key;
-                if (inBounds(last, cmp))
+                if (inBounds(last))
                     return last;
             }
             throw new NoSuchElementException();
         }
 
-        Map.Entry<K,V> lowestEntry() {
-            Comparator<? super K> cmp = m.comparator;
+        private Map.Entry<K,V> lowestEntry() {
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                if (!isBeforeEnd(n, cmp))
+                ConcurrentSkipListMap.Node<K,V> n = loNode();
+                if (!isBeforeEnd(n))
                     return null;
                 Map.Entry<K,V> e = n.createSnapshot();
                 if (e != null)
@@ -2682,11 +2601,10 @@
             }
         }
 
-        Map.Entry<K,V> highestEntry() {
-            Comparator<? super K> cmp = m.comparator;
+        private Map.Entry<K,V> highestEntry() {
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
-                if (n == null || !inBounds(n.key, cmp))
+                ConcurrentSkipListMap.Node<K,V> n = hiNode();
+                if (n == null || !inBounds(n.key))
                     return null;
                 Map.Entry<K,V> e = n.createSnapshot();
                 if (e != null)
@@ -2694,14 +2612,13 @@
             }
         }
 
-        Map.Entry<K,V> removeLowest() {
-            Comparator<? super K> cmp = m.comparator;
+        private Map.Entry<K,V> removeLowest() {
             for (;;) {
-                Node<K,V> n = loNode(cmp);
+                Node<K,V> n = loNode();
                 if (n == null)
                     return null;
                 K k = n.key;
-                if (!inBounds(k, cmp))
+                if (!inBounds(k))
                     return null;
                 V v = m.doRemove(k, null);
                 if (v != null)
@@ -2709,14 +2626,13 @@
             }
         }
 
-        Map.Entry<K,V> removeHighest() {
-            Comparator<? super K> cmp = m.comparator;
+        private Map.Entry<K,V> removeHighest() {
             for (;;) {
-                Node<K,V> n = hiNode(cmp);
+                Node<K,V> n = hiNode();
                 if (n == null)
                     return null;
                 K k = n.key;
-                if (!inBounds(k, cmp))
+                if (!inBounds(k))
                     return null;
                 V v = m.doRemove(k, null);
                 if (v != null)
@@ -2725,23 +2641,22 @@
         }
 
         /**
-         * 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;
+        private Map.Entry<K,V> getNearEntry(K key, int rel) {
             if (isDescending) { // adjust relation for direction
                 if ((rel & LT) == 0)
                     rel |= LT;
                 else
                     rel &= ~LT;
             }
-            if (tooLow(key, cmp))
+            if (tooLow(key))
                 return ((rel & LT) != 0) ? null : lowestEntry();
-            if (tooHigh(key, cmp))
+            if (tooHigh(key))
                 return ((rel & LT) != 0) ? highestEntry() : null;
             for (;;) {
-                Node<K,V> n = m.findNear(key, rel, cmp);
-                if (n == null || !inBounds(n.key, cmp))
+                Node<K,V> n = m.findNear(key, rel);
+                if (n == null || !inBounds(n.key))
                     return null;
                 K k = n.key;
                 V v = n.getValidValue();
@@ -2751,36 +2666,35 @@
         }
 
         // Almost the same as getNearEntry, except for keys
-        K getNearKey(K key, int rel) {
-            Comparator<? super K> cmp = m.comparator;
+        private K getNearKey(K key, int rel) {
             if (isDescending) { // adjust relation for direction
                 if ((rel & LT) == 0)
                     rel |= LT;
                 else
                     rel &= ~LT;
             }
-            if (tooLow(key, cmp)) {
+            if (tooLow(key)) {
                 if ((rel & LT) == 0) {
-                    ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                    if (isBeforeEnd(n, cmp))
+                    ConcurrentSkipListMap.Node<K,V> n = loNode();
+                    if (isBeforeEnd(n))
                         return n.key;
                 }
                 return null;
             }
-            if (tooHigh(key, cmp)) {
+            if (tooHigh(key)) {
                 if ((rel & LT) != 0) {
-                    ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
+                    ConcurrentSkipListMap.Node<K,V> n = hiNode();
                     if (n != null) {
                         K last = n.key;
-                        if (inBounds(last, cmp))
+                        if (inBounds(last))
                             return last;
                     }
                 }
                 return null;
             }
             for (;;) {
-                Node<K,V> n = m.findNear(key, rel, cmp);
-                if (n == null || !inBounds(n.key, cmp))
+                Node<K,V> n = m.findNear(key, rel);
+                if (n == null || !inBounds(n.key))
                     return null;
                 K k = n.key;
                 V v = n.getValidValue();
@@ -2793,28 +2707,30 @@
 
         public boolean containsKey(Object key) {
             if (key == null) throw new NullPointerException();
-            return inBounds(key, m.comparator) && m.containsKey(key);
+            K k = (K)key;
+            return inBounds(k) && m.containsKey(k);
         }
 
         public V get(Object key) {
             if (key == null) throw new NullPointerException();
-            return (!inBounds(key, m.comparator)) ? null : m.get(key);
+            K k = (K)key;
+            return (!inBounds(k)) ? null : m.get(k);
         }
 
         public V put(K key, V value) {
-            checkKeyBounds(key, m.comparator);
+            checkKeyBounds(key);
             return m.put(key, value);
         }
 
         public V remove(Object key) {
-            return (!inBounds(key, m.comparator)) ? null : m.remove(key);
+            K k = (K)key;
+            return (!inBounds(k)) ? null : m.remove(k);
         }
 
         public int size() {
-            Comparator<? super K> cmp = m.comparator;
             long count = 0;
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                 isBeforeEnd(n, cmp);
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+                 isBeforeEnd(n);
                  n = n.next) {
                 if (n.getValidValue() != null)
                     ++count;
@@ -2823,16 +2739,14 @@
         }
 
         public boolean isEmpty() {
-            Comparator<? super K> cmp = m.comparator;
-            return !isBeforeEnd(loNode(cmp), cmp);
+            return !isBeforeEnd(loNode());
         }
 
         public boolean containsValue(Object value) {
             if (value == null)
                 throw new NullPointerException();
-            Comparator<? super K> cmp = m.comparator;
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                 isBeforeEnd(n, cmp);
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+                 isBeforeEnd(n);
                  n = n.next) {
                 V v = n.getValidValue();
                 if (v != null && value.equals(v))
@@ -2842,9 +2756,8 @@
         }
 
         public void clear() {
-            Comparator<? super K> cmp = m.comparator;
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                 isBeforeEnd(n, cmp);
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+                 isBeforeEnd(n);
                  n = n.next) {
                 if (n.getValidValue() != null)
                     m.remove(n.key);
@@ -2854,21 +2767,22 @@
         /* ----------------  ConcurrentMap API methods -------------- */
 
         public V putIfAbsent(K key, V value) {
-            checkKeyBounds(key, m.comparator);
+            checkKeyBounds(key);
             return m.putIfAbsent(key, value);
         }
 
         public boolean remove(Object key, Object value) {
-            return inBounds(key, m.comparator) && m.remove(key, value);
+            K k = (K)key;
+            return inBounds(k) && m.remove(k, value);
         }
 
         public boolean replace(K key, V oldValue, V newValue) {
-            checkKeyBounds(key, m.comparator);
+            checkKeyBounds(key);
             return m.replace(key, oldValue, newValue);
         }
 
         public V replace(K key, V value) {
-            checkKeyBounds(key, m.comparator);
+            checkKeyBounds(key);
             return m.replace(key, value);
         }
 
@@ -2886,9 +2800,10 @@
          * Utility to create submaps, where given bounds override
          * unbounded(null) ones and/or are checked against bounded ones.
          */
-        SubMap<K,V> newSubMap(K fromKey, boolean fromInclusive,
-                              K toKey, boolean toInclusive) {
-            Comparator<? super K> cmp = m.comparator;
+        private SubMap<K,V> newSubMap(K fromKey,
+                                      boolean fromInclusive,
+                                      K toKey,
+                                      boolean toInclusive) {
             if (isDescending) { // flip senses
                 K tk = fromKey;
                 fromKey = toKey;
@@ -2903,7 +2818,7 @@
                     fromInclusive = loInclusive;
                 }
                 else {
-                    int c = cpr(cmp, fromKey, lo);
+                    int c = m.compare(fromKey, lo);
                     if (c < 0 || (c == 0 && !loInclusive && fromInclusive))
                         throw new IllegalArgumentException("key out of range");
                 }
@@ -2914,7 +2829,7 @@
                     toInclusive = hiInclusive;
                 }
                 else {
-                    int c = cpr(cmp, toKey, hi);
+                    int c = m.compare(toKey, hi);
                     if (c > 0 || (c == 0 && !hiInclusive && toInclusive))
                         throw new IllegalArgumentException("key out of range");
                 }
@@ -2923,20 +2838,24 @@
                                    toKey, toInclusive, isDescending);
         }
 
-        public SubMap<K,V> subMap(K fromKey, boolean fromInclusive,
-                                  K toKey, boolean toInclusive) {
+        public SubMap<K,V> subMap(K fromKey,
+                                  boolean fromInclusive,
+                                  K toKey,
+                                  boolean toInclusive) {
             if (fromKey == null || toKey == null)
                 throw new NullPointerException();
             return newSubMap(fromKey, fromInclusive, toKey, toInclusive);
         }
 
-        public SubMap<K,V> headMap(K toKey, boolean inclusive) {
+        public SubMap<K,V> headMap(K toKey,
+                                   boolean inclusive) {
             if (toKey == null)
                 throw new NullPointerException();
             return newSubMap(null, false, toKey, inclusive);
         }
 
-        public SubMap<K,V> tailMap(K fromKey, boolean inclusive) {
+        public SubMap<K,V> tailMap(K fromKey,
+                                   boolean inclusive) {
             if (fromKey == null)
                 throw new NullPointerException();
             return newSubMap(fromKey, inclusive, null, false);
@@ -3020,18 +2939,18 @@
         /* ---------------- Submap Views -------------- */
 
         public NavigableSet<K> keySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K> ks = keySetView;
+            return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
         }
 
         public NavigableSet<K> navigableKeySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K> ks = keySetView;
+            return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
         }
 
         public Collection<V> values() {
             Collection<V> vs = valuesView;
-            return (vs != null) ? vs : (valuesView = new Values<>(this));
+            return (vs != null) ? vs : (valuesView = new Values<V>(this));
         }
 
         public Set<Map.Entry<K,V>> entrySet() {
@@ -3043,11 +2962,22 @@
             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.
          */
-        abstract class SubMapIter<T> implements Iterator<T>, Spliterator<T> {
+        abstract class SubMapIter<T> implements Iterator<T> {
             /** the last node returned by next() */
             Node<K,V> lastReturned;
             /** the next node to return from next(); */
@@ -3056,19 +2986,16 @@
             V nextValue;
 
             SubMapIter() {
-                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
-                    next = isDescending ? hiNode(cmp) : loNode(cmp);
+                    next = isDescending ? hiNode() : loNode();
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (! inBounds(next.key, cmp))
+                        if (! inBounds(next.key))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = (V) x;
                         break;
                     }
                 }
@@ -3089,38 +3016,32 @@
             }
 
             private void ascend() {
-                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
                     next = next.next;
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (tooHigh(next.key, cmp))
+                        if (tooHigh(next.key))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = (V) x;
                         break;
                     }
                 }
             }
 
             private void descend() {
-                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
-                    next = m.findNear(lastReturned.key, LT, cmp);
+                    next = m.findNear(lastReturned.key, LT);
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (tooLow(next.key, cmp))
+                        if (tooLow(next.key))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = (V) x;
                         break;
                     }
                 }
@@ -3134,27 +3055,6 @@
                 lastReturned = null;
             }
 
-            public Spliterator<T> trySplit() {
-                return null;
-            }
-
-            public boolean tryAdvance(Consumer<? super T> action) {
-                if (hasNext()) {
-                    action.accept(next());
-                    return true;
-                }
-                return false;
-            }
-
-            public void forEachRemaining(Consumer<? super T> action) {
-                while (hasNext())
-                    action.accept(next());
-            }
-
-            public long estimateSize() {
-                return Long.MAX_VALUE;
-            }
-
         }
 
         final class SubMapValueIterator extends SubMapIter<V> {
@@ -3163,9 +3063,6 @@
                 advance();
                 return v;
             }
-            public int characteristics() {
-                return 0;
-            }
         }
 
         final class SubMapKeyIterator extends SubMapIter<K> {
@@ -3174,13 +3071,6 @@
                 advance();
                 return n.key;
             }
-            public int characteristics() {
-                return Spliterator.DISTINCT | Spliterator.ORDERED |
-                    Spliterator.SORTED;
-            }
-            public final Comparator<? super K> getComparator() {
-                return SubMap.this.comparator();
-            }
         }
 
         final class SubMapEntryIterator extends SubMapIter<Map.Entry<K,V>> {
@@ -3190,390 +3080,19 @@
                 advance();
                 return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
             }
-            public int characteristics() {
-                return Spliterator.DISTINCT;
-            }
-        }
-    }
-
-    // default Map method overrides
-
-    public void forEach(BiConsumer<? super K, ? super V> action) {
-        if (action == null) throw new NullPointerException();
-        V v;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            if ((v = n.getValidValue()) != null)
-                action.accept(n.key, v);
-        }
-    }
-
-    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-        if (function == null) throw new NullPointerException();
-        V v;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            while ((v = n.getValidValue()) != null) {
-                V r = function.apply(n.key, v);
-                if (r == null) throw new NullPointerException();
-                if (n.casValue(v, r))
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Helper method for EntrySet.removeIf.
-     */
-    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) {
-            V v;
-            if ((v = n.getValidValue()) != null) {
-                K k = n.key;
-                Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
-                if (function.test(e) && remove(k, v))
-                    removed = true;
-            }
-        }
-        return removed;
-    }
-
-    /**
-     * Helper method for Values.removeIf.
-     */
-    boolean removeValueIf(Predicate<? super V> function) {
-        if (function == null) throw new NullPointerException();
-        boolean removed = false;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            V v;
-            if ((v = n.getValidValue()) != null) {
-                K k = n.key;
-                if (function.test(v) && remove(k, v))
-                    removed = true;
-            }
-        }
-        return removed;
-    }
-
-    /**
-     * Base class providing common structure for Spliterators.
-     * (Although not all that much common functionality; as usual for
-     * view classes, details annoyingly vary in key, value, and entry
-     * subclasses in ways that are not worth abstracting out for
-     * internal classes.)
-     *
-     * The basic split strategy is to recursively descend from top
-     * level, row by row, descending to next row when either split
-     * off, or the end of row is encountered. Control of the number of
-     * splits relies on some statistical estimation: The expected
-     * remaining number of elements of a skip list when advancing
-     * either across or down decreases by about 25%. To make this
-     * observation useful, we need to know initial size, which we
-     * don't. But we can just use Integer.MAX_VALUE so that we
-     * don't prematurely zero out while splitting.
-     */
-    abstract static class CSLMSpliterator<K,V> {
-        final Comparator<? super K> comparator;
-        final K fence;     // exclusive upper bound for keys, or null if to end
-        Index<K,V> row;    // the level to split out
-        Node<K,V> current; // current traversal node; initialize at origin
-        int est;           // pseudo-size estimate
-        CSLMSpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                        Node<K,V> origin, K fence, int est) {
-            this.comparator = comparator; this.row = row;
-            this.current = origin; this.fence = fence; this.est = est;
-        }
-
-        public final long estimateSize() { return (long)est; }
-    }
-
-    static final class KeySpliterator<K,V> extends CSLMSpliterator<K,V>
-        implements Spliterator<K> {
-        KeySpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                       Node<K,V> origin, K fence, int est) {
-            super(comparator, row, origin, fence, est);
-        }
-
-        public KeySpliterator<K,V> trySplit() {
-            Node<K,V> e; K ek;
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            if ((e = current) != null && (ek = e.key) != null) {
-                for (Index<K,V> q = row; q != null; q = row = q.down) {
-                    Index<K,V> s; Node<K,V> b, n; K sk;
-                    if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
-                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
-                        (f == null || cpr(cmp, sk, f) < 0)) {
-                        current = n;
-                        Index<K,V> r = q.down;
-                        row = (s.right != null) ? s : s.down;
-                        est -= est >>> 2;
-                        return new KeySpliterator<K,V>(cmp, r, e, sk, est);
-                    }
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            current = null;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
-                    break;
-                if ((v = e.value) != null && v != e)
-                    action.accept(k);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
-                    e = null;
-                    break;
-                }
-                if ((v = e.value) != null && v != e) {
-                    current = e.next;
-                    action.accept(k);
-                    return true;
-                }
-            }
-            current = e;
-            return false;
-        }
-
-        public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.SORTED |
-                Spliterator.ORDERED | Spliterator.CONCURRENT |
-                Spliterator.NONNULL;
-        }
-
-        public final Comparator<? super K> getComparator() {
-            return comparator;
-        }
-    }
-    // factory method for KeySpliterator
-    final KeySpliterator<K,V> keySpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) { // ensure h corresponds to origin p
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new KeySpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                               0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
-        }
-    }
-
-    static final class ValueSpliterator<K,V> extends CSLMSpliterator<K,V>
-        implements Spliterator<V> {
-        ValueSpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                       Node<K,V> origin, K fence, int est) {
-            super(comparator, row, origin, fence, est);
-        }
-
-        public ValueSpliterator<K,V> trySplit() {
-            Node<K,V> e; K ek;
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            if ((e = current) != null && (ek = e.key) != null) {
-                for (Index<K,V> q = row; q != null; q = row = q.down) {
-                    Index<K,V> s; Node<K,V> b, n; K sk;
-                    if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
-                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
-                        (f == null || cpr(cmp, sk, f) < 0)) {
-                        current = n;
-                        Index<K,V> r = q.down;
-                        row = (s.right != null) ? s : s.down;
-                        est -= est >>> 2;
-                        return new ValueSpliterator<K,V>(cmp, r, e, sk, est);
-                    }
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            current = null;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
-                    break;
-                if ((v = e.value) != null && v != e) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept(vv);
-                }
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
-                    e = null;
-                    break;
-                }
-                if ((v = e.value) != null && v != e) {
-                    current = e.next;
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept(vv);
-                    return true;
-                }
-            }
-            current = e;
-            return false;
-        }
-
-        public int characteristics() {
-            return Spliterator.CONCURRENT | Spliterator.ORDERED |
-                Spliterator.NONNULL;
-        }
-    }
-
-    // Almost the same as keySpliterator()
-    final ValueSpliterator<K,V> valueSpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) {
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new ValueSpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                                 0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
-        }
-    }
-
-    static final class EntrySpliterator<K,V> extends CSLMSpliterator<K,V>
-        implements Spliterator<Map.Entry<K,V>> {
-        EntrySpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                         Node<K,V> origin, K fence, int est) {
-            super(comparator, row, origin, fence, est);
-        }
-
-        public EntrySpliterator<K,V> trySplit() {
-            Node<K,V> e; K ek;
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            if ((e = current) != null && (ek = e.key) != null) {
-                for (Index<K,V> q = row; q != null; q = row = q.down) {
-                    Index<K,V> s; Node<K,V> b, n; K sk;
-                    if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
-                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
-                        (f == null || cpr(cmp, sk, f) < 0)) {
-                        current = n;
-                        Index<K,V> r = q.down;
-                        row = (s.right != null) ? s : s.down;
-                        est -= est >>> 2;
-                        return new EntrySpliterator<K,V>(cmp, r, e, sk, est);
-                    }
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            current = null;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
-                    break;
-                if ((v = e.value) != null && v != e) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept
-                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
-                }
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
-            if (action == null) throw new NullPointerException();
-            Comparator<? super K> cmp = comparator;
-            K f = fence;
-            Node<K,V> e = current;
-            for (; e != null; e = e.next) {
-                K k; Object v;
-                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
-                    e = null;
-                    break;
-                }
-                if ((v = e.value) != null && v != e) {
-                    current = e.next;
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept
-                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
-                    return true;
-                }
-            }
-            current = e;
-            return false;
-        }
-
-        public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.SORTED |
-                Spliterator.ORDERED | Spliterator.CONCURRENT |
-                Spliterator.NONNULL;
-        }
-
-        public final Comparator<Map.Entry<K,V>> getComparator() {
-            // Adapt or create a key-based comparator
-            if (comparator != null) {
-                return Map.Entry.comparingByKey(comparator);
-            }
-            else {
-                return (Comparator<Map.Entry<K,V>> & Serializable) (e1, e2) -> {
-                    @SuppressWarnings("unchecked")
-                    Comparable<? super K> k1 = (Comparable<? super K>) e1.getKey();
-                    return k1.compareTo(e2.getKey());
-                };
-            }
-        }
-    }
-
-    // Almost the same as keySpliterator()
-    final EntrySpliterator<K,V> entrySpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) { // almost same as key version
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new EntrySpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                                 0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
         }
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long headOffset;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentSkipListMap.class.getDeclaredField("head"));
-        } catch (ReflectiveOperationException e) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ConcurrentSkipListMap.class;
+            headOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("head"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
index 1719822..13f1a43 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -6,21 +6,10 @@
 
 package java.util.concurrent;
 
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.Spliterator;
+import java.util.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
 // END android-note
 
 /**
@@ -34,12 +23,12 @@
  * cost for the {@code contains}, {@code add}, and {@code remove}
  * operations and their variants.  Insertion, removal, and access
  * operations safely execute concurrently by multiple threads.
- *
- * <p>Iterators and spliterators are
- * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
- *
- * <p>Ascending ordered views and their iterators are faster than
- * descending ones.
+ * Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the set at some point at or since the
+ * creation of the iterator.  They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations.  Ascending ordered views and their iterators are
+ * faster than descending ones.
  *
  * <p>Beware that, unlike in most collections, the {@code size}
  * method is <em>not</em> a constant-time operation. Because of the
@@ -296,9 +285,8 @@
      *
      * @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
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * @throws ClassCastException if the types of one or more elements in this
+     *         set are incompatible with the specified collection
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
      */
@@ -358,19 +346,20 @@
 
     /* ---------------- SortedSet operations -------------- */
 
+
     public Comparator<? super E> comparator() {
         return m.comparator();
     }
 
     /**
-     * @throws java.util.NoSuchElementException {@inheritDoc}
+     * @throws NoSuchElementException {@inheritDoc}
      */
     public E first() {
         return m.firstKey();
     }
 
     /**
-     * @throws java.util.NoSuchElementException {@inheritDoc}
+     * @throws NoSuchElementException {@inheritDoc}
      */
     public E last() {
         return m.lastKey();
@@ -453,42 +442,20 @@
         return new ConcurrentSkipListSet<E>(m.descendingMap());
     }
 
-    /**
-     * Returns a {@link Spliterator} over the elements in this set.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#NONNULL}, {@link Spliterator#DISTINCT},
-     * {@link Spliterator#SORTED} and {@link Spliterator#ORDERED}, with an
-     * encounter order that is ascending order.  Overriding implementations
-     * should document the reporting of additional characteristic values.
-     *
-     * <p>The spliterator's comparator (see
-     * {@link java.util.Spliterator#getComparator()}) is {@code null} if
-     * the set's comparator (see {@link #comparator()}) is {@code null}.
-     * Otherwise, the spliterator's comparator is the same as or imposes the
-     * same total ordering as the set's comparator.
-     *
-     * @return a {@code Spliterator} over the elements in this set
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        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) {
-        U.putObjectVolatile(this, MAP, map);
+        UNSAFE.putObjectVolatile(this, mapOffset, map);
     }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long MAP;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long mapOffset;
     static {
         try {
-            MAP = U.objectFieldOffset
-                (ConcurrentSkipListSet.class.getDeclaredField("m"));
-        } catch (ReflectiveOperationException e) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ConcurrentSkipListSet.class;
+            mapOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("m"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java b/luni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
index c8e342e..798eaaf 100644
--- a/luni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/luni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
@@ -1,1542 +1,783 @@
 /*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group.  Adapted and released, under explicit permission,
- * from JDK ArrayList.java which carries the following copyright:
+ * Copyright (C) 2010 The Android Open Source Project
  *
- * Copyright 1997 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information").  You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package java.util.concurrent;
 
-
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Comparator;
 import java.util.ConcurrentModificationException;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
-import java.util.Objects;
 import java.util.RandomAccess;
-import java.util.Spliterator;
-import java.util.Spliterators;
 import java.util.function.Consumer;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import libcore.util.EmptyArray;
 
-// BEGIN android-note
-// removed link to collections framework docs from header
-// END android-note
+import libcore.util.EmptyArray;
+import libcore.util.Objects;
 
 /**
- * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
- * operations ({@code add}, {@code set}, and so on) are implemented by
- * making a fresh copy of the underlying array.
+ * A thread-safe random-access list.
  *
- * <p>This is ordinarily too costly, but may be <em>more</em> efficient
- * than alternatives when traversal operations vastly outnumber
- * mutations, and is useful when you cannot or don't want to
- * synchronize traversals, yet need to preclude interference among
- * concurrent threads.  The "snapshot" style iterator method uses a
- * reference to the state of the array at the point that the iterator
- * was created. This array never changes during the lifetime of the
- * iterator, so interference is impossible and the iterator is
- * guaranteed not to throw {@code ConcurrentModificationException}.
- * The iterator will not reflect additions, removals, or changes to
- * the list since the iterator was created.  Element-changing
- * operations on iterators themselves ({@code remove}, {@code set}, and
- * {@code add}) are not supported. These methods throw
- * {@code UnsupportedOperationException}.
+ * <p>Read operations (including {@link #get}) do not block and may overlap with
+ * update operations. Reads reflect the results of the most recently completed
+ * operations. Aggregate operations like {@link #addAll} and {@link #clear} are
+ * atomic; they never expose an intermediate state.
  *
- * <p>All elements are permitted, including {@code null}.
+ * <p>Iterators of this list never throw {@link
+ * ConcurrentModificationException}. When an iterator is created, it keeps a
+ * copy of the list's contents. It is always safe to iterate this list, but
+ * iterations may not reflect the latest state of the list.
  *
- * <p>Memory consistency effects: As with other concurrent
- * collections, actions in a thread prior to placing an object into a
- * {@code CopyOnWriteArrayList}
- * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
- * actions subsequent to the access or removal of that element from
- * the {@code CopyOnWriteArrayList} in another thread.
+ * <p>Iterators returned by this list and its sub lists cannot modify the
+ * underlying list. In particular, {@link Iterator#remove}, {@link
+ * ListIterator#add} and {@link ListIterator#set} all throw {@link
+ * UnsupportedOperationException}.
  *
- * @since 1.5
- * @author Doug Lea
- * @param <E> the type of elements held in this list
+ * <p>This class offers extended API beyond the {@link List} interface. It
+ * includes additional overloads for indexed search ({@link #indexOf} and {@link
+ * #lastIndexOf}) and methods for conditional adds ({@link #addIfAbsent} and
+ * {@link #addAllAbsent}).
  */
-public class CopyOnWriteArrayList<E>
-    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
+public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
+
     private static final long serialVersionUID = 8673264195747942595L;
 
     /**
-     * The lock protecting all mutators.  (We have a mild preference
-     * for builtin monitors over ReentrantLock when either will do.)
+     * Holds the latest snapshot of the list's data. This field is volatile so
+     * that data can be read without synchronization. As a consequence, all
+     * writes to this field must be atomic; it is an error to modify the
+     * contents of an array after it has been assigned to this field.
+     *
+     * Synchronization is required by all update operations. This defends
+     * against one update clobbering the result of another operation. For
+     * example, 100 threads simultaneously calling add() will grow the list's
+     * size by 100 when they have completed. No update operations are lost!
+     *
+     * Maintainers should be careful to read this field only once in
+     * non-blocking read methods. Write methods must be synchronized to avoid
+     * clobbering concurrent writes.
      */
-    final transient Object lock = new Object();
-
-    /** The array, accessed only via getArray/setArray. */
-    private transient volatile Object[] array;
+    private transient volatile Object[] elements;
 
     /**
-     * Gets the array.  Non-private so as to also be accessible
-     * from CopyOnWriteArraySet class.
-     */
-    final Object[] getArray() {
-        return array;
-    }
-
-    /**
-     * Sets the array.
-     */
-    final void setArray(Object[] a) {
-        array = a;
-    }
-
-    /**
-     * Creates an empty list.
+     * Creates a new empty instance.
      */
     public CopyOnWriteArrayList() {
-        setArray(new Object[0]);
+        elements = EmptyArray.OBJECT;
     }
 
     /**
-     * Creates a list containing the elements of the specified
-     * collection, in the order they are returned by the collection's
-     * iterator.
-     *
-     * @param c the collection of initially held elements
-     * @throws NullPointerException if the specified collection is null
+     * Creates a new instance containing the elements of {@code collection}.
      */
-    public CopyOnWriteArrayList(Collection<? extends E> c) {
-        Object[] elements;
-        if (c.getClass() == CopyOnWriteArrayList.class)
-            elements = ((CopyOnWriteArrayList<?>)c).getArray();
-        else {
-            elements = c.toArray();
-            // defend against c.toArray (incorrectly) not returning Object[]
-            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
-            if (elements.getClass() != Object[].class)
-                elements = Arrays.copyOf(elements, elements.length, Object[].class);
-        }
-        setArray(elements);
+    @SuppressWarnings("unchecked")
+    public CopyOnWriteArrayList(Collection<? extends E> collection) {
+        this((E[]) collection.toArray());
     }
 
     /**
-     * Creates a list holding a copy of the given array.
-     *
-     * @param toCopyIn the array (a copy of this array is used as the
-     *        internal array)
-     * @throws NullPointerException if the specified array is null
+     * Creates a new instance containing the elements of {@code array}.
      */
-    public CopyOnWriteArrayList(E[] toCopyIn) {
-        setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
+    public CopyOnWriteArrayList(E[] array) {
+        this.elements = Arrays.copyOf(array, array.length, Object[].class);
     }
 
-    /**
-     * Returns the number of elements in this list.
-     *
-     * @return the number of elements in this list
-     */
-    public int size() {
-        return getArray().length;
-    }
-
-    /**
-     * Returns {@code true} if this list contains no elements.
-     *
-     * @return {@code true} if this list contains no elements
-     */
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    /**
-     * static version of indexOf, to allow repeated calls without
-     * needing to re-acquire array each time.
-     * @param o element to search for
-     * @param elements the array
-     * @param index first index to search
-     * @param fence one past last index to search
-     * @return index of element, or -1 if absent
-     */
-    private static int indexOf(Object o, Object[] elements,
-                               int index, int fence) {
-        if (o == null) {
-            for (int i = index; i < fence; i++)
-                if (elements[i] == null)
-                    return i;
-        } else {
-            for (int i = index; i < fence; i++)
-                if (o.equals(elements[i]))
-                    return i;
-        }
-        return -1;
-    }
-
-    /**
-     * static version of lastIndexOf.
-     * @param o element to search for
-     * @param elements the array
-     * @param index first index to search
-     * @return index of element, or -1 if absent
-     */
-    private static int lastIndexOf(Object o, Object[] elements, int index) {
-        if (o == null) {
-            for (int i = index; i >= 0; i--)
-                if (elements[i] == null)
-                    return i;
-        } else {
-            for (int i = index; i >= 0; i--)
-                if (o.equals(elements[i]))
-                    return i;
-        }
-        return -1;
-    }
-
-    /**
-     * 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 {@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
-     */
-    public boolean contains(Object o) {
-        Object[] elements = getArray();
-        return indexOf(o, elements, 0, elements.length) >= 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int indexOf(Object o) {
-        Object[] elements = getArray();
-        return indexOf(o, elements, 0, elements.length);
-    }
-
-    /**
-     * Returns the index of the first occurrence of the specified element in
-     * 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
-     * {@code i >= index && Objects.equals(get(i), e)},
-     * or -1 if there is no such index.
-     *
-     * @param e element to search for
-     * @param index index to start searching from
-     * @return the index of the first occurrence of the element in
-     *         this list at position {@code index} or later in the list;
-     *         {@code -1} if the element is not found.
-     * @throws IndexOutOfBoundsException if the specified index is negative
-     */
-    public int indexOf(E e, int index) {
-        Object[] elements = getArray();
-        return indexOf(e, elements, index, elements.length);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int lastIndexOf(Object o) {
-        Object[] elements = getArray();
-        return lastIndexOf(o, elements, elements.length - 1);
-    }
-
-    /**
-     * Returns the index of the last occurrence of the specified element in
-     * 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
-     * {@code i <= index && Objects.equals(get(i), e)},
-     * or -1 if there is no such index.
-     *
-     * @param e element to search for
-     * @param index index to start searching backwards from
-     * @return the index of the last occurrence of the element at position
-     *         less than or equal to {@code index} in this list;
-     *         -1 if the element is not found.
-     * @throws IndexOutOfBoundsException if the specified index is greater
-     *         than or equal to the current size of this list
-     */
-    public int lastIndexOf(E e, int index) {
-        Object[] elements = getArray();
-        return lastIndexOf(e, elements, index);
-    }
-
-    /**
-     * Returns a shallow copy of this list.  (The elements themselves
-     * are not copied.)
-     *
-     * @return a clone of this list
-     */
-    public Object clone() {
+    @Override public Object clone() {
         try {
-            @SuppressWarnings("unchecked")
-            CopyOnWriteArrayList<E> clone =
-                (CopyOnWriteArrayList<E>) super.clone();
-            clone.resetLock();
-            return clone;
+            CopyOnWriteArrayList result = (CopyOnWriteArrayList) super.clone();
+            result.elements = result.elements.clone();
+            return result;
         } catch (CloneNotSupportedException e) {
-            // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
+            throw new AssertionError(e);
         }
     }
 
-    /**
-     * Returns an array containing all of the elements in this list
-     * in proper sequence (from first to last element).
-     *
-     * <p>The returned array will be "safe" in that no references to it are
-     * maintained by this list.  (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 the elements in this list
-     */
-    public Object[] toArray() {
-        Object[] elements = getArray();
-        return Arrays.copyOf(elements, elements.length);
+    public int size() {
+        return elements.length;
     }
 
-    /**
-     * Returns an array containing all of the elements in this list in
-     * proper sequence (from first to last element); the runtime type of
-     * the returned array is that of the specified array.  If the list 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 list.
-     *
-     * <p>If this list fits in the specified array with room to spare
-     * (i.e., the array has more elements than this list), the element in
-     * the array immediately following the end of the list is set to
-     * {@code null}.  (This is useful in determining the length of this
-     * list <i>only</i> if the caller knows that this list does not contain
-     * any null elements.)
-     *
-     * <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 list known to contain only strings.
-     * 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>
-     *
-     * Note that {@code toArray(new Object[0])} is identical in function to
-     * {@code toArray()}.
-     *
-     * @param a the array into which the elements of the list 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 the elements in this list
-     * @throws ArrayStoreException if the runtime type of the specified array
-     *         is not a supertype of the runtime type of every element in
-     *         this list
-     * @throws NullPointerException if the specified array is null
-     */
-    @SuppressWarnings("unchecked")
-    public <T> T[] toArray(T[] a) {
-        Object[] elements = getArray();
-        int len = elements.length;
-        if (a.length < len)
-            return (T[]) Arrays.copyOf(elements, len, a.getClass());
-        else {
-            System.arraycopy(elements, 0, a, 0, len);
-            if (a.length > len)
-                a[len] = null;
-            return a;
-        }
-    }
-
-    // Positional Access Operations
-
     @SuppressWarnings("unchecked")
-    private E get(Object[] a, int index) {
-        return (E) a[index];
-    }
-
-    static String outOfBounds(int index, int size) {
-        return "Index: " + index + ", Size: " + size;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @throws IndexOutOfBoundsException {@inheritDoc}
-     */
     public E get(int index) {
-        return get(getArray(), index);
+        return (E) elements[index];
     }
 
-    /**
-     * Replaces the element at the specified position in this list with the
-     * specified element.
-     *
-     * @throws IndexOutOfBoundsException {@inheritDoc}
-     */
-    public E set(int index, E element) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            E oldValue = get(elements, index);
-
-            if (oldValue != element) {
-                int len = elements.length;
-                Object[] newElements = Arrays.copyOf(elements, len);
-                newElements[index] = element;
-                setArray(newElements);
-            } else {
-                // Not quite a no-op; ensures volatile write semantics
-                setArray(elements);
-            }
-            return oldValue;
-        }
+    public boolean contains(Object o) {
+        return indexOf(o) != -1;
     }
 
-    /**
-     * Appends the specified element to the end of this list.
-     *
-     * @param e element to be appended to this list
-     * @return {@code true} (as specified by {@link Collection#add})
-     */
-    public boolean add(E e) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len + 1);
-            newElements[len] = e;
-            setArray(newElements);
-            return true;
-        }
+    public boolean containsAll(Collection<?> collection) {
+        Object[] snapshot = elements;
+        return containsAll(collection, snapshot, 0, snapshot.length);
     }
 
-    /**
-     * Inserts the specified element at the specified position in this
-     * list. Shifts the element currently at that position (if any) and
-     * any subsequent elements to the right (adds one to their indices).
-     *
-     * @throws IndexOutOfBoundsException {@inheritDoc}
-     */
-    public void add(int index, E element) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (index > len || index < 0)
-                throw new IndexOutOfBoundsException(outOfBounds(index, len));
-            Object[] newElements;
-            int numMoved = len - index;
-            if (numMoved == 0)
-                newElements = Arrays.copyOf(elements, len + 1);
-            else {
-                newElements = new Object[len + 1];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index, newElements, index + 1,
-                                 numMoved);
-            }
-            newElements[index] = element;
-            setArray(newElements);
-        }
-    }
-
-    /**
-     * Removes the element at the specified position in this list.
-     * Shifts any subsequent elements to the left (subtracts one from their
-     * indices).  Returns the element that was removed from the list.
-     *
-     * @throws IndexOutOfBoundsException {@inheritDoc}
-     */
-    public E remove(int index) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            E oldValue = get(elements, index);
-            int numMoved = len - index - 1;
-            if (numMoved == 0)
-                setArray(Arrays.copyOf(elements, len - 1));
-            else {
-                Object[] newElements = new Object[len - 1];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index + 1, newElements, index,
-                                 numMoved);
-                setArray(newElements);
-            }
-            return oldValue;
-        }
-    }
-
-    /**
-     * 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 {@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).
-     *
-     * @param o element to be removed from this list, if present
-     * @return {@code true} if this list contained the specified element
-     */
-    public boolean remove(Object o) {
-        Object[] snapshot = getArray();
-        int index = indexOf(o, snapshot, 0, snapshot.length);
-        return (index < 0) ? false : remove(o, snapshot, index);
-    }
-
-    /**
-     * A version of remove(Object) using the strong hint that given
-     * recent snapshot contains o at the given index.
-     */
-    private boolean remove(Object o, Object[] snapshot, int index) {
-        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]
-                        && Objects.equals(o, current[i])) {
-                        index = i;
-                        break findIndex;
-                    }
-                }
-                if (index >= len)
-                    return false;
-                if (current[index] == o)
-                    break findIndex;
-                index = indexOf(o, current, index, len);
-                if (index < 0)
-                    return false;
-            }
-            Object[] newElements = new Object[len - 1];
-            System.arraycopy(current, 0, newElements, 0, index);
-            System.arraycopy(current, index + 1,
-                             newElements, index,
-                             len - index - 1);
-            setArray(newElements);
-            return true;
-        }
-    }
-
-    /**
-     * Removes from this list all of the elements whose index is between
-     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
-     * Shifts any succeeding elements to the left (reduces their index).
-     * This call shortens the list by {@code (toIndex - fromIndex)} elements.
-     * (If {@code toIndex==fromIndex}, this operation has no effect.)
-     *
-     * @param fromIndex index of first element to be removed
-     * @param toIndex index after last element to be removed
-     * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
-     *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
-     */
-    void removeRange(int fromIndex, int toIndex) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-
-            if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
-                throw new IndexOutOfBoundsException();
-            int newlen = len - (toIndex - fromIndex);
-            int numMoved = len - toIndex;
-            if (numMoved == 0)
-                setArray(Arrays.copyOf(elements, newlen));
-            else {
-                Object[] newElements = new Object[newlen];
-                System.arraycopy(elements, 0, newElements, 0, fromIndex);
-                System.arraycopy(elements, toIndex, newElements,
-                                 fromIndex, numMoved);
-                setArray(newElements);
-            }
-        }
-    }
-
-    /**
-     * Appends the element, if not present.
-     *
-     * @param e element to be added to this list, if absent
-     * @return {@code true} if the element was added
-     */
-    public boolean addIfAbsent(E e) {
-        Object[] snapshot = getArray();
-        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
-            addIfAbsent(e, snapshot);
-    }
-
-    /**
-     * A version of addIfAbsent using the strong hint that given
-     * recent snapshot does not contain e.
-     */
-    private boolean addIfAbsent(E e, Object[] snapshot) {
-        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]
-                        && Objects.equals(e, current[i]))
-                        return false;
-                if (indexOf(e, current, common, len) >= 0)
-                        return false;
-            }
-            Object[] newElements = Arrays.copyOf(current, len + 1);
-            newElements[len] = e;
-            setArray(newElements);
-            return true;
-        }
-    }
-
-    /**
-     * Returns {@code true} if this list contains all of the elements of the
-     * specified collection.
-     *
-     * @param c collection to be checked for containment in this list
-     * @return {@code true} if this list contains all of the elements of the
-     *         specified collection
-     * @throws NullPointerException if the specified collection is null
-     * @see #contains(Object)
-     */
-    public boolean containsAll(Collection<?> c) {
-        Object[] elements = getArray();
-        int len = elements.length;
-        for (Object e : c) {
-            if (indexOf(e, elements, 0, len) < 0)
+    static boolean containsAll(Collection<?> collection, Object[] snapshot, int from, int to) {
+        for (Object o : collection) {
+            if (indexOf(o, snapshot, from, to) == -1) {
                 return false;
+            }
         }
         return true;
     }
 
     /**
-     * Removes from this list all of its elements that are contained in
-     * the specified collection. This is a particularly expensive operation
-     * in this class because of the need for an internal temporary array.
+     * Searches this list for {@code object} and returns the index of the first
+     * occurrence that is at or after {@code from}.
      *
-     * @param c collection containing elements to be removed from this list
-     * @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="{@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="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
-     *         or if the specified collection is null
-     * @see #remove(Object)
+     * @return the index or -1 if the object was not found.
      */
-    public boolean removeAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (!c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+    public int indexOf(E object, int from) {
+        Object[] snapshot = elements;
+        return indexOf(object, snapshot, from, snapshot.length);
+    }
+
+    public int indexOf(Object object) {
+        Object[] snapshot = elements;
+        return indexOf(object, snapshot, 0, snapshot.length);
     }
 
     /**
-     * Retains only the elements in this list that are contained in the
-     * specified collection.  In other words, removes from this list all of
-     * its elements that are not contained in the specified collection.
+     * Searches this list for {@code object} and returns the index of the last
+     * occurrence that is before {@code to}.
      *
-     * @param c collection containing elements to be retained in this list
-     * @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="{@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="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
-     *         or if the specified collection is null
-     * @see #remove(Object)
+     * @return the index or -1 if the object was not found.
      */
-    public boolean retainAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+    public int lastIndexOf(E object, int to) {
+        Object[] snapshot = elements;
+        return lastIndexOf(object, snapshot, 0, to);
+    }
+
+    public int lastIndexOf(Object object) {
+        Object[] snapshot = elements;
+        return lastIndexOf(object, snapshot, 0, snapshot.length);
+    }
+
+    public boolean isEmpty() {
+        return elements.length == 0;
     }
 
     /**
-     * Appends all of the elements in the specified collection that
-     * are not already contained in this list, to the end of
-     * this list, in the order that they are returned by the
-     * specified collection's iterator.
+     * Returns an {@link Iterator} that iterates over the elements of this list
+     * as they were at the time of this method call. Changes to the list made
+     * after this method call will not be reflected by the iterator, nor will
+     * they trigger a {@link ConcurrentModificationException}.
      *
-     * @param c collection containing elements to be added to this list
-     * @return the number of elements added
-     * @throws NullPointerException if the specified collection is null
-     * @see #addIfAbsent(Object)
-     */
-    public int addAllAbsent(Collection<? extends E> c) {
-        Object[] cs = c.toArray();
-        if (cs.length == 0)
-            return 0;
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            int added = 0;
-            // uniquify and compact elements in cs
-            for (int i = 0; i < cs.length; ++i) {
-                Object e = cs[i];
-                if (indexOf(e, elements, 0, len) < 0 &&
-                    indexOf(e, cs, 0, added) < 0)
-                    cs[added++] = e;
-            }
-            if (added > 0) {
-                Object[] newElements = Arrays.copyOf(elements, len + added);
-                System.arraycopy(cs, 0, newElements, len, added);
-                setArray(newElements);
-            }
-            return added;
-        }
-    }
-
-    /**
-     * Removes all of the elements from this list.
-     * The list will be empty after this call returns.
-     */
-    public void clear() {
-        synchronized (lock) {
-            setArray(new Object[0]);
-        }
-    }
-
-    /**
-     * Appends all of the elements in the specified collection to the end
-     * of this list, in the order that they are returned by the specified
-     * collection's iterator.
-     *
-     * @param c collection containing elements to be added to this list
-     * @return {@code true} if this list changed as a result of the call
-     * @throws NullPointerException if the specified collection is null
-     * @see #add(Object)
-     */
-    public boolean addAll(Collection<? extends E> c) {
-        Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
-            ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
-        if (cs.length == 0)
-            return false;
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len == 0 && cs.getClass() == Object[].class)
-                setArray(cs);
-            else {
-                Object[] newElements = Arrays.copyOf(elements, len + cs.length);
-                System.arraycopy(cs, 0, newElements, len, cs.length);
-                setArray(newElements);
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Inserts all of the elements in the specified collection into this
-     * list, starting at the specified position.  Shifts the element
-     * currently at that position (if any) and any subsequent elements to
-     * the right (increases their indices).  The new elements will appear
-     * in this list in the order that they are returned by the
-     * specified collection's iterator.
-     *
-     * @param index index at which to insert the first element
-     *        from the specified collection
-     * @param c collection containing elements to be added to this list
-     * @return {@code true} if this list changed as a result of the call
-     * @throws IndexOutOfBoundsException {@inheritDoc}
-     * @throws NullPointerException if the specified collection is null
-     * @see #add(int,Object)
-     */
-    public boolean addAll(int index, Collection<? extends E> c) {
-        Object[] cs = c.toArray();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (index > len || index < 0)
-                throw new IndexOutOfBoundsException(outOfBounds(index, len));
-            if (cs.length == 0)
-                return false;
-            int numMoved = len - index;
-            Object[] newElements;
-            if (numMoved == 0)
-                newElements = Arrays.copyOf(elements, len + cs.length);
-            else {
-                newElements = new Object[len + cs.length];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index,
-                                 newElements, index + cs.length,
-                                 numMoved);
-            }
-            System.arraycopy(cs, 0, newElements, index, cs.length);
-            setArray(newElements);
-            return true;
-        }
-    }
-
-    public void forEach(Consumer<? super E> action) {
-        if (action == null) throw new NullPointerException();
-        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();
-        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;       // zero matches => zero copies
-        }
-    }
-
-    public void replaceAll(UnaryOperator<E> operator) {
-        if (operator == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len);
-            for (int i = 0; i < len; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                newElements[i] = operator.apply(e);
-            }
-            setArray(newElements);
-        }
-    }
-
-    public void sort(Comparator<? super E> c) {
-        synchronized (lock) {
-            Object[] elements = getArray();
-            Object[] newElements = Arrays.copyOf(elements, elements.length);
-            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-            Arrays.sort(es, c);
-            setArray(newElements);
-        }
-    }
-
-    /**
-     * Saves this list to a stream (that is, serializes it).
-     *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
-     * @serialData The length of the array backing the list is emitted
-     *               (int), followed by all of its elements (each an Object)
-     *               in the proper order.
-     */
-    private void writeObject(java.io.ObjectOutputStream s)
-        throws java.io.IOException {
-
-        s.defaultWriteObject();
-
-        Object[] elements = getArray();
-        // Write out array length
-        s.writeInt(elements.length);
-
-        // Write out all elements in the proper order.
-        for (Object element : elements)
-            s.writeObject(element);
-    }
-
-    /**
-     * Reconstitutes this list 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 {
-
-        s.defaultReadObject();
-
-        // bind to new lock
-        resetLock();
-
-        // Read in array length and allocate array
-        int len = s.readInt();
-        Object[] elements = new Object[len];
-
-        // Read in all elements in the proper order.
-        for (int i = 0; i < len; i++)
-            elements[i] = s.readObject();
-        setArray(elements);
-    }
-
-    /**
-     * Returns a string representation of this list.  The string
-     * representation consists of the string representations of the list's
-     * elements in the order they are returned by its iterator, enclosed in
-     * square brackets ({@code "[]"}).  Adjacent elements are separated by
-     * the characters {@code ", "} (comma and space).  Elements are
-     * converted to strings as by {@link String#valueOf(Object)}.
-     *
-     * @return a string representation of this list
-     */
-    public String toString() {
-        return Arrays.toString(getArray());
-    }
-
-    /**
-     * Compares the specified object with this list for equality.
-     * Returns {@code true} if the specified object is the same object
-     * as this object, or if it is also a {@link List} and the sequence
-     * of elements returned by an {@linkplain List#iterator() iterator}
-     * over the specified list is the same as the sequence returned by
-     * an iterator over this list.  The two sequences are considered to
-     * 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 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
-     */
-    public boolean equals(Object o) {
-        if (o == this)
-            return true;
-        if (!(o instanceof List))
-            return false;
-
-        List<?> list = (List<?>)o;
-        Iterator<?> it = list.iterator();
-        Object[] elements = getArray();
-        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;
-        return true;
-    }
-
-    /**
-     * Returns the hash code value for this list.
-     *
-     * <p>This implementation uses the definition in {@link List#hashCode}.
-     *
-     * @return the hash code value for this list
-     */
-    public int hashCode() {
-        int hashCode = 1;
-        for (Object x : getArray())
-            hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode());
-        return hashCode;
-    }
-
-    /**
-     * Returns an iterator over the elements in this list in proper sequence.
-     *
-     * <p>The returned iterator provides a snapshot of the state of the list
-     * when the iterator was constructed. No synchronization is needed while
-     * traversing the iterator. The iterator does <em>NOT</em> support the
-     * {@code remove} method.
-     *
-     * @return an iterator over the elements in this list in proper sequence
+     * <p>The returned iterator does not support {@link Iterator#remove()}.
      */
     public Iterator<E> iterator() {
-        return new COWIterator<E>(getArray(), 0);
+        Object[] snapshot = elements;
+        return new CowIterator<E>(snapshot, 0, snapshot.length);
     }
 
     /**
-     * {@inheritDoc}
+     * Returns a {@link ListIterator} that iterates over the elements of this
+     * list as they were at the time of this method call. Changes to the list
+     * made after this method call will not be reflected by the iterator, nor
+     * will they trigger a {@link ConcurrentModificationException}.
      *
-     * <p>The returned iterator provides a snapshot of the state of the list
-     * when the iterator was constructed. No synchronization is needed while
-     * traversing the iterator. The iterator does <em>NOT</em> support the
-     * {@code remove}, {@code set} or {@code add} methods.
-     */
-    public ListIterator<E> listIterator() {
-        return new COWIterator<E>(getArray(), 0);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>The returned iterator provides a snapshot of the state of the list
-     * when the iterator was constructed. No synchronization is needed while
-     * traversing the iterator. The iterator does <em>NOT</em> support the
-     * {@code remove}, {@code set} or {@code add} methods.
-     *
-     * @throws IndexOutOfBoundsException {@inheritDoc}
+     * <p>The returned iterator does not support {@link ListIterator#add},
+     * {@link ListIterator#set} or {@link Iterator#remove()},
      */
     public ListIterator<E> listIterator(int index) {
-        Object[] elements = getArray();
-        int len = elements.length;
-        if (index < 0 || index > len)
-            throw new IndexOutOfBoundsException(outOfBounds(index, len));
-
-        return new COWIterator<E>(elements, index);
+        Object[] snapshot = elements;
+        if (index < 0 || index > snapshot.length) {
+            throw new IndexOutOfBoundsException("index=" + index + ", length=" + snapshot.length);
+        }
+        CowIterator<E> result = new CowIterator<E>(snapshot, 0, snapshot.length);
+        result.index = index;
+        return result;
     }
 
     /**
-     * Returns a {@link Spliterator} over the elements in this list.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#IMMUTABLE},
-     * {@link Spliterator#ORDERED}, {@link Spliterator#SIZED}, and
-     * {@link Spliterator#SUBSIZED}.
-     *
-     * <p>The spliterator provides a snapshot of the state of the list
-     * when the spliterator was constructed. No synchronization is needed while
-     * operating on the spliterator.
-     *
-     * @return a {@code Spliterator} over the elements in this list
-     * @since 1.8
+     * Equivalent to {@code listIterator(0)}.
      */
-    public Spliterator<E> spliterator() {
-        return Spliterators.spliterator
-            (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
+    public ListIterator<E> listIterator() {
+        Object[] snapshot = elements;
+        return new CowIterator<E>(snapshot, 0, snapshot.length);
     }
 
-    static final class COWIterator<E> implements ListIterator<E> {
-        /** Snapshot of the array */
-        private final Object[] snapshot;
-        /** Index of element to be returned by subsequent call to next.  */
-        private int cursor;
-
-        COWIterator(Object[] elements, int initialCursor) {
-            cursor = initialCursor;
-            snapshot = elements;
+    public List<E> subList(int from, int to) {
+        Object[] snapshot = elements;
+        if (from < 0 || from > to || to > snapshot.length) {
+            throw new IndexOutOfBoundsException("from=" + from + ", to=" + to +
+                    ", list size=" + snapshot.length);
         }
+        return new CowSubList(snapshot, from, to);
+    }
 
-        public boolean hasNext() {
-            return cursor < snapshot.length;
+    public Object[] toArray() {
+        return elements.clone();
+    }
+
+    @SuppressWarnings({"unchecked","SuspiciousSystemArraycopy"})
+    public <T> T[] toArray(T[] contents) {
+        Object[] snapshot = elements;
+        if (snapshot.length > contents.length) {
+            return (T[]) Arrays.copyOf(snapshot, snapshot.length, contents.getClass());
         }
-
-        public boolean hasPrevious() {
-            return cursor > 0;
+        System.arraycopy(snapshot, 0, contents, 0, snapshot.length);
+        if (snapshot.length < contents.length) {
+            contents[snapshot.length] = null;
         }
+        return contents;
+    }
 
-        @SuppressWarnings("unchecked")
-        public E next() {
-            if (! hasNext())
-                throw new NoSuchElementException();
-            return (E) snapshot[cursor++];
-        }
-
-        @SuppressWarnings("unchecked")
-        public E previous() {
-            if (! hasPrevious())
-                throw new NoSuchElementException();
-            return (E) snapshot[--cursor];
-        }
-
-        public int nextIndex() {
-            return cursor;
-        }
-
-        public int previousIndex() {
-            return cursor-1;
-        }
-
-        /**
-         * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; {@code remove}
-         *         is not supported by this iterator.
-         */
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        /**
-         * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; {@code set}
-         *         is not supported by this iterator.
-         */
-        public void set(E e) {
-            throw new UnsupportedOperationException();
-        }
-
-        /**
-         * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; {@code add}
-         *         is not supported by this iterator.
-         */
-        public void add(E e) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public void forEachRemaining(Consumer<? super E> action) {
-            Objects.requireNonNull(action);
-            final int size = snapshot.length;
-            for (int i = cursor; i < size; i++) {
-                action.accept((E) snapshot[i]);
+    @Override public boolean equals(Object other) {
+        if (other instanceof CopyOnWriteArrayList) {
+            return this == other
+                    || Arrays.equals(elements, ((CopyOnWriteArrayList<?>) other).elements);
+        } else if (other instanceof List) {
+            Object[] snapshot = elements;
+            Iterator<?> i = ((List<?>) other).iterator();
+            for (Object o : snapshot) {
+                if (!i.hasNext() || !Objects.equal(o, i.next())) {
+                    return false;
+                }
             }
-            cursor = size;
+            return !i.hasNext();
+        } else {
+            return false;
         }
     }
 
+    @Override public int hashCode() {
+        return Arrays.hashCode(elements);
+    }
+
+    @Override public String toString() {
+        return Arrays.toString(elements);
+    }
+
+    public synchronized boolean add(E e) {
+        Object[] newElements = new Object[elements.length + 1];
+        System.arraycopy(elements, 0, newElements, 0, elements.length);
+        newElements[elements.length] = e;
+        elements = newElements;
+        return true;
+    }
+
+    public synchronized void add(int index, E e) {
+        Object[] newElements = new Object[elements.length + 1];
+        System.arraycopy(elements, 0, newElements, 0, index);
+        newElements[index] = e;
+        System.arraycopy(elements, index, newElements, index + 1, elements.length - index);
+        elements = newElements;
+    }
+
+    public synchronized boolean addAll(Collection<? extends E> collection) {
+        return addAll(elements.length, collection);
+    }
+
+    public synchronized boolean addAll(int index, Collection<? extends E> collection) {
+        Object[] toAdd = collection.toArray();
+        Object[] newElements = new Object[elements.length + toAdd.length];
+        System.arraycopy(elements, 0, newElements, 0, index);
+        System.arraycopy(toAdd, 0, newElements, index, toAdd.length);
+        System.arraycopy(elements, index,
+                newElements, index + toAdd.length, elements.length - index);
+        elements = newElements;
+        return toAdd.length > 0;
+    }
+
     /**
-     * Returns a view of the portion of this list between
-     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
-     * The returned list is backed by this list, so changes in the
-     * returned list are reflected in this list.
+     * Adds the elements of {@code collection} that are not already present in
+     * this list. If {@code collection} includes a repeated value, at most one
+     * occurrence of that value will be added to this list. Elements are added
+     * at the end of this list.
      *
-     * <p>The semantics of the list returned by this method become
-     * undefined if the backing list (i.e., this list) is modified in
-     * any way other than via the returned list.
-     *
-     * @param fromIndex low endpoint (inclusive) of the subList
-     * @param toIndex high endpoint (exclusive) of the subList
-     * @return a view of the specified range within this list
-     * @throws IndexOutOfBoundsException {@inheritDoc}
+     * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose
+     * API is more appropriate for set operations.
      */
-    public List<E> subList(int fromIndex, int toIndex) {
-        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);
+    public synchronized int addAllAbsent(Collection<? extends E> collection) {
+        Object[] toAdd = collection.toArray();
+        Object[] newElements = new Object[elements.length + toAdd.length];
+        System.arraycopy(elements, 0, newElements, 0, elements.length);
+        int addedCount = 0;
+        for (Object o : toAdd) {
+            if (indexOf(o, newElements, 0, elements.length + addedCount) == -1) {
+                newElements[elements.length + addedCount++] = o;
+            }
         }
+        if (addedCount < toAdd.length) {
+            newElements = Arrays.copyOfRange(
+                    newElements, 0, elements.length + addedCount); // trim to size
+        }
+        elements = newElements;
+        return addedCount;
     }
 
     /**
-     * Sublist for CopyOnWriteArrayList.
-     * This class extends AbstractList merely for convenience, to
-     * avoid having to define addAll, etc. This doesn't hurt, but
-     * is wasteful.  This class does not need or use modCount
-     * mechanics in AbstractList, but does need to check for
-     * concurrent modification using similar mechanics.  On each
-     * operation, the array that we expect the backing list to use
-     * is checked and updated.  Since we do this for all of the
-     * base operations invoked by those defined in AbstractList,
-     * all is well.  While inefficient, this is not worth
-     * improving.  The kinds of list operations inherited from
-     * AbstractList are already so slow on COW sublists that
-     * adding a bit more space/time doesn't seem even noticeable.
+     * Adds {@code object} to the end of this list if it is not already present.
+     *
+     * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose
+     * API is more appropriate for set operations.
      */
-    private static class COWSubList<E>
-        extends AbstractList<E>
-        implements RandomAccess
-    {
-        private final CopyOnWriteArrayList<E> l;
-        private final int offset;
-        private int size;
-        private Object[] expectedArray;
+    public synchronized boolean addIfAbsent(E object) {
+        if (contains(object)) {
+            return false;
+        }
+        add(object);
+        return true;
+    }
 
-        // 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;
-            size = toIndex - fromIndex;
+    @Override public synchronized void clear() {
+        elements = EmptyArray.OBJECT;
+    }
+
+    public synchronized E remove(int index) {
+        @SuppressWarnings("unchecked")
+        E removed = (E) elements[index];
+        removeRange(index, index + 1);
+        return removed;
+    }
+
+    public synchronized boolean remove(Object o) {
+        int index = indexOf(o);
+        if (index == -1) {
+            return false;
+        }
+        remove(index);
+        return true;
+    }
+
+    public synchronized boolean removeAll(Collection<?> collection) {
+        return removeOrRetain(collection, false, 0, elements.length) != 0;
+    }
+
+    public synchronized boolean retainAll(Collection<?> collection) {
+        return removeOrRetain(collection, true, 0, elements.length) != 0;
+    }
+
+    /**
+     * Removes or retains the elements in {@code collection}. Returns the number
+     * of elements removed.
+     */
+    private int removeOrRetain(Collection<?> collection, boolean retain, int from, int to) {
+        for (int i = from; i < to; i++) {
+            if (collection.contains(elements[i]) == retain) {
+                continue;
+            }
+
+            /*
+             * We've encountered an element that must be removed! Create a new
+             * array and copy in the surviving elements one by one.
+             */
+            Object[] newElements = new Object[elements.length - 1];
+            System.arraycopy(elements, 0, newElements, 0, i);
+            int newSize = i;
+            for (int j = i + 1; j < to; j++) {
+                if (collection.contains(elements[j]) == retain) {
+                    newElements[newSize++] = elements[j];
+                }
+            }
+
+            /*
+             * Copy the elements after 'to'. This is only useful for sub lists,
+             * where 'to' will be less than elements.length.
+             */
+            System.arraycopy(elements, to, newElements, newSize, elements.length - to);
+            newSize += (elements.length - to);
+
+            if (newSize < newElements.length) {
+                newElements = Arrays.copyOfRange(newElements, 0, newSize); // trim to size
+            }
+            int removed = elements.length - newElements.length;
+            elements = newElements;
+            return removed;
         }
 
-        // only call this holding l's lock
-        private void checkForComodification() {
-            // assert Thread.holdsLock(l.lock);
-            if (l.getArray() != expectedArray)
-                throw new ConcurrentModificationException();
+        // we made it all the way through the loop without making any changes
+        return 0;
+    }
+
+    public synchronized E set(int index, E e) {
+        Object[] newElements = elements.clone();
+        @SuppressWarnings("unchecked")
+        E result = (E) newElements[index];
+        newElements[index] = e;
+        elements = newElements;
+        return result;
+    }
+
+    private void removeRange(int from, int to) {
+        Object[] newElements = new Object[elements.length - (to - from)];
+        System.arraycopy(elements, 0, newElements, 0, from);
+        System.arraycopy(elements, to, newElements, from, elements.length - to);
+        elements = newElements;
+    }
+
+    static int lastIndexOf(Object o, Object[] data, int from, int to) {
+        if (o == null) {
+            for (int i = to - 1; i >= from; i--) {
+                if (data[i] == null) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = to - 1; i >= from; i--) {
+                if (o.equals(data[i])) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    static int indexOf(Object o, Object[] data, int from, int to) {
+        if (o == null) {
+            for (int i = from; i < to; i++) {
+                if (data[i] == null) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = from; i < to; i++) {
+                if (o.equals(data[i])) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    final Object[] getArray() {
+        // CopyOnWriteArraySet needs this.
+        return elements;
+    }
+
+    /**
+     * The sub list is thread safe and supports non-blocking reads. Doing so is
+     * more difficult than in the full list, because each read needs to examine
+     * four fields worth of state:
+     *  - the elements array of the full list
+     *  - two integers for the bounds of this sub list
+     *  - the expected elements array (to detect concurrent modification)
+     *
+     * This is accomplished by aggregating the sub list's three fields into a
+     * single snapshot object representing the current slice. This permits reads
+     * to be internally consistent without synchronization. This takes advantage
+     * of Java's concurrency semantics for final fields.
+     */
+    class CowSubList extends AbstractList<E> {
+
+        /*
+         * An immutable snapshot of a sub list's state. By gathering all three
+         * of the sub list's fields in an immutable object,
+         */
+        private volatile Slice slice;
+
+        public CowSubList(Object[] expectedElements, int from, int to) {
+            this.slice = new Slice(expectedElements, from, to);
         }
 
-        // 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(outOfBounds(index, size));
+        @Override public int size() {
+            Slice slice = this.slice;
+            return slice.to - slice.from;
         }
 
-        public E set(int index, E element) {
-            synchronized (l.lock) {
-                rangeCheck(index);
-                checkForComodification();
-                E x = l.set(index+offset, element);
-                expectedArray = l.getArray();
-                return x;
+        @Override public boolean isEmpty() {
+            Slice slice = this.slice;
+            return slice.from == slice.to;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override public E get(int index) {
+            Slice slice = this.slice;
+            Object[] snapshot = elements;
+            slice.checkElementIndex(index);
+            slice.checkConcurrentModification(snapshot);
+            return (E) snapshot[index + slice.from];
+        }
+
+        @Override public Iterator<E> iterator() {
+            return listIterator(0);
+        }
+
+        @Override public ListIterator<E> listIterator() {
+            return listIterator(0);
+        }
+
+        @Override public ListIterator<E> listIterator(int index) {
+            Slice slice = this.slice;
+            Object[] snapshot = elements;
+            slice.checkPositionIndex(index);
+            slice.checkConcurrentModification(snapshot);
+            CowIterator<E> result = new CowIterator<E>(snapshot, slice.from, slice.to);
+            result.index = slice.from + index;
+            return result;
+        }
+
+        @Override public int indexOf(Object object) {
+            Slice slice = this.slice;
+            Object[] snapshot = elements;
+            slice.checkConcurrentModification(snapshot);
+            int result = CopyOnWriteArrayList.indexOf(object, snapshot, slice.from, slice.to);
+            return (result != -1) ? (result - slice.from) : -1;
+        }
+
+        @Override public int lastIndexOf(Object object) {
+            Slice slice = this.slice;
+            Object[] snapshot = elements;
+            slice.checkConcurrentModification(snapshot);
+            int result = CopyOnWriteArrayList.lastIndexOf(object, snapshot, slice.from, slice.to);
+            return (result != -1) ? (result - slice.from) : -1;
+        }
+
+        @Override public boolean contains(Object object) {
+            return indexOf(object) != -1;
+        }
+
+        @Override public boolean containsAll(Collection<?> collection) {
+            Slice slice = this.slice;
+            Object[] snapshot = elements;
+            slice.checkConcurrentModification(snapshot);
+            return CopyOnWriteArrayList.containsAll(collection, snapshot, slice.from, slice.to);
+        }
+
+        @Override public List<E> subList(int from, int to) {
+            Slice slice = this.slice;
+            if (from < 0 || from > to || to > size()) {
+                throw new IndexOutOfBoundsException("from=" + from + ", to=" + to +
+                        ", list size=" + size());
+            }
+            return new CowSubList(slice.expectedElements, slice.from + from, slice.from + to);
+        }
+
+        @Override public E remove(int index) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkElementIndex(index);
+                slice.checkConcurrentModification(elements);
+                E removed = CopyOnWriteArrayList.this.remove(slice.from + index);
+                slice = new Slice(elements, slice.from, slice.to - 1);
+                return removed;
             }
         }
 
-        public E get(int index) {
-            synchronized (l.lock) {
-                rangeCheck(index);
-                checkForComodification();
-                return l.get(index+offset);
+        @Override public void clear() {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkConcurrentModification(elements);
+                CopyOnWriteArrayList.this.removeRange(slice.from, slice.to);
+                slice = new Slice(elements, slice.from, slice.from);
             }
         }
 
-        public int size() {
-            synchronized (l.lock) {
-                checkForComodification();
-                return size;
+        @Override public void add(int index, E object) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkPositionIndex(index);
+                slice.checkConcurrentModification(elements);
+                CopyOnWriteArrayList.this.add(index + slice.from, object);
+                slice = new Slice(elements, slice.from, slice.to + 1);
             }
         }
 
-        public void add(int index, E element) {
-            synchronized (l.lock) {
-                checkForComodification();
-                if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException
-                        (outOfBounds(index, size));
-                l.add(index+offset, element);
-                expectedArray = l.getArray();
-                size++;
+        @Override public boolean add(E object) {
+            synchronized (CopyOnWriteArrayList.this) {
+                add(slice.to - slice.from, object);
+                return true;
             }
         }
 
-        public void clear() {
-            synchronized (l.lock) {
-                checkForComodification();
-                l.removeRange(offset, offset+size);
-                expectedArray = l.getArray();
-                size = 0;
-            }
-        }
-
-        public E remove(int index) {
-            synchronized (l.lock) {
-                rangeCheck(index);
-                checkForComodification();
-                E result = l.remove(index+offset);
-                expectedArray = l.getArray();
-                size--;
+        @Override public boolean addAll(int index, Collection<? extends E> collection) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkPositionIndex(index);
+                slice.checkConcurrentModification(elements);
+                int oldSize = elements.length;
+                boolean result = CopyOnWriteArrayList.this.addAll(index + slice.from, collection);
+                slice = new Slice(elements, slice.from, slice.to + (elements.length - oldSize));
                 return result;
             }
         }
 
-        public boolean remove(Object o) {
-            int index = indexOf(o);
-            if (index == -1)
-                return false;
-            remove(index);
-            return true;
-        }
-
-        public Iterator<E> iterator() {
-            synchronized (l.lock) {
-                checkForComodification();
-                return new COWSubListIterator<E>(l, 0, offset, size);
+        @Override public boolean addAll(Collection<? extends E> collection) {
+            synchronized (CopyOnWriteArrayList.this) {
+                return addAll(size(), collection);
             }
         }
 
-        public ListIterator<E> listIterator(int index) {
-            synchronized (l.lock) {
-                checkForComodification();
-                if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException
-                        (outOfBounds(index, size));
-                return new COWSubListIterator<E>(l, index, offset, size);
+        @Override public E set(int index, E object) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkElementIndex(index);
+                slice.checkConcurrentModification(elements);
+                E result = CopyOnWriteArrayList.this.set(index + slice.from, object);
+                slice = new Slice(elements, slice.from, slice.to);
+                return result;
             }
         }
 
-        public List<E> subList(int fromIndex, int toIndex) {
-            synchronized (l.lock) {
-                checkForComodification();
-                if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
-                    throw new IndexOutOfBoundsException();
-                return new COWSubList<E>(l, fromIndex + offset,
-                                         toIndex + offset);
-            }
-        }
-
-        public void forEach(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            for (int i = lo; i < hi; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) a[i];
-                action.accept(e);
-            }
-        }
-
-        public void replaceAll(UnaryOperator<E> operator) {
-            if (operator == null) throw new NullPointerException();
-            synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                for (int i = lo; i < hi; ++i) {
-                    @SuppressWarnings("unchecked") E e = (E) elements[i];
-                    newElements[i] = operator.apply(e);
+        @Override public boolean remove(Object object) {
+            synchronized (CopyOnWriteArrayList.this) {
+                int index = indexOf(object);
+                if (index == -1) {
+                    return false;
                 }
-                l.setArray(expectedArray = newElements);
+                remove(index);
+                return true;
             }
         }
 
-        public void sort(Comparator<? super E> c) {
-            synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-                Arrays.sort(es, lo, hi, c);
-                l.setArray(expectedArray = newElements);
+        @Override public boolean removeAll(Collection<?> collection) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkConcurrentModification(elements);
+                int removed = removeOrRetain(collection, false, slice.from, slice.to);
+                slice = new Slice(elements, slice.from, slice.to - removed);
+                return removed != 0;
             }
         }
 
-        public boolean removeAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (!c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
+        @Override public boolean retainAll(Collection<?> collection) {
+            synchronized (CopyOnWriteArrayList.this) {
+                slice.checkConcurrentModification(elements);
+                int removed = removeOrRetain(collection, true, slice.from, slice.to);
+                slice = new Slice(elements, slice.from, slice.to - removed);
+                return removed != 0;
             }
-            return removed;
         }
-
-        public boolean retainAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
-        }
-
-        public boolean removeIf(Predicate<? super E> filter) {
-            if (filter == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        @SuppressWarnings("unchecked") E e = (E) elements[i];
-                        if (!filter.test(e))
-                            temp[newSize++] = e;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
-        }
-
-        public Spliterator<E> spliterator() {
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            return Spliterators.spliterator
-                (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
-        }
-
     }
 
-    private static class COWSubListIterator<E> implements ListIterator<E> {
-        private final ListIterator<E> it;
-        private final int offset;
-        private final int size;
+    static class Slice {
+        private final Object[] expectedElements;
+        private final int from;
+        private final int to;
 
-        COWSubListIterator(List<E> l, int index, int offset, int size) {
-            this.offset = offset;
-            this.size = size;
-            it = l.listIterator(index+offset);
+        Slice(Object[] expectedElements, int from, int to) {
+            this.expectedElements = expectedElements;
+            this.from = from;
+            this.to = to;
+        }
+
+        /**
+         * Throws if {@code index} doesn't identify an element in the array.
+         */
+        void checkElementIndex(int index) {
+            if (index < 0 || index >= to - from) {
+                throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from));
+            }
+        }
+
+        /**
+         * Throws if {@code index} doesn't identify an insertion point in the
+         * array. Unlike element index, it's okay to add or iterate at size().
+         */
+        void checkPositionIndex(int index) {
+            if (index < 0 || index > to - from) {
+                throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from));
+            }
+        }
+
+        void checkConcurrentModification(Object[] snapshot) {
+            if (expectedElements != snapshot) {
+                throw new ConcurrentModificationException();
+            }
+        }
+    }
+
+    /**
+     * Iterates an immutable snapshot of the list.
+     */
+    static class CowIterator<E> implements ListIterator<E> {
+        private final Object[] snapshot;
+        private final int from;
+        private final int to;
+        private int index = 0;
+
+        CowIterator(Object[] snapshot, int from, int to) {
+            this.snapshot = snapshot;
+            this.from = from;
+            this.to = to;
+            this.index = from;
+        }
+
+        public void add(E object) {
+            throw new UnsupportedOperationException();
         }
 
         public boolean hasNext() {
-            return nextIndex() < size;
-        }
-
-        public E next() {
-            if (hasNext())
-                return it.next();
-            else
-                throw new NoSuchElementException();
+            return index < to;
         }
 
         public boolean hasPrevious() {
-            return previousIndex() >= 0;
+            return index > from;
         }
 
-        public E previous() {
-            if (hasPrevious())
-                return it.previous();
-            else
+        @SuppressWarnings("unchecked")
+        public E next() {
+            if (index < to) {
+                return (E) snapshot[index++];
+            } else {
                 throw new NoSuchElementException();
+            }
         }
 
         public int nextIndex() {
-            return it.nextIndex() - offset;
+            return index;
+        }
+
+        @SuppressWarnings("unchecked")
+        public E previous() {
+            if (index > from) {
+                return (E) snapshot[--index];
+            } else {
+                throw new NoSuchElementException();
+            }
         }
 
         public int previousIndex() {
-            return it.previousIndex() - offset;
+            return index - 1;
         }
 
         public void remove() {
             throw new UnsupportedOperationException();
         }
 
-        public void set(E e) {
-            throw new UnsupportedOperationException();
-        }
-
-        public void add(E e) {
+        public void set(E object) {
             throw new UnsupportedOperationException();
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
-            Objects.requireNonNull(action);
-            while (nextIndex() < size) {
-                action.accept(it.next());
+            java.util.Objects.requireNonNull(action);
+            Object[] elements = snapshot;
+            for (int i = index; i < to; i++) {
+                @SuppressWarnings("unchecked") E e = (E) elements[i];
+                action.accept(e);
             }
+            index = to;
         }
     }
 
-    // Support for resetting lock while deserializing
-    private void resetLock() {
-        U.putObjectVolatile(this, LOCK, new Object());
-    }
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long LOCK;
-    static {
-        try {
-            LOCK = U.objectFieldOffset
-                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        Object[] snapshot = elements;
+        out.defaultWriteObject();
+        out.writeInt(snapshot.length);
+        for (Object o : snapshot) {
+            out.writeObject(o);
         }
     }
+
+    private synchronized void readObject(ObjectInputStream in)
+            throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        Object[] snapshot = new Object[in.readInt()];
+        for (int i = 0; i < snapshot.length; i++) {
+            snapshot[i] = in.readObject();
+        }
+        elements = snapshot;
+    }
 }
diff --git a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index 0cf8558..347ed14 100644
--- a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -6,19 +6,10 @@
 
 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.Spliterator;
-import java.util.Spliterators;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
+import java.util.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
 // END android-note
 
 /**
@@ -44,12 +35,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<>();
+ *     = new CopyOnWriteArraySet<Handler>();
  *   public void addHandler(Handler h) { handlers.add(h); }
  *
  *   private long internalState;
@@ -65,7 +56,7 @@
  * @see CopyOnWriteArrayList
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this set
+ * @param <E> the type of elements held in this collection
  */
 public class CopyOnWriteArraySet<E> extends AbstractSet<E>
         implements java.io.Serializable {
@@ -88,15 +79,8 @@
      * @throws NullPointerException if the specified collection is null
      */
     public CopyOnWriteArraySet(Collection<? extends E> c) {
-        if (c.getClass() == CopyOnWriteArraySet.class) {
-            @SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
-                (CopyOnWriteArraySet<E>)c;
-            al = new CopyOnWriteArrayList<E>(cc.al);
-        }
-        else {
-            al = new CopyOnWriteArrayList<E>();
-            al.addAllAbsent(c);
-        }
+        al = new CopyOnWriteArrayList<E>();
+        al.addAllAbsent(c);
     }
 
     /**
@@ -120,7 +104,8 @@
     /**
      * 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 {@code Objects.equals(o, e)}.
+     * contains an element {@code e} such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @param o element whose presence in this set is to be tested
      * @return {@code true} if this set contains the specified element
@@ -176,7 +161,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()}.
@@ -205,10 +190,11 @@
     /**
      * Removes the specified element from this set if it is present.
      * More formally, removes an element {@code e} such that
-     * {@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.)
+     * <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.)
      *
      * @param o object to be removed from this set, if present
      * @return {@code true} if this set contained the specified element
@@ -221,7 +207,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
-     * {@code Objects.equals(e, e2)}.
+     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
      * If this set already contains the element, the call leaves the set
      * unchanged and returns {@code false}.
      *
@@ -245,44 +231,7 @@
      * @see #contains(Object)
      */
     public boolean containsAll(Collection<?> 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;
+        return al.containsAll(c);
     }
 
     /**
@@ -311,11 +260,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 class of an element of this set
-     *         is incompatible with the specified collection
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
-     *         specified collection does not permit null elements
-     * (<a href="../Collection.html#optional-restrictions">optional</a>),
+     *         specified collection does not permit null elements (optional),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -334,11 +281,9 @@
      * @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
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
-     *         specified collection does not permit null elements
-     * (<a href="../Collection.html#optional-restrictions">optional</a>),
+     *         specified collection does not permit null elements (optional),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -365,49 +310,54 @@
      * Compares the specified object with this set for equality.
      * Returns {@code true} if the specified object is the same object
      * as this object, or if it is also a {@link Set} and the elements
-     * returned by an {@linkplain Set#iterator() iterator} over the
+     * returned by an {@linkplain List#iterator() iterator} over the
      * specified set are the same as the elements returned by an
      * iterator over this set.  More formally, the two iterators are
      * considered to return the same elements if they return the same
      * 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 Objects.equals(e1, e2)}.
+     * {@code (e1==null ? e2==null : e1.equals(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) {
-        return (o == this)
-            || ((o instanceof Set)
-                && compareSets(al.getArray(), (Set<?>) o) == 0);
-    }
+        if (o == this)
+            return true;
+        if (!(o instanceof Set))
+            return false;
+        Set<?> set = (Set<?>)(o);
+        Iterator<?> it = set.iterator();
 
-    public boolean removeIf(Predicate<? super E> filter) {
-        return al.removeIf(filter);
-    }
+        // Uses O(n^2) algorithm that is only appropriate
+        // for small sets, which CopyOnWriteArraySets should be.
 
-    public void forEach(Consumer<? super E> action) {
-        al.forEach(action);
+        //  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;
     }
 
     /**
-     * Returns a {@link Spliterator} over the elements in this set in the order
-     * in which these elements were added.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#IMMUTABLE},
-     * {@link Spliterator#DISTINCT}, {@link Spliterator#SIZED}, and
-     * {@link Spliterator#SUBSIZED}.
-     *
-     * <p>The spliterator provides a snapshot of the state of the set
-     * when the spliterator was constructed. No synchronization is needed while
-     * operating on the spliterator.
-     *
-     * @return a {@code Spliterator} over the elements in this set
-     * @since 1.8
+     * Tests for equality, coping with nulls.
      */
-    public Spliterator<E> spliterator() {
-        return Spliterators.spliterator
-            (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
+    private static boolean eq(Object o1, Object o2) {
+        return (o1 == null) ? o2 == null : o1.equals(o2);
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/CountDownLatch.java b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
index 680ea16..77093f7 100644
--- a/luni/src/main/java/java/util/concurrent/CountDownLatch.java
+++ b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
@@ -44,7 +44,7 @@
  * until all workers have completed.
  * </ul>
  *
- * <pre> {@code
+ *  <pre> {@code
  * class Driver { // ...
  *   void main() throws InterruptedException {
  *     CountDownLatch startSignal = new CountDownLatch(1);
@@ -85,7 +85,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);
@@ -151,7 +151,7 @@
                 int c = getState();
                 if (c == 0)
                     return false;
-                int nextc = c - 1;
+                int nextc = c-1;
                 if (compareAndSetState(c, nextc))
                     return nextc == 0;
             }
diff --git a/luni/src/main/java/java/util/concurrent/CountedCompleter.java b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
index 9c8b1b2..b868037 100644
--- a/luni/src/main/java/java/util/concurrent/CountedCompleter.java
+++ b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -13,7 +13,7 @@
  * presence of subtask stalls and blockage than are other forms of
  * ForkJoinTasks, but are less intuitive to program.  Uses of
  * CountedCompleter are similar to those of other completion based
- * components
+ * components (such as {@link java.nio.channels.CompletionHandler})
  * except that multiple <em>pending</em> completions may be necessary
  * to trigger the completion action {@link #onCompletion(CountedCompleter)},
  * not just one.
@@ -139,8 +139,7 @@
  * {@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;
@@ -154,19 +153,18 @@
  *       tryComplete();
  *     }
  *   }
- * }}</pre>
+ * }</pre>
  *
- * As a further optimization, notice that the left task need not even exist.
+ * 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,
  * and add a pending count for each fork.  Additionally, because no task
  * in this tree implements an {@link #onCompletion(CountedCompleter)} method,
  * {@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);
@@ -177,9 +175,9 @@
  *       op.apply(array[l]);
  *     propagateCompletion();
  *   }
- * }}</pre>
+ * }</pre>
  *
- * Additional optimizations of such classes might entail precomputing
+ * Additional improvements of such classes might entail precomputing
  * pending counts so that they can be established in constructors,
  * specializing classes for leaf steps, subdividing by say, four,
  * instead of two per iteration, and using an adaptive threshold
@@ -206,7 +204,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;
@@ -231,9 +229,9 @@
  * }}</pre>
  *
  * In this example, as well as others in which tasks have no other
- * effects except to {@code compareAndSet} a common result, the
- * trailing unconditional invocation of {@code tryComplete} could be
- * made conditional ({@code if (result.get() == null) tryComplete();})
+ * effects except to compareAndSet a common result, the trailing
+ * unconditional invocation of {@code tryComplete} could be made
+ * conditional ({@code if (result.get() == null) tryComplete();})
  * because no further bookkeeping is required to manage completions
  * once the root task completes.
  *
@@ -336,7 +334,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);
@@ -347,7 +345,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);
  *     }
  *   }
@@ -375,9 +373,11 @@
  * // sample use:
  * PacketSender p = new PacketSender();
  * new HeaderBuilder(p, ...).fork();
- * new BodyBuilder(p, ...).fork();}</pre>
+ * new BodyBuilder(p, ...).fork();
+ * }</pre>
  *
  * @since 1.8
+ * @hide
  * @author Doug Lea
  */
 public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
@@ -495,7 +495,8 @@
      * @param delta the value to add
      */
     public final void addToPendingCount(int delta) {
-        U.getAndAddInt(this, PENDING, delta);
+        int c;
+        do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta));
     }
 
     /**
@@ -595,7 +596,7 @@
      * any one (versus all) of several subtask results are obtained.
      * However, in the common (and recommended) case in which {@code
      * setRawResult} is not overridden, this effect can be obtained
-     * more simply using {@link #quietlyCompleteRoot()}.
+     * more simply using {@code quietlyCompleteRoot();}.
      *
      * @param rawResult the raw result
      */
@@ -610,9 +611,9 @@
 
     /**
      * If this task's pending count is zero, returns this task;
-     * otherwise decrements its pending count and returns {@code null}.
-     * This method is designed to be used with {@link #nextComplete} in
-     * completion traversal loops.
+     * otherwise decrements its pending count and returns {@code
+     * null}. This method is designed to be used with {@link
+     * #nextComplete} in completion traversal loops.
      *
      * @return this task, if pending count was zero, else {@code null}
      */
@@ -666,26 +667,6 @@
     }
 
     /**
-     * If this task has not completed, attempts to process at most the
-     * given number of other unprocessed tasks for which this task is
-     * on the completion path, if any are known to exist.
-     *
-     * @param maxTasks the maximum number of tasks to process.  If
-     *                 less than or equal to zero, then no tasks are
-     *                 processed.
-     */
-    public final void helpComplete(int maxTasks) {
-        Thread t; ForkJoinWorkerThread wt;
-        if (maxTasks > 0 && status >= 0) {
-            if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
-                (wt = (ForkJoinWorkerThread)t).pool.
-                    helpComplete(wt.workQueue, this, maxTasks);
-            else
-                ForkJoinPool.common.externalHelpComplete(this, maxTasks);
-        }
-    }
-
-    /**
      * Supports ForkJoinTask exception propagation.
      */
     void internalPropagateException(Throwable ex) {
@@ -725,13 +706,14 @@
     protected void setRawResult(T t) { }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final sun.misc.Unsafe U;
     private static final long PENDING;
     static {
         try {
+            U = sun.misc.Unsafe.getUnsafe();
             PENDING = U.objectFieldOffset
                 (CountedCompleter.class.getDeclaredField("pending"));
-        } catch (ReflectiveOperationException e) {
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
index 7219c93..d698501 100644
--- a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -23,10 +23,10 @@
  * This <em>barrier action</em> is useful
  * for updating shared-state before any of the parties continue.
  *
- * <p><b>Sample usage:</b> Here is an example of using a barrier in a
- * parallel decomposition design:
+ * <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;
@@ -53,20 +53,16 @@
  *   public Solver(float[][] matrix) {
  *     data = matrix;
  *     N = matrix.length;
- *     Runnable barrierAction =
- *       new Runnable() { public void run() { mergeRows(...); }};
- *     barrier = new CyclicBarrier(N, barrierAction);
+ *     barrier = new CyclicBarrier(N,
+ *                                 new Runnable() {
+ *                                   public void run() {
+ *                                     mergeRows(...);
+ *                                   }
+ *                                 });
+ *     for (int i = 0; i < N; ++i)
+ *       new Thread(new Worker(i)).start();
  *
- *     List<Thread> threads = new ArrayList<>(N);
- *     for (int i = 0; i < N; i++) {
- *       Thread thread = new Thread(new Worker(i));
- *       threads.add(thread);
- *       thread.start();
- *     }
- *
- *     // wait until done
- *     for (Thread thread : threads)
- *       thread.join();
+ *     waitUntilDone();
  *   }
  * }}</pre>
  *
@@ -83,7 +79,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>
@@ -121,7 +117,7 @@
      * but no subsequent reset.
      */
     private static class Generation {
-        boolean broken;         // initially false
+        boolean broken = false;
     }
 
     /** The lock for guarding barrier entry */
@@ -392,8 +388,7 @@
      *         to arrive and zero indicates the last to arrive
      * @throws InterruptedException if the current thread was interrupted
      *         while waiting
-     * @throws TimeoutException if the specified timeout elapses.
-     *         In this case the barrier will be broken.
+     * @throws TimeoutException if the specified timeout elapses
      * @throws BrokenBarrierException if <em>another</em> thread was
      *         interrupted or timed out while the current thread was
      *         waiting, or the barrier was reset, or the barrier was broken
diff --git a/luni/src/main/java/java/util/concurrent/DelayQueue.java b/luni/src/main/java/java/util/concurrent/DelayQueue.java
index d100a9c..e4a715e 100644
--- a/luni/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/luni/src/main/java/java/util/concurrent/DelayQueue.java
@@ -7,14 +7,9 @@
 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.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -42,7 +37,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
     implements BlockingQueue<E> {
@@ -162,9 +157,10 @@
         lock.lock();
         try {
             E first = q.peek();
-            return (first == null || first.getDelay(NANOSECONDS) > 0)
-                ? null
-                : q.poll();
+            if (first == null || first.getDelay(NANOSECONDS) > 0)
+                return null;
+            else
+                return q.poll();
         } finally {
             lock.unlock();
         }
@@ -187,7 +183,7 @@
                     available.await();
                 else {
                     long delay = first.getDelay(NANOSECONDS);
-                    if (delay <= 0L)
+                    if (delay <= 0)
                         return q.poll();
                     first = null; // don't retain ref while waiting
                     if (leader != null)
@@ -229,15 +225,15 @@
             for (;;) {
                 E first = q.peek();
                 if (first == null) {
-                    if (nanos <= 0L)
+                    if (nanos <= 0)
                         return null;
                     else
                         nanos = available.awaitNanos(nanos);
                 } else {
                     long delay = first.getDelay(NANOSECONDS);
-                    if (delay <= 0L)
+                    if (delay <= 0)
                         return q.poll();
-                    if (nanos <= 0L)
+                    if (nanos <= 0)
                         return null;
                     first = null; // don't retain ref while waiting
                     if (nanos < delay || leader != null)
@@ -466,7 +462,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;
@@ -488,8 +484,12 @@
      * unexpired) in this queue. The iterator does not return the
      * elements in any particular order.
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this queue
      */
diff --git a/luni/src/main/java/java/util/concurrent/Exchanger.java b/luni/src/main/java/java/util/concurrent/Exchanger.java
index 5f4c534..60871b4 100644
--- a/luni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/luni/src/main/java/java/util/concurrent/Exchanger.java
@@ -21,9 +21,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<>();
+ *   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
  *   DataBuffer initialEmptyBuffer = ... a made-up type
  *   DataBuffer initialFullBuffer = ...
  *
@@ -125,10 +125,9 @@
      * writing, there is no way to determine cacheline size, we define
      * a value that is enough for common platforms.  Additionally,
      * extra care elsewhere is taken to avoid other false/unintended
-     * sharing and to enhance locality, including adding padding (via
-     * @Contended) to Nodes, embedding "bound" as an Exchanger field,
-     * and reworking some park/unpark mechanics compared to
-     * LockSupport versions.
+     * sharing and to enhance locality, including adding padding to
+     * Nodes, embedding "bound" as an Exchanger field, and reworking
+     * some park/unpark mechanics compared to LockSupport versions.
      *
      * The arena starts out with only one used slot. We expand the
      * effective arena size by tracking collisions; i.e., failed CASes
@@ -275,9 +274,8 @@
 
     /**
      * Nodes hold partially exchanged data, plus other per-thread
-     * bookkeeping. Padded via @Contended to reduce memory contention.
+     * bookkeeping.
      */
-    //@jdk.internal.vm.annotation.Contended // android-removed
     static final class Node {
         int index;              // Arena index
         int bound;              // Last recorded value of Exchanger.bound
@@ -286,6 +284,10 @@
         Object item;            // This thread's current item
         volatile Object match;  // Item provided by releasing thread
         volatile Thread parked; // Set to this thread when parked, else null
+
+        // Padding to ameliorate unfortunate memory placements
+        Object p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb, pc, pd, pe, pf;
+        Object q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe, qf;
     }
 
     /** The corresponding thread local class */
@@ -294,7 +296,7 @@
     }
 
     /**
-     * Per-thread state.
+     * Per-thread state
      */
     private final Participant participant;
 
@@ -596,33 +598,37 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final sun.misc.Unsafe U;
     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
-                (Exchanger.class.getDeclaredField("bound"));
+                (ek.getDeclaredField("bound"));
             SLOT = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("slot"));
-
+                (ek.getDeclaredField("slot"));
             MATCH = U.objectFieldOffset
-                (Node.class.getDeclaredField("match"));
-
+                (nk.getDeclaredField("match"));
             BLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-
-            int scale = U.arrayIndexScale(Node[].class);
-            if ((scale & (scale - 1)) != 0 || scale > (1 << ASHIFT))
-                throw new Error("Unsupported array scale");
+                (tk.getDeclaredField("parkBlocker"));
+            s = U.arrayIndexScale(ak);
             // ABASE absorbs padding in front of element 0
-            ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
-        } catch (ReflectiveOperationException e) {
+            ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
+
+        } catch (Exception e) {
             throw new Error(e);
         }
+        if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
+            throw new Error("Unsupported array scale");
     }
 
 }
diff --git a/luni/src/main/java/java/util/concurrent/Executor.java b/luni/src/main/java/java/util/concurrent/Executor.java
index 9dd3efb..095ebfc 100644
--- a/luni/src/main/java/java/util/concurrent/Executor.java
+++ b/luni/src/main/java/java/util/concurrent/Executor.java
@@ -15,28 +15,30 @@
  * invoking {@code new Thread(new RunnableTask()).start()} for each
  * of a set of tasks, you might use:
  *
- * <pre> {@code
- * Executor executor = anExecutor();
+ * <pre>
+ * Executor executor = <em>anExecutor</em>;
  * 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();
@@ -48,7 +50,7 @@
  * 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<>();
  *   final Executor executor;
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java b/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
index cea0384..9514246 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
@@ -27,16 +27,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
@@ -47,31 +47,32 @@
  * 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<>(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;
+ *     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) {}
  *         }
- *       } 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> {
@@ -80,18 +81,15 @@
     private final BlockingQueue<Future<V>> completionQueue;
 
     /**
-     * FutureTask extension to enqueue upon completion.
+     * FutureTask extension to enqueue upon completion
      */
-    private static class QueueingFuture<V> extends FutureTask<Void> {
-        QueueingFuture(RunnableFuture<V> task,
-                       BlockingQueue<Future<V>> completionQueue) {
+    private class QueueingFuture extends FutureTask<Void> {
+        QueueingFuture(RunnableFuture<V> task) {
             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) {
@@ -151,14 +149,14 @@
     public Future<V> submit(Callable<V> task) {
         if (task == null) throw new NullPointerException();
         RunnableFuture<V> f = newTaskFor(task);
-        executor.execute(new QueueingFuture<V>(f, completionQueue));
+        executor.execute(new QueueingFuture(f));
         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<V>(f, completionQueue));
+        executor.execute(new QueueingFuture(f));
         return f;
     }
 
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorService.java b/luni/src/main/java/java/util/concurrent/ExecutorService.java
index ce7b2c6..58a2113 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorService.java
@@ -6,8 +6,8 @@
 
 package java.util.concurrent;
 
-import java.util.Collection;
 import java.util.List;
+import java.util.Collection;
 
 // BEGIN android-note
 // removed security manager docs
@@ -47,7 +47,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;
@@ -81,7 +81,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 {
diff --git a/luni/src/main/java/java/util/concurrent/Executors.java b/luni/src/main/java/java/util/concurrent/Executors.java
index 3d49b82..2068fd7 100644
--- a/luni/src/main/java/java/util/concurrent/Executors.java
+++ b/luni/src/main/java/java/util/concurrent/Executors.java
@@ -6,21 +6,17 @@
 
 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.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import sun.security.util.SecurityConstants;
+import java.security.PrivilegedActionException;
 
 // BEGIN android-note
 // removed security manager docs
 // END android-note
-
 /**
  * Factory and utility methods for {@link Executor}, {@link
  * ExecutorService}, {@link ScheduledExecutorService}, {@link
@@ -28,18 +24,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
@@ -82,6 +78,7 @@
      * @return the newly created thread pool
      * @throws IllegalArgumentException if {@code parallelism <= 0}
      * @since 1.8
+     * @hide
      */
     public static ExecutorService newWorkStealingPool(int parallelism) {
         return new ForkJoinPool
@@ -91,13 +88,12 @@
     }
 
     /**
-     * Creates a work-stealing thread pool using the number of
-     * {@linkplain Runtime#availableProcessors available processors}
+     * Creates a work-stealing thread pool using all
+     * {@link Runtime#availableProcessors available processors}
      * as its target parallelism level.
-     *
      * @return the newly created thread pool
-     * @see #newWorkStealingPool(int)
      * @since 1.8
+     * @hide
      */
     public static ExecutorService newWorkStealingPool() {
         return new ForkJoinPool
@@ -415,11 +411,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
      */
-    private static final class RunnableAdapter<T> implements Callable<T> {
-        private final Runnable task;
-        private final T result;
+    static final class RunnableAdapter<T> implements Callable<T> {
+        final Runnable task;
+        final T result;
         RunnableAdapter(Runnable task, T result) {
             this.task = task;
             this.result = result;
@@ -431,11 +427,11 @@
     }
 
     /**
-     * A callable that runs under established access control settings.
+     * A callable that runs under established access control settings
      */
-    private static final class PrivilegedCallable<T> implements Callable<T> {
-        final Callable<T> task;
-        final AccessControlContext acc;
+    static final class PrivilegedCallable<T> implements Callable<T> {
+        private final Callable<T> task;
+        private final AccessControlContext acc;
 
         PrivilegedCallable(Callable<T> task) {
             this.task = task;
@@ -458,13 +454,12 @@
 
     /**
      * A callable that runs under established access control settings and
-     * current ClassLoader.
+     * current ClassLoader
      */
-    private static final class PrivilegedCallableUsingCurrentClassLoader<T>
-            implements Callable<T> {
-        final Callable<T> task;
-        final AccessControlContext acc;
-        final ClassLoader ccl;
+    static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
+        private final Callable<T> task;
+        private final AccessControlContext acc;
+        private final ClassLoader ccl;
 
         PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
             // BEGIN android-removed
@@ -474,7 +469,7 @@
             //     // never trigger a security check, but we check
             //     // whether our callers have this permission anyways.
             //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
-
+            //
             //     // Whether setContextClassLoader turns out to be necessary
             //     // or not, we fail fast if permission is not available.
             //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
@@ -511,9 +506,9 @@
     }
 
     /**
-     * The default thread factory.
+     * The default thread factory
      */
-    private static class DefaultThreadFactory implements ThreadFactory {
+    static class DefaultThreadFactory implements ThreadFactory {
         private static final AtomicInteger poolNumber = new AtomicInteger(1);
         private final ThreadGroup group;
         private final AtomicInteger threadNumber = new AtomicInteger(1);
@@ -541,11 +536,11 @@
     }
 
     /**
-     * Thread factory capturing access control context and class loader.
+     * Thread factory capturing access control context and class loader
      */
-    private static class PrivilegedThreadFactory extends DefaultThreadFactory {
-        final AccessControlContext acc;
-        final ClassLoader ccl;
+    static class PrivilegedThreadFactory extends DefaultThreadFactory {
+        private final AccessControlContext acc;
+        private final ClassLoader ccl;
 
         PrivilegedThreadFactory() {
             super();
@@ -556,7 +551,7 @@
             //     // never trigger a security check, but we check
             //     // whether our callers have this permission anyways.
             //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
-
+            //
             //     // Fail fast
             //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
             // }
@@ -584,8 +579,7 @@
      * A wrapper class that exposes only the ExecutorService methods
      * of an ExecutorService implementation.
      */
-    private static class DelegatedExecutorService
-            extends AbstractExecutorService {
+    static class DelegatedExecutorService extends AbstractExecutorService {
         private final ExecutorService e;
         DelegatedExecutorService(ExecutorService executor) { e = executor; }
         public void execute(Runnable command) { e.execute(command); }
@@ -626,8 +620,8 @@
         }
     }
 
-    private static class FinalizableDelegatedExecutorService
-            extends DelegatedExecutorService {
+    static class FinalizableDelegatedExecutorService
+        extends DelegatedExecutorService {
         FinalizableDelegatedExecutorService(ExecutorService executor) {
             super(executor);
         }
@@ -640,7 +634,7 @@
      * A wrapper class that exposes only the ScheduledExecutorService
      * methods of a ScheduledExecutorService implementation.
      */
-    private static class DelegatedScheduledExecutorService
+    static class DelegatedScheduledExecutorService
             extends DelegatedExecutorService
             implements ScheduledExecutorService {
         private final ScheduledExecutorService e;
diff --git a/luni/src/main/java/java/util/concurrent/Flow.java b/luni/src/main/java/java/util/concurrent/Flow.java
deleted file mode 100644
index 75425f6..0000000
--- a/luni/src/main/java/java/util/concurrent/Flow.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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 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;
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
index 184d07a..41dd161 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -7,16 +7,11 @@
 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.locks.ReentrantLock;
-import java.util.concurrent.locks.LockSupport;
 
 /**
  * An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -36,7 +31,7 @@
  * ForkJoinPool}s may also be appropriate for use with event-style
  * tasks that are never joined.
  *
- * <p>A static {@link #commonPool()} is available and appropriate for
+ * <p>A static {@code commonPool()} is available and appropriate for
  * most applications. The common pool is used by any ForkJoinTask that
  * is not explicitly submitted to a specified pool. Using the common
  * pool normally reduces resource usage (its threads are slowly
@@ -45,9 +40,9 @@
  *
  * <p>For applications that require separate or custom pools, a {@code
  * ForkJoinPool} may be constructed with a given target parallelism
- * level; by default, equal to the number of available processors.
- * The pool attempts to maintain enough active (or available) threads
- * by dynamically adding, suspending, or resuming internal worker
+ * level; by default, equal to the number of available processors. The
+ * pool attempts to maintain enough active (or available) threads by
+ * dynamically adding, suspending, or resuming internal worker
  * threads, even if some tasks are stalled waiting to join others.
  * However, no such adjustments are guaranteed in the face of blocked
  * I/O or other unmanaged synchronization. The nested {@link
@@ -107,19 +102,12 @@
  * - the class name of a {@link ForkJoinWorkerThreadFactory}
  * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
  * - the class name of a {@link UncaughtExceptionHandler}
- * <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
- * - the maximum number of allowed extra threads to maintain target
- * parallelism (default 256).
  * </ul>
- * If a {@link SecurityManager} is present and no factory is
- * specified, then the default pool uses a factory supplying
- * threads that have no {@link Permissions} enabled.
  * The system class loader is used to load these classes.
  * Upon any error in establishing these settings, default parameters
  * are used. It is possible to disable or limit the use of threads in
  * the common pool by setting the parallelism property to zero, and/or
- * using a factory that may return {@code null}. However doing so may
- * cause unjoined tasks to never be executed.
+ * using a factory that may return {@code null}.
  *
  * <p><b>Implementation notes</b>: This implementation restricts the
  * maximum number of running threads to 32767. Attempts to create
@@ -133,7 +121,6 @@
  * @since 1.7
  * @author Doug Lea
  */
-//@jdk.internal.vm.annotation.Contended   // android-removed
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
@@ -146,14 +133,7 @@
      * that may be stolen by other workers.  Preference rules give
      * first priority to processing tasks from their own queues (LIFO
      * or FIFO, depending on mode), then to randomized FIFO steals of
-     * tasks in other queues.  This framework began as vehicle for
-     * supporting tree-structured parallelism using work-stealing.
-     * Over time, its scalability advantages led to extensions and
-     * changes to better support more diverse usage contexts.  Because
-     * most internal methods and nested classes are interrelated,
-     * their main rationale and descriptions are presented here;
-     * individual methods and nested classes contain only brief
-     * comments about details.
+     * tasks in other queues.
      *
      * WorkQueues
      * ==========
@@ -173,305 +153,200 @@
      * (http://research.sun.com/scalable/pubs/index.html) and
      * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
      * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
-     * The main differences ultimately stem from GC requirements that
-     * we null out taken slots as soon as we can, to maintain as small
-     * a footprint as possible even in programs generating huge
-     * numbers of tasks. To accomplish this, we shift the CAS
-     * 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)
-     * in a circular buffer:
-     *    q.array[q.top++ % length] = task;
-     *
-     * (The actual code needs to null-check and size-check the array,
-     * 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 ((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 ((the task at base slot is not null) and
-     *        (CAS slot to null))
-     *           increment base and return task;
-     *
-     * 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
+     * See also "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) visibly completes.
+     * analysis of memory ordering (atomic, volatile etc) issues.  The
+     * main differences ultimately stem from GC requirements that we
+     * null out taken slots as soon as we can, to maintain as small a
+     * footprint as possible even in programs generating huge numbers
+     * of tasks. To accomplish this, we shift the CAS arbitrating pop
+     * vs poll (steal) from being on the indices ("base" and "top") to
+     * the slots themselves.  So, both a successful pop and poll
+     * mainly entail a CAS of a slot from non-null to null.  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 must still be ordered in a way that guarantees 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. Note that this means
+     * that 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 scanning
-     * thief chooses a different random victim target to try next. So,
-     * in order for one thief to progress, it suffices for any
+     * 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
      * 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
-     * consider alternative actions, rather than method poll, which
-     * retries.)
+     * consider alternative actions, rather than method poll.)
      *
-     * This approach also enables support of a user mode in which
-     * 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.
+     * This approach also enables support of a user mode in which 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.)
      *
      * WorkQueues are also used in a similar way for tasks submitted
      * to the pool. We cannot mix these tasks in the same queues used
-     * by workers. Instead, we randomly associate submission queues
+     * for work-stealing (this would contaminate lifo/fifo
+     * processing). Instead, we randomly associate submission queues
      * with submitting threads, using a form of hashing.  The
-     * ThreadLocalRandom probe value serves as a hash code for
+     * Submitter probe value serves as a hash code for
      * choosing existing queues, and may be randomly repositioned upon
      * contention with other submitters.  In essence, submitters act
      * 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 but we use only a simple spinlock (using
+     * tasks that they submitted. However, because most
+     * shared/external queue operations are more expensive than
+     * internal, and because, at steady state, external submitters
+     * will compete for CPU with workers, ForkJoinTask.join and
+     * related methods disable them from repeatedly helping to process
+     * tasks if all workers are active.  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 bits in
      * 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.
+     * creating and registering new queues.
      *
      * Management
      * ==========
      *
      * The main throughput advantages of work-stealing stem from
      * decentralized control -- workers mostly take tasks from
-     * themselves or each other, at rates that can exceed a billion
-     * per second.  The pool itself creates, activates (enables
-     * scanning for and running tasks), deactivates, blocks, and
-     * terminates threads, all with minimal central information.
-     * There are only a few properties that we can globally track or
-     * maintain, so we pack them into a small number of variables,
-     * often maintaining atomicity without blocking or locking.
-     * Nearly all essentially atomic control state is held in two
-     * volatile variables that are by far most often read (not
-     * written) as status and consistency checks. (Also, field
-     * "config" holds unchanging configuration state.)
+     * themselves or each other. We cannot negate this in the
+     * implementation of other management responsibilities. The main
+     * tactic for avoiding bottlenecks is packing nearly all
+     * essentially atomic control state into two volatile variables
+     * that are by far most often read (not written) as status and
+     * consistency checks.
      *
-     * Field "ctl" contains 64 bits holding information needed to
-     * atomically decide to add, inactivate, enqueue (on an event
+     * Field "ctl" contains 64 bits holding all the information needed
+     * to atomically decide to add, inactivate, enqueue (on an event
      * queue), dequeue, and/or re-activate workers.  To enable this
      * packing, we restrict maximum parallelism to (1<<15)-1 (which is
      * far in excess of normal operating range) to allow ids, counts,
      * and their negations (used for thresholding) to fit into 16bit
-     * subfields.
+     * fields.
      *
-     * Field "runState" holds lifetime status, atomically and
-     * monotonically setting STARTED, SHUTDOWN, STOP, and finally
-     * TERMINATED bits.
+     * Field "plock" is a form of sequence lock with a saturating
+     * shutdown bit (similarly for per-queue "qlocks"), mainly
+     * protecting updates to the workQueues array, as well as to
+     * enable shutdown.  When used as a lock, it is normally only very
+     * briefly held, so is nearly always available after at most a
+     * brief spin, but we use a monitor-based backup strategy to
+     * block when needed.
      *
-     * 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.
-     *
-     * 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 (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
+     * Recording WorkQueues.  WorkQueues are recorded in the
+     * "workQueues" array that is created upon first use and expanded
+     * if necessary.  Updates to the array while recording new workers
+     * and unrecording terminated ones are protected from each other
+     * by a lock but the array is otherwise concurrently readable, and
+     * accessed directly.  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
-     * a weak reference mechanism. Thus for example the stack top
-     * subfield of ctl stores indices, not references.
+     * a weak reference mechanism. Thus for example the wait queue
+     * field of ctl stores indices, not references.  Access to the
+     * workQueues in associated methods (for example signalWork) must
+     * both index-check and null-check the IDs. All such accesses
+     * ignore bad IDs by returning out early from what they are doing,
+     * since this can only be associated with termination, in which
+     * case it is OK to give up.  All uses of the workQueues array
+     * also check that it is non-null (even if previously
+     * non-null). This allows nulling during termination, which is
+     * currently not necessary, but remains an option for
+     * resource-revocation-based shutdown schemes. It also helps
+     * reduce JIT issuance of uncommon-trap code, which tends to
+     * unnecessarily complicate control flow in some methods.
      *
-     * Queuing Idle Workers. Unlike HPC work-stealing frameworks, we
-     * cannot let workers spin indefinitely scanning for tasks when
-     * none can be found immediately, and we cannot start/resume
-     * workers unless there appear to be tasks available.  On the
-     * other hand, we must quickly prod them into action when new
-     * tasks are submitted or generated. In many usages, ramp-up time
-     * to activate workers is the main limiting factor in overall
-     * performance, which is compounded at program start-up by JIT
-     * compilation and allocation. So we streamline this as much as
-     * possible.
+     * Event Queuing. Unlike HPC work-stealing frameworks, we cannot
+     * let workers spin indefinitely scanning for tasks when none can
+     * be found immediately, and we cannot start/resume workers unless
+     * there appear to be tasks available.  On the other hand, we must
+     * quickly prod them into action when new tasks are submitted or
+     * generated. In many usages, ramp-up time to activate workers is
+     * the main limiting factor in overall performance (this is
+     * compounded at program start-up by JIT compilation and
+     * allocation). So we try to streamline this as much as possible.
+     * We park/unpark workers after placing in an event wait queue
+     * when they cannot find work. This "queue" is actually a simple
+     * Treiber stack, headed by the "id" field of ctl, plus a 15bit
+     * counter value (that reflects the number of times a worker has
+     * been inactivated) to avoid ABA effects (we need only as many
+     * version numbers as worker threads). Successors are held in
+     * field WorkQueue.nextWait.  Queuing deals with several intrinsic
+     * races, mainly 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. We solve this by requiring
+     * a full sweep of all workers (via repeated calls to method
+     * scan()) both before and after a newly waiting worker is added
+     * to the wait queue.  Because enqueued workers may actually be
+     * rescanning rather than waiting, we set and clear the "parker"
+     * field of WorkQueues to reduce unnecessary calls to unpark.
+     * (This requires a secondary recheck to avoid missed signals.)
+     * 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.
      *
-     * The "ctl" field atomically maintains active and total worker
-     * counts as well as a queue to place waiting threads so they can
-     * be located for signalling. Active counts also play the role of
-     * quiescence indicators, so are decremented when workers believe
-     * that there are no more tasks to execute. The "queue" is
-     * actually a form of Treiber stack.  A stack is ideal for
-     * 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 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
-     * worker: its index and status, plus a version counter that, in
-     * addition to the count subfields (also serving as version
-     * stamps) provide protection against Treiber stack ABA effects.
-     *
-     * 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
-     * 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.
-     * Worker index assignment avoids the bias in scanning that would
-     * occur if entries were sequentially packed starting at the front
-     * of the workQueues array. We treat the array as a simple
-     * power-of-two hash table, expanding as needed. The seedIndex
-     * increment ensures no collisions until a resize is needed or a
-     * worker is deregistered and replaced, and thereafter keeps
-     * 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 (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 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).
-     *
-     * Workers block (in method awaitWork) using park/unpark;
-     * advertising the need for signallers to unpark by setting their
-     * "parker" fields.
+     * Signalling.  We create or wake up workers only when there
+     * appears to be at least one task they might be able to find and
+     * execute.  When a submission is added or another worker adds a
+     * task to a queue that has fewer than two tasks, they signal
+     * waiting workers (or trigger creation of new ones if fewer than
+     * the given parallelism level -- signalWork).  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.  So in general, pools will be over-signalled. 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. Additionally, workers spin-down gradually, by staying
+     * alive so long as they see the ctl state changing.  Similar
+     * stability-sensing techniques are also used before blocking in
+     * awaitJoin and helpComplete.
      *
      * 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 given by IDLE_TIMEOUT_MS, increasing the
-     * period as the number of threads decreases, eventually removing
-     * all workers.
+     * time out and terminate if the pool has remained quiescent for a
+     * given period -- a short period if there are more threads than
+     * parallelism, longer as the number of threads decreases. This
+     * will slowly propagate, eventually terminating all workers after
+     * periods of non-use.
      *
-     * 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. 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.)
+     * Shutdown and Termination. A call to shutdownNow atomically sets
+     * a plock bit and then (non-atomically) sets each worker's
+     * qlock status, cancels all unprocessed tasks, and wakes up
+     * all waiting workers.  Detecting whether termination should
+     * commence after a non-abrupt shutdown() call requires more work
+     * and bookkeeping. We need consensus about quiescence (i.e., that
+     * there is no more work). The active count provides a primary
+     * indication but non-abrupt shutdown still requires a rechecking
+     * scan for any workers that are inactive but not queued.
      *
      * Joining Tasks
      * =============
@@ -482,9 +357,9 @@
      * just let them block (as in Thread.join).  We also cannot just
      * reassign the joiner's run-time stack with another and replace
      * it later, which would be a form of "continuation", that even if
-     * possible is not necessarily a good idea since we may need both
-     * an unblocked task and its continuation to progress.  Instead we
-     * combine two tactics:
+     * possible is not necessarily a good idea since we sometimes need
+     * both an unblocked task and its continuation to progress.
+     * Instead we combine two tactics:
      *
      *   Helping: Arranging for the joiner to execute some task that it
      *      would be running if the steal had not occurred.
@@ -504,16 +379,16 @@
      * The ManagedBlocker extension API can't use helping so relies
      * only on compensation in method awaitBlocker.
      *
-     * The algorithm in helpStealer entails a form of "linear
-     * helping".  Each worker records (in field currentSteal) the most
-     * recent task it stole from some other worker (or a submission).
-     * It also records (in field currentJoin) the task it is currently
-     * actively joining. Method helpStealer uses these markers to try
-     * to find a worker to help (i.e., steal back a task from and
-     * execute it) that could hasten completion of the actively joined
-     * task.  Thus, the joiner executes a task that would be on its
-     * own local deque had the to-be-joined task not been stolen. This
-     * is a conservative variant of the approach described in Wagner &
+     * The algorithm in tryHelpStealer entails a form of "linear"
+     * helping: Each worker records (in field currentSteal) the most
+     * recent task it stole from some other worker. Plus, it records
+     * (in field currentJoin) the task it is currently actively
+     * joining. Method tryHelpStealer uses these markers to try to
+     * find a worker to help (i.e., steal back a task from and execute
+     * it) that could hasten completion of the actively joined task.
+     * In essence, the joiner executes a task that would be on its own
+     * local deque had the to-be-joined task not been stolen. This may
+     * be seen as a conservative variant of the approach in Wagner &
      * Calder "Leapfrogging: a portable technique for implementing
      * efficient futures" SIGPLAN Notices, 1993
      * (http://portal.acm.org/citation.cfm?id=155354). It differs in
@@ -531,45 +406,31 @@
      * which means that we miss links in the chain during long-lived
      * tasks, GC stalls etc (which is OK since blocking in such cases
      * is usually a good idea).  (4) We bound the number of attempts
-     * to find work using checksums and fall back to suspending the
+     * to find work (see MAX_HELP) and fall back to suspending the
      * worker and if necessary replacing it with another.
      *
-     * Helping actions for CountedCompleters do not require tracking
-     * currentJoins: Method helpComplete takes and executes any task
-     * with the same root as the task being waited on (preferring
-     * local pops to non-local polls). However, this still entails
-     * some traversal of completer chains, so is less efficient than
-     * using CountedCompleters without explicit joins.
-     *
-     * Compensation does not aim to keep exactly the target
-     * parallelism number of unblocked threads running at any given
-     * time. Some previous versions of this class employed immediate
-     * compensations for any blocked join. However, in practice, the
-     * vast majority of blockages are transient byproducts of GC and
-     * other JVM or OS activities that are made worse by replacement.
-     * Currently, compensation is attempted only after validating that
-     * all purportedly active threads are processing tasks by checking
-     * field WorkQueue.scanState, which eliminates most false
-     * positives.  Also, compensation is bypassed (tolerating fewer
-     * threads) in the most common case in which it is rarely
-     * beneficial: when a worker with an empty queue (thus no
-     * 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 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
-     * pool (like all others) is imprecise.  Total worker counts are
-     * decremented when threads deregister, not when they exit and
-     * resources are reclaimed by the JVM and OS. So the number of
-     * simultaneously live threads may transiently exceed bounds.
+     * It is impossible to keep exactly the target parallelism number
+     * of threads running at any given time.  Determining the
+     * existence of conservatively safe helping targets, the
+     * availability of already-created spares, and the apparent need
+     * to create new spares are all racy, so we rely on multiple
+     * retries of each.  Compensation in the apparent absence of
+     * helping opportunities is challenging to control on JVMs, where
+     * GC and other activities can stall progress of tasks that in
+     * turn stall out many other dependent tasks, without us being
+     * able to determine whether they will ever require compensation.
+     * Even though work-stealing otherwise encounters little
+     * degradation in the presence of more threads than cores,
+     * aggressively adding new threads in such cases entails risk of
+     * unwanted positive feedback control loops in which more threads
+     * cause more dependent stalls (as well as delayed progress of
+     * unblocked threads to the point that we know they are available)
+     * leading to more situations requiring more threads, and so
+     * on. This aspect of control can be seen as an (analytically
+     * intractable) game with an opponent that may choose the worst
+     * (for us) active thread to stall at any time.  We take several
+     * precautions to bound losses (and thus bound gains), mainly in
+     * methods tryCompensate and awaitJoin.
      *
      * Common Pool
      * ===========
@@ -579,52 +440,24 @@
      * never be used, we minimize initial construction overhead and
      * footprint to the setup of about a dozen fields, with no nested
      * allocation. Most bootstrapping occurs within method
-     * externalSubmit during the first submission to the pool.
+     * fullExternalPush during the first submission to the pool.
      *
      * When external threads submit to the common pool, they can
-     * perform subtask processing (see externalHelpComplete and
-     * related methods) upon joins.  This caller-helps policy makes it
-     * sensible to set common pool parallelism level to one (or more)
-     * less than the total number of available cores, or even zero for
-     * pure caller-runs.  We do not need to record whether external
-     * submissions are to the common pool -- if not, external help
-     * methods return quickly. These submitters would otherwise be
-     * blocked waiting for completion, so the extra effort (with
-     * liberally sprinkled task status checks) in inapplicable cases
-     * amounts to an odd form of limited spin-wait before blocking in
-     * ForkJoinTask.join.
-     *
-     * As a more appropriate default in managed environments, unless
-     * overridden by system properties, we use workers of subclass
-     * InnocuousForkJoinWorkerThread when there is a SecurityManager
-     * present. These workers have no permissions set, do not belong
-     * to any user-defined ThreadGroup, and erase all ThreadLocals
-     * after executing any top-level task (see WorkQueue.runTask).
-     * The associated mechanics (mainly in ForkJoinWorkerThread) may
-     * be JVM-dependent and must access particular Thread class fields
-     * to achieve this effect.
+     * perform subtask processing (see externalHelpJoin and related
+     * methods).  This caller-helps policy makes it sensible to set
+     * common pool parallelism level to one (or more) less than the
+     * total number of available cores, or even zero for pure
+     * caller-runs.  We do not need to record whether external
+     * submissions are to the common pool -- if not, externalHelpJoin
+     * returns quickly (at the most helping to signal some common pool
+     * workers). These submitters would otherwise be blocked waiting
+     * for completion, so the extra effort (with liberally sprinkled
+     * task status checks) in inapplicable cases amounts to an odd
+     * form of limited spin-wait before blocking in ForkJoinTask.join.
      *
      * Style notes
      * ===========
      *
-     * Memory ordering relies mainly on Unsafe intrinsics that carry
-     * the further responsibility of explicitly performing null- and
-     * bounds- checks otherwise carried out implicitly by JVMs.  This
-     * can be awkward and ugly, but also reflects the need to control
-     * outcomes across the unusual cases that arise in very racy code
-     * with very few invariants. So these explicit checks would exist
-     * in some form anyway.  All fields are read into locals before
-     * use, and null-checked if they are references.  This is usually
-     * done in a "C"-like style of listing declarations at the heads
-     * of methods or blocks, and using inline assignments on first
-     * encounter.  Array bounds-checks are usually performed by
-     * masking with array.length-1, which relies on the invariant that
-     * these arrays are created with positive lengths, which is itself
-     * paranoically checked. Nearly all explicit checks lead to
-     * bypass/return, not exception throws, because they may
-     * legitimately arise due to cancellation/revocation during
-     * shutdown.
-     *
      * There is a lot of representation-level coupling among classes
      * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask.  The
      * fields of WorkQueue maintain data structures managed by
@@ -632,13 +465,22 @@
      * trying to reduce this, since any associated future changes in
      * representations will need to be accompanied by algorithmic
      * changes anyway. Several methods intrinsically sprawl because
-     * they must accumulate sets of consistent reads of fields held in
-     * local variables.  There are also other coding oddities
-     * (including several unnecessary-looking hoisted null checks)
-     * that help some methods perform reasonably even when interpreted
-     * (not compiled).
+     * they must accumulate sets of consistent reads of volatiles held
+     * in local variables.  Methods signalWork() and scan() are the
+     * main bottlenecks, so are especially heavily
+     * micro-optimized/mangled.  There are lots of inline assignments
+     * (of form "while ((local = field) != 0)") which are usually the
+     * simplest way to ensure the required read orderings (which are
+     * sometimes critical). This leads to a "C"-like style of listing
+     * declarations of these locals at the heads of methods or blocks.
+     * There are several occurrences of the unusual "do {} while
+     * (!cas...)"  which is the simplest way to force an update of a
+     * CAS'ed variable. There are also other coding oddities (including
+     * several unnecessary-looking hoisted null checks) that help
+     * some methods perform reasonably even when interpreted (not
+     * compiled).
      *
-     * The order of declarations in this file is (with a few exceptions):
+     * The order of declarations in this file is:
      * (1) Static utility functions
      * (2) Nested (static) classes
      * (3) Static fields
@@ -648,6 +490,7 @@
      * (7) Exported methods
      * (8) Static block initializing statics in minimally dependent order
      */
+    // android-note: Removed references to CountedCompleters.
 
     // Static utilities
 
@@ -674,8 +517,7 @@
          * Returns a new worker thread operating in the given pool.
          *
          * @param pool the pool this thread works in
-         * @return the new worker thread, or {@code null} if the request
-         *         to create a thread is rejected
+         * @return the new worker thread
          * @throws NullPointerException if the pool is null
          */
         public ForkJoinWorkerThread newThread(ForkJoinPool pool);
@@ -685,7 +527,7 @@
      * Default ForkJoinWorkerThreadFactory implementation; creates a
      * new ForkJoinWorkerThread.
      */
-    private static final class DefaultForkJoinWorkerThreadFactory
+    static final class DefaultForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
             return new ForkJoinWorkerThread(pool);
@@ -698,7 +540,7 @@
      * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
      * actually do anything beyond having a unique identity.
      */
-    private static final class EmptyTask extends ForkJoinTask<Void> {
+    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; }
@@ -707,54 +549,54 @@
     }
 
     /**
-     * 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
-    static final int SMASK        = 0xffff;        // short bits == max index
-    static final int MAX_CAP      = 0x7fff;        // max #workers - 1
-    static final int EVENMASK     = 0xfffe;        // even short bits
-    static final int SQMASK       = 0x007e;        // max 64 (even) slots
-
-    // Masks and units for WorkQueue.scanState and ctl sp subfield
-    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 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
-     * submission. See above for descriptions and algorithms.
+     * submission. See above for main rationale and algorithms.
+     * Implementation relies heavily on "Unsafe" intrinsics
+     * and selective use of "volatile":
+     *
+     * Field "base" is the index (mod array.length) of the least valid
+     * queue slot, which is always the next position to steal (poll)
+     * from if nonempty. Reads and writes require volatile orderings
+     * but not CAS, because updates are only performed after slot
+     * CASes.
+     *
+     * Field "top" is the index (mod array.length) of the next queue
+     * slot to push to or pop from. It is written only by owner thread
+     * for push, or under lock for external/shared push, and accessed
+     * by other threads only after reading (volatile) base.  Both top
+     * and base are allowed to wrap around on overflow, but (top -
+     * base) (or more commonly -(base - top) to force volatile read of
+     * base before top) still estimates size. The lock ("qlock") is
+     * forced to -1 on termination, causing all further lock attempts
+     * to fail. (Note: we don't need CAS for termination state because
+     * upon pool shutdown, all shared-queues will stop being used
+     * anyway.)  Nearly all lock bodies are set up so that exceptions
+     * within lock bodies are "impossible" (modulo JVM errors that
+     * would cause failure anyway.)
+     *
+     * The array slots are read and written using the emulation of
+     * volatiles/atomics provided by Unsafe. Insertions must in
+     * general use putOrderedObject as a form of releasing store to
+     * ensure that all writes to the task object are ordered before
+     * its publication in the queue.  All removals entail a CAS to
+     * null.  The array is always a power of two. To ensure safety of
+     * Unsafe array operations, all accesses perform explicit null
+     * checks and implicit bounds checks via power-of-two masking.
+     *
+     * In addition to basic queuing support, this class contains
+     * fields described elsewhere to control execution. It turns out
+     * to work better memory-layout-wise to include them in this class
+     * rather than a separate class.
+     *
      * Performance on most platforms is very sensitive to placement of
      * instances of both WorkQueues and their arrays -- we absolutely
      * do not want multiple WorkQueue instances or multiple queue
-     * arrays sharing cache lines. The @Contended annotation alerts
-     * JVMs to try to keep instances apart.
+     * arrays sharing cache lines. (It would be best for queue objects
+     * and their arrays to share, but there is nothing available to
+     * help arrange that). The @Contended annotation alerts JVMs to
+     * try to keep instances apart.
      */
-    //@jdk.internal.vm.annotation.Contended   // android-removed
     static final class WorkQueue {
-
         /**
          * Capacity of work-stealing queue array upon initialization.
          * Must be a power of two; at least 4, but should be larger to
@@ -775,44 +617,43 @@
          */
         static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 
-        // Instance fields
+        // Heuristic padding to ameliorate unfortunate memory placements
+        volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
 
-        volatile int scanState;    // versioned, negative if inactive
-        int stackPred;             // pool stack (ctl) predecessor
+        volatile int eventCount;   // encoded inactivation count; < 0 if inactive
+        int nextWait;              // encoded record of next event waiter
         int nsteals;               // number of steals
-        int hint;                  // randomization and stealer index hint
-        int config;                // pool index and mode
-        volatile int qlock;        // 1: locked, < 0: terminate; else 0
+        int hint;                  // steal index hint
+        short poolIndex;           // index of this queue in pool
+        final short mode;          // 0: lifo, > 0: fifo, < 0: shared
+        volatile int qlock;        // 1: locked, -1: terminate; else 0
         volatile int base;         // index of next slot for poll
         int top;                   // index of next slot for push
         ForkJoinTask<?>[] array;   // the elements (initially unallocated)
         final ForkJoinPool pool;   // the containing pool (may be null)
         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<?> currentJoin;  // task being joined in awaitJoin
+        ForkJoinTask<?> currentSteal; // current non-local task being executed
 
-      // @jdk.internal.vm.annotation.Contended("group2") // segregate // android-removed
-        volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
+        volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+        volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d;
 
-        WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
+        WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
+                  int seed) {
             this.pool = pool;
             this.owner = owner;
+            this.mode = (short)mode;
+            this.hint = seed; // store initial seed for runWorker
             // Place indices in the center of array (that is not yet allocated)
             base = top = INITIAL_QUEUE_CAPACITY >>> 1;
         }
 
         /**
-         * Returns an exportable index (used by ForkJoinWorkerThread).
-         */
-        final int getPoolIndex() {
-            return (config & 0xffff) >>> 1; // ignore odd/even tag bit
-        }
-
-        /**
          * Returns the approximate number of tasks in the queue.
          */
         final int queueSize() {
-            int n = base - top;       // read base first
+            int n = base - top;       // non-owner callers must read base first
             return (n >= 0) ? 0 : -n; // ignore transient negative
         }
 
@@ -822,31 +663,32 @@
          * near-empty queue has at least one unclaimed task.
          */
         final boolean isEmpty() {
-            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)));
+            ForkJoinTask<?>[] a; int m, s;
+            int n = base - (s = top);
+            return (n >= 0 ||
+                    (n == -1 &&
+                     ((a = array) == null ||
+                      (m = a.length - 1) < 0 ||
+                      U.getObject
+                      (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
         }
 
         /**
-         * Pushes a task. Call only by owner in unshared queues.
+         * Pushes a task. Call only by owner in unshared queues.  (The
+         * shared-queue version is embedded in method externalPush.)
          *
          * @param task the task. Caller must ensure non-null.
          * @throws RejectedExecutionException if array cannot be resized
          */
         final void push(ForkJoinTask<?> task) {
-            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 (al + d == 1)
+            ForkJoinTask<?>[] a; ForkJoinPool p;
+            int s = top, n;
+            if ((a = array) != null) {    // ignore if queue removed
+                int m = a.length - 1;
+                U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
+                if ((n = (top = s + 1) - base) <= 2)
+                    (p = pool).signalWork(p.workQueues, this);
+                else if (n >= m)
                     growArray();
             }
         }
@@ -859,23 +701,22 @@
         final ForkJoinTask<?>[] growArray() {
             ForkJoinTask<?>[] oldA = array;
             int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
-            if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY)
+            if (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
-                    int index = b & oldMask;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> x = (ForkJoinTask<?>)
-                        U.getObjectVolatile(oldA, offset);
+                do {
+                    ForkJoinTask<?> x;
+                    int oldj = ((b & oldMask) << ASHIFT) + ABASE;
+                    int j    = ((b &    mask) << ASHIFT) + ABASE;
+                    x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
                     if (x != null &&
-                        U.compareAndSwapObject(oldA, offset, x, null))
-                        a[b & mask] = x;
+                        U.compareAndSwapObject(oldA, oldj, x, null))
+                        U.putObjectVolatile(a, j, x);
                 } while (++b != t);
-                U.storeFence();
             }
             return a;
         }
@@ -885,16 +726,16 @@
          * by owner in unshared queues.
          */
         final ForkJoinTask<?> pop() {
-            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;
+            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)) {
+                        top = s;
+                        return t;
+                    }
                 }
             }
             return null;
@@ -903,18 +744,15 @@
         /**
          * Takes a task in FIFO order if b is base of queue and a task
          * can be claimed without contention. Specialized versions
-         * appear in ForkJoinPool methods scan and helpStealer.
+         * appear in ForkJoinPool methods scan and tryHelpStealer.
          */
         final ForkJoinTask<?> pollAt(int b) {
-            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;
+            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)) {
+                    U.putOrderedInt(this, QBASE, b + 1);
                     return t;
                 }
             }
@@ -925,27 +763,21 @@
          * Takes next task, if one exists, in FIFO order.
          */
         final ForkJoinTask<?> poll() {
-            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
+            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 (t != null) {
+                    if (U.compareAndSwapObject(a, j, t, null)) {
+                        U.putOrderedInt(this, QBASE, b + 1);
+                        return t;
                     }
                 }
-                else
-                    break;
+                else if (base == b) {
+                    if (b + 1 == top)
+                        break;
+                    Thread.yield(); // wait for lagging update (very rare)
+                }
             }
             return null;
         }
@@ -954,350 +786,218 @@
          * Takes next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> nextLocalTask() {
-            return (config < 0) ? poll() : pop();
+            return mode == 0 ? pop() : poll();
         }
 
         /**
          * Returns next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> peek() {
-            int al; ForkJoinTask<?>[] a;
-            return ((a = array) != null && (al = a.length) > 0) ?
-                a[(al - 1) & (config < 0 ? base : top - 1)] : null;
+            ForkJoinTask<?>[] a = array; int m;
+            if (a == null || (m = a.length - 1) < 0)
+                return null;
+            int i = mode == 0 ? top - 1 : base;
+            int j = ((i & m) << ASHIFT) + ABASE;
+            return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
         }
 
         /**
          * 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<?> 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;
-                }
+        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)) {
+                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 tryUnpush.
-         */
-        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 (top == s + 1 && array == a &&
-                        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() {
-            ForkJoinTask<?> t;
-            if ((t = currentJoin) != null) {
-                currentJoin = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            if ((t = currentSteal) != null) {
-                currentSteal = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            while ((t = poll()) != null)
+            ForkJoinTask.cancelIgnoringExceptions(currentJoin);
+            ForkJoinTask.cancelIgnoringExceptions(currentSteal);
+            for (ForkJoinTask<?> t; (t = poll()) != null; )
                 ForkJoinTask.cancelIgnoringExceptions(t);
         }
 
         // Specialized execution methods
 
         /**
-         * Pops and executes up to POLL_LIMIT tasks or until empty.
+         * Polls and runs tasks until empty.
          */
-        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;
-            }
+        final void pollAndExecAll() {
+            for (ForkJoinTask<?> t; (t = poll()) != null;)
+                t.doExec();
         }
 
         /**
-         * Polls and executes up to POLL_LIMIT tasks or until empty.
-         */
-        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 (++nexec > POLL_LIMIT)
-                            break;
-                    }
-                }
-                else
-                    break;
-            }
-        }
-
-        /**
-         * Executes the given task and (some) remaining local tasks.
+         * Executes a top-level task and any local tasks remaining
+         * after execution.
          */
         final void runTask(ForkJoinTask<?> task) {
-            if (task != null) {
+            if ((currentSteal = task) != null) {
                 task.doExec();
-                if (config < 0)
-                    localPollAndExec();
-                else
-                    localPopAndExec();
-                int ns = ++nsteals;
-                ForkJoinWorkerThread thread = owner;
+                ForkJoinTask<?>[] a = array;
+                int md = mode;
+                ++nsteals;
                 currentSteal = null;
-                if (ns < 0)           // collect on overflow
-                    transferStealCount(pool);
-                if (thread != null)
-                    thread.afterTopLevelExec();
-            }
-        }
-
-        /**
-         * Adds steal count to pool steal count if it exists, and resets.
-         */
-        final void transferStealCount(ForkJoinPool p) {
-            AuxState aux;
-            if (p != null && (aux = p.auxState) != null) {
-                long s = nsteals;
-                nsteals = 0;            // if negative, correct for overflow
-                if (s < 0) s = Integer.MAX_VALUE;
-                aux.lock();
-                try {
-                    aux.stealCount += s;
-                } finally {
-                    aux.unlock();
+                if (md != 0)
+                    pollAndExecAll();
+                else if (a != null) {
+                    int s, m = a.length - 1;
+                    while ((s = top - 1) - base >= 0) {
+                        long i = ((m & s) << ASHIFT) + ABASE;
+                        ForkJoinTask<?> t = (ForkJoinTask<?>)U.getObject(a, i);
+                        if (t == null)
+                            break;
+                        if (U.compareAndSwapObject(a, i, t, null)) {
+                            top = s;
+                            t.doExec();
+                        }
+                    }
                 }
             }
         }
 
         /**
          * If present, removes from queue and executes the given task,
-         * or any other cancelled task. Used only by awaitJoin.
+         * or any other cancelled task. Returns (true) on any CAS
+         * or consistency check failure so caller can retry.
          *
-         * @return true if queue empty and task not known to be done
+         * @return false if no progress can be made, else true
          */
         final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
-            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, offset, t, null)) {
-                                    top = s;
-                                    removed = true;
-                                }
-                            }
-                            else if (base == b)      // replace with proxy
-                                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, offset, t, null)) {
-                                top = s;
-                            }
-                            break;                  // was cancelled
-                        }
-                        else if (++d == 0) {
-                            if (base != b)          // rescan
+            boolean stat;
+            ForkJoinTask<?>[] a; int m, s, b, n;
+            if (task != null && (a = array) != null && (m = a.length - 1) >= 0 &&
+                (n = (s = top) - (b = base)) > 0) {
+                boolean removed = false, empty = true;
+                stat = true;
+                for (ForkJoinTask<?> t;;) {           // traverse from s to b
+                    long j = ((--s & m) << ASHIFT) + ABASE;
+                    t = (ForkJoinTask<?>)U.getObject(a, j);
+                    if (t == null)                    // inconsistent length
+                        break;
+                    else if (t == task) {
+                        if (s + 1 == top) {           // pop
+                            if (!U.compareAndSwapObject(a, j, task, null))
                                 break;
-                            return false;
+                            top = s;
+                            removed = true;
                         }
+                        else if (base == b)           // replace with proxy
+                            removed = U.compareAndSwapObject(a, j, task,
+                                                             new EmptyTask());
+                        break;
                     }
-                    if (task.status < 0)
-                        return false;
-                }
-            }
-            return true;
-        }
-
-        /**
-         * Pops task if in the same CC computation as the given task,
-         * in either shared or owned mode. Used only by helpComplete.
-         */
-        final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
-            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 & IS_OWNED) == 0) {
-                                boolean popped = false;
-                                if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                                    if (top == s && array == a &&
-                                        U.compareAndSwapObject(a, offset,
-                                                               t, null)) {
-                                        popped = true;
-                                        top = s - 1;
-                                    }
-                                    U.putOrderedInt(this, QLOCK, 0);
-                                    if (popped)
-                                        return t;
-                                }
-                            }
-                            else if (U.compareAndSwapObject(a, offset,
-                                                            t, null)) {
-                                top = s - 1;
-                                return t;
-                            }
-                            break;
-                        }
-                        else if ((r = r.completer) == null) // try parent
-                            break;
+                    else if (t.status >= 0)
+                        empty = false;
+                    else if (s + 1 == top) {          // pop and throw away
+                        if (U.compareAndSwapObject(a, j, t, null))
+                            top = s;
+                        break;
+                    }
+                    if (--n == 0) {
+                        if (!empty && base == b)
+                            stat = false;
+                        break;
                     }
                 }
-            }
-            return null;
-        }
-
-        /**
-         * Steals and runs a task in the same CC computation as the
-         * given task if one exists and can be taken without
-         * contention. Otherwise returns a checksum/control value for
-         * use by method helpComplete.
-         *
-         * @return 1 if successful, 2 if retryable (lost to another
-         * stealer), -1 if non-empty but no matching task found, else
-         * the base index, forced negative.
-         */
-        final int pollAndExecCC(CountedCompleter<?> task) {
-            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
-                else {
-                    CountedCompleter<?> t = (CountedCompleter<?>)o;
-                    for (CountedCompleter<?> r = t;;) {
-                        if (r == task) {
-                            if (b++ == base &&
-                                U.compareAndSwapObject(a, offset, t, null)) {
-                                base = b;
-                                t.doExec();
-                                h = 1;          // success
-                            }
-                            else
-                                h = 2;          // lost CAS
-                            break;
-                        }
-                        else if ((r = r.completer) == null) {
-                            h = -1;             // unmatched
-                            break;
-                        }
-                    }
-                }
+                if (removed)
+                    task.doExec();
             }
             else
-                h = b | Integer.MIN_VALUE;      // to sense movement on re-poll
-            return h;
+                stat = false;
+            return stat;
+        }
+
+        /**
+         * Tries to poll for and execute the given task or any other
+         * task in its CountedCompleter computation.
+         */
+        final boolean pollAndExecCC(CountedCompleter<?> root) {
+            ForkJoinTask<?>[] a; int b; Object o; CountedCompleter<?> t, r;
+            if ((b = base) - top < 0 && (a = array) != null) {
+                long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                if ((o = U.getObjectVolatile(a, j)) == null)
+                    return true; // retry
+                if (o instanceof CountedCompleter) {
+                    for (t = (CountedCompleter<?>)o, r = t;;) {
+                        if (r == root) {
+                            if (base == b &&
+                                U.compareAndSwapObject(a, j, t, null)) {
+                                U.putOrderedInt(this, QBASE, b + 1);
+                                t.doExec();
+                            }
+                            return true;
+                        }
+                        else if ((r = r.completer) == null)
+                            break; // not part of root computation
+                    }
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Tries to pop and execute the given task or any other task
+         * in its CountedCompleter computation.
+         */
+        final boolean externalPopAndExecCC(CountedCompleter<?> root) {
+            ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
+            if (base - (s = top) < 0 && (a = array) != null) {
+                long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+                if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
+                    for (t = (CountedCompleter<?>)o, r = t;;) {
+                        if (r == root) {
+                            if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+                                if (top == s && array == a &&
+                                    U.compareAndSwapObject(a, j, t, null)) {
+                                    top = s - 1;
+                                    qlock = 0;
+                                    t.doExec();
+                                }
+                                else
+                                    qlock = 0;
+                            }
+                            return true;
+                        }
+                        else if ((r = r.completer) == null)
+                            break;
+                    }
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Internal version
+         */
+        final boolean internalPopAndExecCC(CountedCompleter<?> root) {
+            ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
+            if (base - (s = top) < 0 && (a = array) != null) {
+                long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+                if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
+                    for (t = (CountedCompleter<?>)o, r = t;;) {
+                        if (r == root) {
+                            if (U.compareAndSwapObject(a, j, t, null)) {
+                                top = s - 1;
+                                t.doExec();
+                            }
+                            return true;
+                        }
+                        else if ((r = r.completer) == null)
+                            break;
+                    }
+                }
+            }
+            return false;
         }
 
         /**
@@ -1305,28 +1005,34 @@
          */
         final boolean isApparentlyUnblocked() {
             Thread wt; Thread.State s;
-            return (scanState >= 0 &&
+            return (eventCount >= 0 &&
                     (wt = owner) != null &&
                     (s = wt.getState()) != Thread.State.BLOCKED &&
                     s != Thread.State.WAITING &&
                     s != Thread.State.TIMED_WAITING);
         }
 
-        // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        // Unsafe mechanics
+        private static final sun.misc.Unsafe U;
+        private static final long QBASE;
         private static final long QLOCK;
         private static final int ABASE;
         private static final int ASHIFT;
         static {
             try {
+                U = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = WorkQueue.class;
+                Class<?> ak = ForkJoinTask[].class;
+                QBASE = U.objectFieldOffset
+                    (k.getDeclaredField("base"));
                 QLOCK = U.objectFieldOffset
-                    (WorkQueue.class.getDeclaredField("qlock"));
-                ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-                int scale = U.arrayIndexScale(ForkJoinTask[].class);
+                    (k.getDeclaredField("qlock"));
+                ABASE = U.arrayBaseOffset(ak);
+                int scale = U.arrayIndexScale(ak);
                 if ((scale & (scale - 1)) != 0)
-                    throw new Error("array index scale not a power of two");
+                    throw new Error("data type scale not a power of two");
                 ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-            } catch (ReflectiveOperationException e) {
+            } catch (Exception e) {
                 throw new Error(e);
             }
         }
@@ -1335,6 +1041,15 @@
     // static fields (initialized in static initializer below)
 
     /**
+     * Per-thread submission bookkeeping. Shared across all pools
+     * to reduce ThreadLocal pollution and because random motion
+     * to avoid contention in one pool is likely to hold for others.
+     * Lazily initialized on first submission (but null-checked
+     * in other contexts to avoid unnecessary initialization).
+     */
+    static final ThreadLocal<Submitter> submitters;
+
+    /**
      * Creates a new ForkJoinWorkerThread. This factory is used unless
      * overridden in ForkJoinPool constructors.
      */
@@ -1343,9 +1058,9 @@
 
     /**
      * Permission required for callers of methods that may start or
-     * kill threads.  Also used as a static lock in tryInitialize.
+     * kill threads.
      */
-    static final RuntimePermission modifyThreadPermission;
+    private static final RuntimePermission modifyThreadPermission;
 
     /**
      * Common (static) pool. Non-null for public use unless a static
@@ -1361,12 +1076,7 @@
      * common.parallelism field to be zero, but in that case still report
      * parallelism as 1 to reflect resulting caller-runs mechanics.
      */
-    static final int COMMON_PARALLELISM;
-
-    /**
-     * Limit on spare thread construction in tryCompensate.
-     */
-    private static final int COMMON_MAX_SPARES;
+    static final int commonParallelism;
 
     /**
      * Sequence number for creating workerNamePrefix.
@@ -1381,215 +1091,270 @@
         return ++poolNumberSequence;
     }
 
-    // static configuration constants
+    // static constants
 
     /**
-     * Initial timeout value (in milliseconds) for the thread
+     * Initial timeout value (in nanoseconds) 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_MS = 2000L; // 2sec
+    private static final long IDLE_TIMEOUT      = 2000L * 1000L * 1000L; // 2sec
 
     /**
-     * Tolerance for idle timeouts, to cope with timer undershoots.
+     * Timeout value when there are more threads than parallelism level
      */
-    private static final long TIMEOUT_SLOP_MS =   20L; // 20ms
+    private static final long FAST_IDLE_TIMEOUT =  200L * 1000L * 1000L;
 
     /**
-     * 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.
+     * Tolerance for idle timeouts, to cope with timer undershoots
      */
-    private static final int DEFAULT_COMMON_MAX_SPARES = 256;
+    private static final long TIMEOUT_SLOP = 2000000L;
+
+    /**
+     * The maximum stolen->joining link depth allowed in method
+     * tryHelpStealer.  Must be a power of two.  Depths for legitimate
+     * chains are unbounded, but we use a fixed constant to avoid
+     * (otherwise unchecked) cycles and to bound staleness of
+     * traversal parameters at the expense of sometimes blocking when
+     * we could be helping.
+     */
+    private static final int MAX_HELP = 64;
 
     /**
      * Increment for seed generators. See class ThreadLocal for
      * explanation.
      */
-    private static final int SEED_INCREMENT = 0x9e3779b9;
+    private static final int SEED_INCREMENT = 0x61c88647;
 
     /*
-     * Bits and masks for field ctl, packed with 4 16 bit subfields:
-     * AC: Number of active running workers minus target parallelism
-     * TC: Number of total workers minus target parallelism
-     * SS: version count and status of top waiting thread
-     * ID: poolIndex of top of Treiber stack of waiters
+     * Bits and masks for control variables
      *
-     * When convenient, we can extract the lower 32 stack top bits
-     * (including version bits) as sp=(int)ctl.  The offsets of counts
-     * by the target parallelism and the positionings of fields makes
-     * it possible to perform the most common checks via sign tests of
-     * fields: When ac is negative, there are not enough active
-     * workers, when tc is negative, there are not enough total
-     * workers.  When sp is non-zero, there are waiting workers.  To
-     * deal with possibly negative fields, we use casts in and out of
-     * "short" and/or signed shifts to maintain signedness.
+     * Field ctl is a long packed with:
+     * AC: Number of active running workers minus target parallelism (16 bits)
+     * TC: Number of total workers minus target parallelism (16 bits)
+     * ST: true if pool is terminating (1 bit)
+     * EC: the wait count of top waiting thread (15 bits)
+     * ID: poolIndex of top of Treiber stack of waiters (16 bits)
      *
-     * Because it occupies uppermost bits, we can add one active count
-     * using getAndAddLong of AC_UNIT, rather than CAS, when returning
-     * from a blocked join.  Other updates entail multiple subfields
-     * and masking, requiring CAS.
+     * When convenient, we can extract the upper 32 bits of counts and
+     * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
+     * (int)ctl.  The ec field is never accessed alone, but always
+     * together with id and st. The offsets of counts by the target
+     * parallelism and the positionings of fields makes it possible to
+     * perform the most common checks via sign tests of fields: When
+     * ac is negative, there are not enough active workers, when tc is
+     * negative, there are not enough total workers, and when e is
+     * negative, the pool is terminating.  To deal with these possibly
+     * negative fields, we use casts in and out of "short" and/or
+     * signed shifts to maintain signedness.
+     *
+     * When a thread is queued (inactivated), its eventCount field is
+     * set negative, which is the only way to tell if a worker is
+     * prevented from executing tasks, even though it must continue to
+     * scan for them to avoid queuing races. Note however that
+     * eventCount updates lag releases so usage requires care.
+     *
+     * Field plock is an int packed with:
+     * SHUTDOWN: true if shutdown is enabled (1 bit)
+     * SEQ:  a sequence lock, with PL_LOCK bit set if locked (30 bits)
+     * SIGNAL: set when threads may be waiting on the lock (1 bit)
+     *
+     * The sequence number enables simple consistency checks:
+     * Staleness of read-only operations on the workQueues array can
+     * be checked by comparing plock before vs after the reads.
      */
 
-    // Lower and upper word masks
-    private static final long SP_MASK    = 0xffffffffL;
-    private static final long UC_MASK    = ~SP_MASK;
-
-    // Active counts
+    // bit positions/shifts for fields
     private static final int  AC_SHIFT   = 48;
-    private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
-    private static final long AC_MASK    = 0xffffL << AC_SHIFT;
-
-    // Total counts
     private static final int  TC_SHIFT   = 32;
-    private static final long TC_UNIT    = 0x0001L << TC_SHIFT;
-    private static final long TC_MASK    = 0xffffL << TC_SHIFT;
-    private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
+    private static final int  ST_SHIFT   = 31;
+    private static final int  EC_SHIFT   = 16;
 
-    // runState bits: SHUTDOWN must be negative, others arbitrary powers of two
-    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;
+    // bounds
+    private static final int  SMASK      = 0xffff;  // short bits
+    private static final int  MAX_CAP    = 0x7fff;  // max #workers - 1
+    private static final int  EVENMASK   = 0xfffe;  // even short bits
+    private static final int  SQMASK     = 0x007e;  // max 64 (even) slots
+    private static final int  SHORT_SIGN = 1 << 15;
+    private static final int  INT_SIGN   = 1 << 31;
+
+    // masks
+    private static final long STOP_BIT   = 0x0001L << ST_SHIFT;
+    private static final long AC_MASK    = ((long)SMASK) << AC_SHIFT;
+    private static final long TC_MASK    = ((long)SMASK) << TC_SHIFT;
+
+    // units for incrementing and decrementing
+    private static final long TC_UNIT    = 1L << TC_SHIFT;
+    private static final long AC_UNIT    = 1L << AC_SHIFT;
+
+    // masks and units for dealing with u = (int)(ctl >>> 32)
+    private static final int  UAC_SHIFT  = AC_SHIFT - 32;
+    private static final int  UTC_SHIFT  = TC_SHIFT - 32;
+    private static final int  UAC_MASK   = SMASK << UAC_SHIFT;
+    private static final int  UTC_MASK   = SMASK << UTC_SHIFT;
+    private static final int  UAC_UNIT   = 1 << UAC_SHIFT;
+    private static final int  UTC_UNIT   = 1 << UTC_SHIFT;
+
+    // masks and units for dealing with e = (int)ctl
+    private static final int E_MASK      = 0x7fffffff; // no STOP_BIT
+    private static final int E_SEQ       = 1 << EC_SHIFT;
+
+    // plock bits
+    private static final int SHUTDOWN    = 1 << 31;
+    private static final int PL_LOCK     = 2;
+    private static final int PL_SIGNAL   = 1;
+    private static final int PL_SPINS    = 1 << 8;
+
+    // access mode for WorkQueue
+    static final int LIFO_QUEUE          =  0;
+    static final int FIFO_QUEUE          =  1;
+    static final int SHARED_QUEUE        = -1;
+
+    // Heuristic padding to ameliorate unfortunate memory placements
+    volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
 
     // Instance fields
-    volatile long ctl;                   // main pool control
-    volatile int runState;
-    final int config;                    // parallelism, mode
-    AuxState auxState;                   // lock, steal counts
-    volatile WorkQueue[] workQueues;     // main registry
-    final String workerNamePrefix;       // to create worker name string
+    volatile long stealCount;                  // collects worker counts
+    volatile long ctl;                         // main pool control
+    volatile int plock;                        // shutdown status and seqLock
+    volatile int indexSeed;                    // worker/submitter index seed
+    final short parallelism;                   // parallelism level
+    final short mode;                          // LIFO/FIFO
+    WorkQueue[] workQueues;                    // main registry
     final ForkJoinWorkerThreadFactory factory;
-    final UncaughtExceptionHandler ueh;  // per-worker UEH
+    final UncaughtExceptionHandler ueh;        // per-worker UEH
+    final String workerNamePrefix;             // to create worker name string
+
+    volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+    volatile Object pad18, pad19, pad1a, pad1b;
 
     /**
-     * Instantiates fields upon first submission, or upon shutdown if
-     * no submissions. If checkTermination true, also responds to
-     * termination by external calls submitting tasks.
+     * Acquires the plock lock to protect worker array and related
+     * updates. This method is called only if an initial CAS on plock
+     * fails. This acts as a spinlock for normal cases, but falls back
+     * to builtin monitor to block when (rarely) needed. This would be
+     * a terrible idea for a highly contended lock, but works fine as
+     * a more conservative alternative to a pure spinlock.
      */
-    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;
+    private int acquirePlock() {
+        int spins = PL_SPINS, ps, nps;
+        for (;;) {
+            if (((ps = plock) & PL_LOCK) == 0 &&
+                U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK))
+                return nps;
+            else if (spins >= 0) {
+                if (ThreadLocalRandom.current().nextInt() >= 0)
+                    --spins;
+            }
+            else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) {
+                synchronized (this) {
+                    if ((plock & PL_SIGNAL) != 0) {
+                        try {
+                            wait();
+                        } catch (InterruptedException ie) {
+                            try {
+                                Thread.currentThread().interrupt();
+                            } catch (SecurityException ignore) {
+                            }
+                        }
+                    }
+                    else
+                        notifyAll();
                 }
             }
         }
-        if (checkTermination && runState < 0) {
-            tryTerminate(false, false); // help terminate
-            throw new RejectedExecutionException();
-        }
-    }
-
-    // Creating, registering and deregistering workers
-
-    /**
-     * Tries to construct and start one worker. Assumes that total
-     * 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(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;
-            }
-        } catch (Throwable rex) {
-            ex = rex;
-        }
-        deregisterWorker(wt, ex);
-        return false;
     }
 
     /**
-     * Tries to add one worker, incrementing ctl counts before doing
-     * so, relying on createWorker to back out on failure.
-     *
-     * @param c incoming ctl value, with total count negative and no
-     * idle workers.  On CAS failure, c is refreshed and retried if
-     * this holds (otherwise, a new worker is not needed).
+     * Unlocks and signals any thread waiting for plock. Called only
+     * when CAS of seq value for unlock fails.
      */
-    private void tryAddWorker(long c) {
-        do {
-            long nc = ((AC_MASK & (c + AC_UNIT)) |
-                       (TC_MASK & (c + TC_UNIT)));
-            if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) {
-                createWorker(false);
+    private void releasePlock(int ps) {
+        plock = ps;
+        synchronized (this) { notifyAll(); }
+    }
+
+    /**
+     * Tries to create and start one worker if fewer than target
+     * parallelism level exist. Adjusts counts etc on failure.
+     */
+    private void tryAddWorker() {
+        long c; int u, e;
+        while ((u = (int)((c = ctl) >>> 32)) < 0 &&
+               (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) {
+            long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) |
+                              ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e;
+            if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                ForkJoinWorkerThreadFactory fac;
+                Throwable ex = null;
+                ForkJoinWorkerThread wt = null;
+                try {
+                    if ((fac = factory) != null &&
+                        (wt = fac.newThread(this)) != null) {
+                        wt.start();
+                        break;
+                    }
+                } catch (Throwable rex) {
+                    ex = rex;
+                }
+                deregisterWorker(wt, ex);
                 break;
             }
-        } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
+        }
     }
 
+    //  Registering and deregistering workers
+
     /**
-     * Callback from ForkJoinWorkerThread constructor to establish and
-     * record its WorkQueue.
+     * Callback from ForkJoinWorkerThread to establish and record its
+     * WorkQueue. To avoid scanning bias due to packing entries in
+     * front of the workQueues array, we treat the array as a simple
+     * power-of-two hash table using per-thread seed as hash,
+     * expanding as needed.
      *
      * @param wt the worker thread
      * @return the worker's queue
      */
     final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
-        UncaughtExceptionHandler handler;
-        AuxState aux;
-        wt.setDaemon(true);                           // configure thread
+        UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps;
+        wt.setDaemon(true);
         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;
-        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;
-                            }
+        do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed,
+                                          s += SEED_INCREMENT) ||
+                     s == 0); // skip 0
+        WorkQueue w = new WorkQueue(this, wt, mode, s);
+        if (((ps = plock) & PL_LOCK) != 0 ||
+            !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+            ps = acquirePlock();
+        int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+        try {
+            if ((ws = workQueues) != null) {    // skip if shutting down
+                int n = ws.length, m = n - 1;
+                int r = (s << 1) | 1;           // use odd-numbered indices
+                if (ws[r &= m] != null) {       // collision
+                    int probes = 0;             // step by approx half size
+                    int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
+                    while (ws[r = (r + 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;
                 }
-            } finally {
-                aux.unlock();
+                w.poolIndex = (short)r;
+                w.eventCount = r; // volatile write orders
+                ws[r] = w;
             }
+        } finally {
+            if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                releasePlock(nps);
         }
-        wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
+        wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1)));
         return w;
     }
 
@@ -1605,628 +1370,672 @@
     final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
         WorkQueue w = null;
         if (wt != null && (w = wt.workQueue) != null) {
-            AuxState aux; WorkQueue[] ws;          // remove index from array
-            int idx = w.config & SMASK;
-            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();
+            int ps; long sc;
+            w.qlock = -1;                // ensure set
+            do {} while (!U.compareAndSwapLong(this, STEALCOUNT,
+                                               sc = stealCount,
+                                               sc + w.nsteals));
+            if (((ps = plock) & PL_LOCK) != 0 ||
+                !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                ps = acquirePlock();
+            int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+            try {
+                int idx = w.poolIndex;
+                WorkQueue[] ws = workQueues;
+                if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w)
+                    ws[idx] = null;
+            } finally {
+                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                    releasePlock(nps);
+            }
+        }
+
+        long c;                          // adjust ctl counts
+        do {} while (!U.compareAndSwapLong
+                     (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) |
+                                           ((c - TC_UNIT) & TC_MASK) |
+                                           (c & ~(AC_MASK|TC_MASK)))));
+
+        if (!tryTerminate(false, false) && w != null && w.array != null) {
+            w.cancelAll();               // cancel remaining tasks
+            WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e;
+            while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) {
+                if (e > 0) {             // activate or create replacement
+                    if ((ws = workQueues) == null ||
+                        (i = e & SMASK) >= ws.length ||
+                        (v = ws[i]) == null)
+                        break;
+                    long nc = (((long)(v.nextWait & E_MASK)) |
+                               ((long)(u + UAC_UNIT) << 32));
+                    if (v.eventCount != (e | INT_SIGN))
+                        break;
+                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                        v.eventCount = (e + E_SEQ) & E_MASK;
+                        if ((p = v.parker) != null)
+                            U.unpark(p);
+                        break;
+                    }
+                }
+                else {
+                    if ((short)u < 0)
+                        tryAddWorker();
+                    break;
                 }
             }
         }
-        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.cancelAll();                            // cancel remaining tasks
-        }
-        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;
-            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) {
-                tryAddWorker(c);                      // create replacement
-                break;
-            }
-            else                                      // don't need replacement
-                break;
-        }
-        if (ex == null)                               // help clean on way out
+        if (ex == null)                     // help clean refs on way out
             ForkJoinTask.helpExpungeStaleExceptions();
-        else                                          // rethrow
+        else                                // rethrow
             ForkJoinTask.rethrow(ex);
     }
 
-    // Signalling
+    // Submissions
+
+    /**
+     * Per-thread records for threads that submit to pools. Currently
+     * holds only pseudo-random seed / index that is used to choose
+     * submission queues in method externalPush. In the future, this may
+     * also incorporate a means to implement different task rejection
+     * and resubmission policies.
+     *
+     * Seeds for submitters and workers/workQueues work in basically
+     * the same way but are initialized and updated using slightly
+     * different mechanics. Both are initialized using the same
+     * approach as in class ThreadLocal, where successive values are
+     * unlikely to collide with previous values. Seeds are then
+     * randomly modified upon collisions using xorshifts, which
+     * requires a non-zero seed.
+     */
+    static final class Submitter {
+        int seed;
+        Submitter(int s) { seed = s; }
+    }
+
+    /**
+     * Unless shutting down, adds the given task to a submission queue
+     * at submitter's current queue index (modulo submission
+     * range). Only the most common path is directly handled in this
+     * method. All others are relayed to fullExternalPush.
+     *
+     * @param task the task. Caller must ensure non-null.
+     */
+    final void externalPush(ForkJoinTask<?> task) {
+        Submitter z = submitters.get();
+        WorkQueue q; int r, m, s, n, am; ForkJoinTask<?>[] a;
+        int ps = plock;
+        WorkQueue[] ws = workQueues;
+        if (z != null && ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 &&
+            (q = ws[m & (r = z.seed) & SQMASK]) != null && r != 0 &&
+            U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
+            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);
+                q.top = s + 1;                     // push on to deque
+                q.qlock = 0;
+                if (n <= 1)
+                    signalWork(ws, q);
+                return;
+            }
+            q.qlock = 0;
+        }
+        fullExternalPush(task);
+    }
+
+    /**
+     * Full version of externalPush. This method is called, among
+     * other times, upon the first submission of the first task to the
+     * pool, so must perform secondary initialization.  It also
+     * detects first submission by an external thread by looking up
+     * its ThreadLocal, and creates a new shared queue if the one at
+     * index if empty or contended. The plock lock body must be
+     * exception-free (so no try/finally) so we optimistically
+     * allocate new queues outside the lock and throw them away if
+     * (very rarely) not needed.
+     *
+     * Secondary initialization occurs when plock is zero, to create
+     * workQueue array and set plock to a valid value.  This lock body
+     * must also be exception-free. Because the plock seq value can
+     * eventually wrap around zero, this method harmlessly fails to
+     * reinitialize if workQueues exists, while still advancing plock.
+     */
+    private void fullExternalPush(ForkJoinTask<?> task) {
+        int r = 0; // random index seed
+        for (Submitter z = submitters.get();;) {
+            WorkQueue[] ws; WorkQueue q; int ps, m, k;
+            if (z == null) {
+                if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed,
+                                        r += SEED_INCREMENT) && r != 0)
+                    submitters.set(z = new Submitter(r));
+            }
+            else if (r == 0) {                  // move to a different index
+                r = z.seed;
+                r ^= r << 13;                   // same xorshift as WorkQueues
+                r ^= r >>> 17;
+                z.seed = r ^= (r << 5);
+            }
+            if ((ps = plock) < 0)
+                throw new RejectedExecutionException();
+            else if (ps == 0 || (ws = workQueues) == null ||
+                     (m = ws.length - 1) < 0) { // initialize workQueues
+                int p = parallelism;            // find power of two table size
+                int n = (p > 1) ? p - 1 : 1;    // ensure at least 2 slots
+                n |= n >>> 1; n |= n >>> 2;  n |= n >>> 4;
+                n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
+                WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ?
+                                   new WorkQueue[n] : null);
+                if (((ps = plock) & PL_LOCK) != 0 ||
+                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                    ps = acquirePlock();
+                if (((ws = workQueues) == null || ws.length == 0) && nws != null)
+                    workQueues = nws;
+                int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                    releasePlock(nps);
+            }
+            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;
+                    try {                      // locked version of push
+                        if ((a != null && a.length > s + 1 - q.base) ||
+                            (a = q.growArray()) != null) {   // must presize
+                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
+                            U.putOrderedObject(a, j, task);
+                            q.top = s + 1;
+                            submitted = true;
+                        }
+                    } finally {
+                        q.qlock = 0;  // unlock
+                    }
+                    if (submitted) {
+                        signalWork(ws, q);
+                        return;
+                    }
+                }
+                r = 0; // move on failure
+            }
+            else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
+                q = new WorkQueue(this, null, SHARED_QUEUE, r);
+                q.poolIndex = (short)k;
+                if (((ps = plock) & PL_LOCK) != 0 ||
+                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                    ps = acquirePlock();
+                if ((ws = workQueues) != null && k < ws.length && ws[k] == null)
+                    ws[k] = q;
+                int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                    releasePlock(nps);
+            }
+            else
+                r = 0;
+        }
+    }
+
+    // Maintaining ctl counts
+
+    /**
+     * Increments active count; mainly called upon return from blocking.
+     */
+    final void incrementActiveCount() {
+        long c;
+        do {} while (!U.compareAndSwapLong
+                     (this, CTL, c = ctl, ((c & ~AC_MASK) |
+                                           ((c & AC_MASK) + AC_UNIT))));
+    }
 
     /**
      * Tries to create or activate a worker if too few are active.
+     *
+     * @param ws the worker array to use to find signallees
+     * @param q if non-null, the queue holding tasks to be processed
      */
-    final void signalWork() {
+    final void signalWork(WorkQueue[] ws, WorkQueue q) {
         for (;;) {
-            long c; int sp, i; WorkQueue v; WorkQueue[] ws;
-            if ((c = ctl) >= 0L)                      // enough workers
+            long c; int e, u, i; WorkQueue w; Thread p;
+            if ((u = (int)((c = ctl) >>> 32)) >= 0)
                 break;
-            else if ((sp = (int)c) == 0) {            // no idle workers
-                if ((c & ADD_WORKER) != 0L)           // too few workers
-                    tryAddWorker(c);
+            if ((e = (int)c) <= 0) {
+                if ((short)u < 0)
+                    tryAddWorker();
                 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;
-                }
-            }
-        }
-    }
-
-    /**
-     * Signals and releases worker v if it is top of idle worker
-     * stack.  This performs a one-shot version of signalWork only if
-     * there is (apparently) at least one idle worker.
-     *
-     * @param c incoming ctl value
-     * @param v if non-null, a worker
-     * @param inc the increment to active count (zero when compensating)
-     * @return true if successful
-     */
-    private boolean tryRelease(long c, WorkQueue v, long inc) {
-        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;
-    }
-
-    /**
-     * 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 &&
+            if (ws == null || ws.length <= (i = e & SMASK) ||
+                (w = ws[i]) == null)
+                break;
+            long nc = (((long)(w.nextWait & E_MASK)) |
+                       ((long)(u + UAC_UNIT)) << 32);
+            int ne = (e + E_SEQ) & E_MASK;
+            if (w.eventCount == (e | INT_SIGN) &&
                 U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = ns;
-                LockSupport.unpark(v.parker);
+                w.eventCount = ne;
+                if ((p = w.parker) != null)
+                    U.unpark(p);
+                break;
             }
-        }
-    }
-
-    /**
-     * 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 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;
-            }
+            if (q != null && q.base >= q.top)
+                break;
         }
     }
 
     // Scanning for tasks
 
     /**
-     * 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.
+     * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
+     */
+    final void runWorker(WorkQueue w) {
+        w.growArray(); // allocate queue
+        for (int r = w.hint; scan(w, r) == 0; ) {
+            r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
+        }
+    }
+
+    /**
+     * Scans for and, if found, runs one task, else possibly
+     * inactivates the worker. This method operates on single reads of
+     * volatile state and is designed to be re-invoked continuously,
+     * in part because it returns upon detecting inconsistencies,
+     * contention, or state changes that indicate possible success on
+     * re-invocation.
+     *
+     * The scan searches for tasks across queues starting at a random
+     * index, checking each at least twice.  The scan terminates upon
+     * either finding a non-empty queue, or completing the sweep. If
+     * the worker is not inactivated, it takes and runs a task from
+     * this queue. Otherwise, if not activated, it tries to activate
+     * itself or some other worker by signalling. On failure to find a
+     * task, returns (for retry) if pool state may have changed during
+     * an empty scan, or tries to inactivate if active, else possibly
+     * blocks or terminates via method awaitWork.
      *
      * @param w the worker (via its WorkQueue)
-     * @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
+     * @param r a random seed
+     * @return worker qlock status if would have waited, else 0
      */
-    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
+    private final int scan(WorkQueue w, int r) {
+        WorkQueue[] ws; int m;
+        long c = ctl;                            // for consistency check
+        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) {
+            for (int j = m + m + 1, ec = w.eventCount;;) {
+                WorkQueue q; int b, e; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
+                if ((q = ws[(r - j) & m]) != null &&
+                    (b = q.base) - q.top < 0 && (a = q.array) != null) {
+                    long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                    if ((t = ((ForkJoinTask<?>)
+                              U.getObjectVolatile(a, i))) != null) {
+                        if (ec < 0)
+                            helpRelease(c, ws, w, q, b);
+                        else if (q.base == b &&
+                                 U.compareAndSwapObject(a, i, t, null)) {
+                            U.putOrderedInt(q, QBASE, b + 1);
+                            if ((b + 1) - q.top < 0)
+                                signalWork(ws, q);
+                            w.runTask(t);
+                        }
                     }
-                    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;
-                    }
-                }
-                else if (npolls != 0)              // rescan
                     break;
-                else if ((idx = (idx + step) & m) == origin) {
-                    if (ss < 0) {                  // await signal
-                        stat = ss;
-                        break;
+                }
+                else if (--j < 0) {
+                    if ((ec | (e = (int)c)) < 0) // inactive or terminating
+                        return awaitWork(w, c, ec);
+                    else if (ctl == c) {         // try to inactivate and enqueue
+                        long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
+                        w.nextWait = e;
+                        w.eventCount = ec | INT_SIGN;
+                        if (!U.compareAndSwapLong(this, CTL, c, nc))
+                            w.eventCount = ec;   // back out
                     }
-                    else if (r >= 0) {
-                        inactivate(w, ss);
-                        break;
-                    }
-                    else
-                        r <<= 1;                   // at most 31 rescans
+                    break;
+                }
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * A continuation of scan(), possibly blocking or terminating
+     * worker w. Returns without blocking if pool state has apparently
+     * changed since last invocation.  Also, 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 event 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 c the ctl value on entry to scan
+     * @param ec the worker's eventCount on entry to scan
+     */
+    private final int awaitWork(WorkQueue w, long c, int ec) {
+        int stat, ns; long parkTime, deadline;
+        if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c &&
+            !Thread.interrupted()) {
+            int e = (int)c;
+            int u = (int)(c >>> 32);
+            int d = (u >> UAC_SHIFT) + parallelism; // active count
+
+            if (e < 0 || (d <= 0 && tryTerminate(false, false)))
+                stat = w.qlock = -1;          // pool is terminating
+            else if ((ns = w.nsteals) != 0) { // collect steals and retry
+                long sc;
+                w.nsteals = 0;
+                do {} while (!U.compareAndSwapLong(this, STEALCOUNT,
+                                                   sc = stealCount, sc + ns));
+            }
+            else {
+                long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L :
+                           ((long)(w.nextWait & E_MASK)) | // ctl to restore
+                           ((long)(u + UAC_UNIT)) << 32);
+                if (pc != 0L) {               // timed wait if last waiter
+                    int dc = -(short)(c >>> TC_SHIFT);
+                    parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT:
+                                (dc + 1) * IDLE_TIMEOUT);
+                    deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
+                }
+                else
+                    parkTime = deadline = 0L;
+                if (w.eventCount == ec && ctl == c) {
+                    Thread wt = Thread.currentThread();
+                    U.putObject(wt, PARKBLOCKER, this);
+                    w.parker = wt;            // emulate LockSupport.park
+                    if (w.eventCount == ec && ctl == c)
+                        U.park(false, parkTime);  // must recheck before park
+                    w.parker = null;
+                    U.putObject(wt, PARKBLOCKER, null);
+                    if (parkTime != 0L && ctl == c &&
+                        deadline - System.nanoTime() <= 0L &&
+                        U.compareAndSwapLong(this, CTL, c, pc))
+                        stat = w.qlock = -1;  // shrink pool
                 }
             }
         }
         return stat;
     }
 
-    // Joining tasks
-
     /**
-     * Tries to steal and run tasks within the target's computation.
-     * Uses a variant of the top-level algorithm, restricted to tasks
-     * with the given task as ancestor: It prefers taking and running
-     * 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 from pollAndExecCC). The maxTasks
-     * argument supports external usages; internal calls use zero,
-     * allowing unbounded steps (external calls trap non-positive
-     * values).
-     *
-     * @param w caller
-     * @param maxTasks if non-zero, the maximum number of other tasks to run
-     * @return task status on exit
+     * Possibly releases (signals) a worker. Called only from scan()
+     * when a worker with apparently inactive status finds a non-empty
+     * queue. This requires revalidating all of the associated state
+     * from caller.
      */
-    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
-                           int maxTasks) {
-        WorkQueue[] ws; int s = 0, wl;
-        if ((ws = workQueues) != null && (wl = ws.length) > 1 &&
-            task != null && w != null) {
-            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) {
-                    p.doExec();                  // run local task
-                    if (maxTasks != 0 && --maxTasks == 0)
-                        break;
-                    origin = k;                  // reset
-                    oldSum = checkSum = 0;
-                }
-                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
-                        k = origin = r & m;      // move and restart
-                        oldSum = checkSum = 0;
-                    }
-                    else if ((k = (k + step) & m) == origin) {
-                        if (oldSum == (oldSum = checkSum))
-                            break;
-                        checkSum = 0;
-                    }
-                }
+    private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w,
+                                   WorkQueue q, int b) {
+        WorkQueue v; int e, i; Thread p;
+        if (w != null && w.eventCount < 0 && (e = (int)c) > 0 &&
+            ws != null && ws.length > (i = e & SMASK) &&
+            (v = ws[i]) != null && ctl == c) {
+            long nc = (((long)(v.nextWait & E_MASK)) |
+                       ((long)((int)(c >>> 32) + UAC_UNIT)) << 32);
+            int ne = (e + E_SEQ) & E_MASK;
+            if (q != null && q.base == b && w.eventCount < 0 &&
+                v.eventCount == (e | INT_SIGN) &&
+                U.compareAndSwapLong(this, CTL, c, nc)) {
+                v.eventCount = ne;
+                if ((p = v.parker) != null)
+                    U.unpark(p);
             }
         }
-        return s;
     }
 
     /**
      * 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
      * waiting join will often entail scanning/search, (which is OK
      * because the joiner has nothing better to do), but this method
-     * leaves hints in workers to speed up subsequent calls.
+     * leaves hints in workers to speed up subsequent calls. The
+     * implementation is very branchy to cope with potential
+     * inconsistencies or loops encountering chains that are stale,
+     * unknown, or so long that they are likely cyclic.
      *
-     * @param w caller
+     * @param joiner the joining worker
      * @param task the task to join
+     * @return 0 if no progress can be made, negative if task
+     * known complete, else positive
      */
-    private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
-        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;;) {
-                        if ((v = ws[i = (h + (k << 1)) & m]) != null) {
-                            if (v.currentSteal == subtask) {
-                                j.hint = i;
+    private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
+        int stat = 0, steps = 0;                    // bound to avoid cycles
+        if (task != null && joiner != null &&
+            joiner.base - joiner.top >= 0) {        // hoist checks
+            restart: for (;;) {
+                ForkJoinTask<?> subtask = task;     // current target
+                for (WorkQueue j = joiner, v;;) {   // v is stealer of subtask
+                    WorkQueue[] ws; int m, s, h;
+                    if ((s = task.status) < 0) {
+                        stat = s;
+                        break restart;
+                    }
+                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
+                        break restart;              // shutting down
+                    if ((v = ws[h = (j.hint | 1) & m]) == null ||
+                        v.currentSteal != subtask) {
+                        for (int origin = h;;) {    // find stealer
+                            if (((h = (h + 2) & m) & 15) == 1 &&
+                                (subtask.status < 0 || j.currentJoin != subtask))
+                                continue restart;   // occasional staleness check
+                            if ((v = ws[h]) != null &&
+                                v.currentSteal == subtask) {
+                                j.hint = h;        // save hint
                                 break;
                             }
-                            checkSum += v.base;
+                            if (h == origin)
+                                break restart;      // cannot find stealer
                         }
-                        if (++k > m)                   // can't find stealer
-                            break outer;
                     }
-
-                    for (;;) {                         // help v or descend
-                        ForkJoinTask<?>[] a; int b, al;
-                        if (subtask.status < 0)        // too late to help
-                            break descent;
-                        checkSum += (b = v.base);
-                        ForkJoinTask<?> next = v.currentJoin;
-                        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;
-                                    }
+                    for (;;) { // help stealer or descend to its stealer
+                        ForkJoinTask[] a; int b;
+                        if (subtask.status < 0)     // surround probes with
+                            continue restart;       //   consistency checks
+                        if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
+                            int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                            ForkJoinTask<?> t =
+                                (ForkJoinTask<?>)U.getObjectVolatile(a, i);
+                            if (subtask.status < 0 || j.currentJoin != subtask ||
+                                v.currentSteal != subtask)
+                                continue restart;   // stale
+                            stat = 1;               // apparent progress
+                            if (v.base == b) {
+                                if (t == null)
+                                    break restart;
+                                if (U.compareAndSwapObject(a, i, t, null)) {
+                                    U.putOrderedInt(v, QBASE, b + 1);
+                                    ForkJoinTask<?> ps = joiner.currentSteal;
+                                    int jt = joiner.top;
+                                    do {
+                                        joiner.currentSteal = t;
+                                        t.doExec(); // clear local tasks too
+                                    } while (task.status >= 0 &&
+                                             joiner.top != jt &&
+                                             (t = joiner.pop()) != null);
+                                    joiner.currentSteal = ps;
+                                    break restart;
                                 }
                             }
                         }
-                        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;
+                        else {                      // empty -- try to descend
+                            ForkJoinTask<?> next = v.currentJoin;
+                            if (subtask.status < 0 || j.currentJoin != subtask ||
+                                v.currentSteal != subtask)
+                                continue restart;   // stale
+                            else if (next == null || ++steps == MAX_HELP)
+                                break restart;      // dead-end or maybe cyclic
+                            else {
+                                subtask = next;
+                                j = v;
+                                break;
                             }
-                            j = v;
-                            break;
                         }
                     }
                 }
             }
         }
+        return stat;
     }
 
     /**
-     * Tries to decrement active count (sometimes implicitly) and
-     * possibly release or create a compensating worker in preparation
-     * for blocking. Returns false (retryable by caller), on
-     * contention, detected staleness, instability, or termination.
+     * Analog of tryHelpStealer for CountedCompleters. Tries to steal
+     * and run tasks within the target's computation.
      *
-     * @param w caller
+     * @param task the task to join
      */
-    private boolean tryCompensate(WorkQueue w) {
-        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 {
-            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 (!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
-                canBlock = U.compareAndSwapLong(this, CTL, c, nc);
-            }
-            else if (tc >= MAX_CAP ||
-                     (this == common && tc >= pc + COMMON_MAX_SPARES))
-                throw new RejectedExecutionException(
-                    "Thread limit exceeded replacing blocked worker");
-            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;
-    }
-
-    /**
-     * Helps and/or blocks until the given task is done or timeout.
-     *
-     * @param w caller
-     * @param task the task
-     * @param deadline for timed waits, if nonzero
-     * @return task status on exit
-     */
-    final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
+    private int helpComplete(WorkQueue joiner, CountedCompleter<?> task) {
+        WorkQueue[] ws; int m;
         int s = 0;
-        if (w != null) {
-            ForkJoinTask<?> prevJoin = w.currentJoin;
-            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)
+        if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+            joiner != null && task != null) {
+            int j = joiner.poolIndex;
+            int scans = m + m + 1;
+            long c = 0L;              // for stability check
+            for (int k = scans; ; j += 2) {
+                WorkQueue q;
+                if ((s = task.status) < 0)
+                    break;
+                else if (joiner.internalPopAndExecCC(task))
+                    k = scans;
+                else if ((s = task.status) < 0)
+                    break;
+                else if ((q = ws[j & m]) != null && q.pollAndExecCC(task))
+                    k = scans;
+                else if (--k < 0) {
+                    if (c == (c = ctl))
                         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;
+                    k = scans;
                 }
-                w.currentJoin = prevJoin;
             }
         }
         return s;
     }
 
-    // Specialized scanning
+    /**
+     * Tries to decrement active count (sometimes implicitly) and
+     * possibly release or create a compensating worker in preparation
+     * for blocking. Fails on contention or termination. Otherwise,
+     * adds a new thread if no idle workers are available and pool
+     * may become starved.
+     *
+     * @param c the assumed ctl value
+     */
+    final boolean tryCompensate(long c) {
+        WorkQueue[] ws = workQueues;
+        int pc = parallelism, e = (int)c, m, tc;
+        if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) {
+            WorkQueue w = ws[e & m];
+            if (e != 0 && w != null) {
+                Thread p;
+                long nc = ((long)(w.nextWait & E_MASK) |
+                           (c & (AC_MASK|TC_MASK)));
+                int ne = (e + E_SEQ) & E_MASK;
+                if (w.eventCount == (e | INT_SIGN) &&
+                    U.compareAndSwapLong(this, CTL, c, nc)) {
+                    w.eventCount = ne;
+                    if ((p = w.parker) != null)
+                        U.unpark(p);
+                    return true;   // replace with idle worker
+                }
+            }
+            else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 &&
+                     (int)(c >> AC_SHIFT) + pc > 1) {
+                long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
+                if (U.compareAndSwapLong(this, CTL, c, nc))
+                    return true;   // no compensation
+            }
+            else if (tc + pc < MAX_CAP) {
+                long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
+                if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                    ForkJoinWorkerThreadFactory fac;
+                    Throwable ex = null;
+                    ForkJoinWorkerThread wt = null;
+                    try {
+                        if ((fac = factory) != null &&
+                            (wt = fac.newThread(this)) != null) {
+                            wt.start();
+                            return true;
+                        }
+                    } catch (Throwable rex) {
+                        ex = rex;
+                    }
+                    deregisterWorker(wt, ex); // clean up and return false
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Helps and/or blocks until the given task is done.
+     *
+     * @param joiner the joining worker
+     * @param task the task
+     * @return task status on exit
+     */
+    final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
+        int s = 0;
+        if (task != null && (s = task.status) >= 0 && joiner != null) {
+            ForkJoinTask<?> prevJoin = joiner.currentJoin;
+            joiner.currentJoin = task;
+            do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
+                         (s = task.status) >= 0);
+            if (s >= 0 && (task instanceof CountedCompleter))
+                s = helpComplete(joiner, (CountedCompleter<?>)task);
+            long cc = 0;        // for stability checks
+            while (s >= 0 && (s = task.status) >= 0) {
+                if ((s = tryHelpStealer(joiner, task)) == 0 &&
+                    (s = task.status) >= 0) {
+                    if (!tryCompensate(cc))
+                        cc = ctl;
+                    else {
+                        if (task.trySetSignal() && (s = task.status) >= 0) {
+                            synchronized (task) {
+                                if (task.status >= 0) {
+                                    try {                // see ForkJoinTask
+                                        task.wait();     //  for explanation
+                                    } catch (InterruptedException ie) {
+                                    }
+                                }
+                                else
+                                    task.notifyAll();
+                            }
+                        }
+                        long c; // reactivate
+                        do {} while (!U.compareAndSwapLong
+                                     (this, CTL, c = ctl,
+                                      ((c & ~AC_MASK) |
+                                       ((c & AC_MASK) + AC_UNIT))));
+                    }
+                }
+            }
+            joiner.currentJoin = prevJoin;
+        }
+        return s;
+    }
+
+    /**
+     * Stripped-down variant of awaitJoin used by timed joins. Tries
+     * to help join only while there is continuous progress. (Caller
+     * will then enter a timed wait.)
+     *
+     * @param joiner the joining worker
+     * @param task the task
+     */
+    final void helpJoinOnce(WorkQueue joiner, ForkJoinTask<?> task) {
+        int s;
+        if (joiner != null && task != null && (s = task.status) >= 0) {
+            ForkJoinTask<?> prevJoin = joiner.currentJoin;
+            joiner.currentJoin = task;
+            do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
+                         (s = task.status) >= 0);
+            if (s >= 0) {
+                if (task instanceof CountedCompleter)
+                    helpComplete(joiner, (CountedCompleter<?>)task);
+                do {} while (task.status >= 0 &&
+                             tryHelpStealer(joiner, task) > 0);
+            }
+            joiner.currentJoin = prevJoin;
+        }
+    }
 
     /**
      * Returns a (probably) non-empty steal queue, if one is found
@@ -2234,25 +2043,19 @@
      * caller if, by the time it tries to use the queue, it is empty.
      */
     private WorkQueue findNonEmptyStealQueue() {
-        WorkQueue[] ws; int wl;  // one-shot version of scan loop
-        int r = ThreadLocalRandom.nextSecondarySeed();
-        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)
+        int r = ThreadLocalRandom.current().nextInt();
+        for (;;) {
+            int ps = plock, m; WorkQueue[] ws; WorkQueue q;
+            if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+                for (int j = (m + 1) << 2; j >= 0; --j) {
+                    if ((q = ws[(((r - j) << 1) | 1) & m]) != null &&
+                        q.base - q.top < 0)
                         return q;
-                    checkSum += b;
-                }
-                if ((k = (k + 1) & m) == origin) {
-                    if (oldSum == (oldSum = checkSum))
-                        break;
-                    checkSum = 0;
                 }
             }
+            if (plock == ps)
+                return null;
         }
-        return null;
     }
 
     /**
@@ -2262,33 +2065,35 @@
      * find tasks either.
      */
     final void helpQuiescePool(WorkQueue w) {
-        ForkJoinTask<?> ps = w.currentSteal; // save context
-        int wc = w.config;
+        ForkJoinTask<?> ps = w.currentSteal;
         for (boolean active = true;;) {
-            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) {
+            long c; WorkQueue q; ForkJoinTask<?> t; int b;
+            while ((t = w.nextLocalTask()) != null)
+                t.doExec();
+            if ((q = findNonEmptyStealQueue()) != null) {
                 if (!active) {      // re-establish active count
                     active = true;
-                    U.getAndAddLong(this, CTL, AC_UNIT);
+                    do {} while (!U.compareAndSwapLong
+                                 (this, CTL, c = ctl,
+                                  ((c & ~AC_MASK) |
+                                   ((c & AC_MASK) + AC_UNIT))));
                 }
-                if ((t = q.pollAt(q.base)) != null) {
+                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != 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);
+                long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT);
+                if ((int)(nc >> AC_SHIFT) + parallelism == 0)
+                    break;          // bypass decrement-then-increment
                 if (U.compareAndSwapLong(this, CTL, c, nc))
                     active = false;
             }
-            else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) <= 0 &&
-                     U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
+            else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 &&
+                     U.compareAndSwapLong
+                     (this, CTL, c, ((c & ~AC_MASK) |
+                                     ((c & AC_MASK) + AC_UNIT))))
                 break;
         }
     }
@@ -2300,12 +2105,12 @@
      */
     final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
         for (ForkJoinTask<?> t;;) {
-            WorkQueue q;
+            WorkQueue q; int b;
             if ((t = w.nextLocalTask()) != null)
                 return t;
             if ((q = findNonEmptyStealQueue()) == null)
                 return null;
-            if ((t = q.pollAt(q.base)) != null)
+            if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
                 return t;
         }
     }
@@ -2313,7 +2118,7 @@
     /**
      * Returns a cheap heuristic guide for task partitioning when
      * programmers, frameworks, tools, or languages have little or no
-     * idea about task granularity.  In essence, by offering this
+     * idea about task granularity.  In essence by offering this
      * method, we ask users only about tradeoffs in overhead vs
      * expected throughput and its variance, rather than how finely to
      * partition tasks.
@@ -2351,11 +2156,15 @@
      * many of these by further considering the number of "idle"
      * threads, that are known to have zero queued tasks, so
      * compensate by a factor of (#idle/#active) threads.
+     *
+     * Note: The approximation of #busy workers as #active workers is
+     * not very good under current signalling scheme, and should be
+     * improved.
      */
     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).parallelism;
             int n = (q = wt.workQueue).top - q.base;
             int a = (int)(pool.ctl >> AC_SHIFT) + p;
             return n - (a > (p >>>= 1) ? 0 :
@@ -2370,203 +2179,170 @@
     //  Termination
 
     /**
-     * Possibly initiates and/or completes termination.
+     * Possibly initiates and/or completes termination.  The caller
+     * triggering termination runs three passes through workQueues:
+     * (0) Setting termination status, followed by wakeups of queued
+     * workers; (1) cancelling all tasks; (2) interrupting lagging
+     * threads (likely in external tasks, but possibly also blocked in
+     * joins).  Each pass repeats previous steps because of potential
+     * lagging thread creation.
      *
      * @param now if true, unconditionally terminate, else only
      * if no work and no active workers
-     * @param enable if true, terminate when next possible
-     * @return -1: terminating/terminated, 0: retry if internal caller, else 1
+     * @param enable if true, enable shutdown when next possible
+     * @return true if now terminating or terminated
      */
-    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);
+    private boolean tryTerminate(boolean now, boolean enable) {
+        int ps;
+        if (this == common)                        // cannot shut down
+            return false;
+        if ((ps = plock) >= 0) {                   // enable by setting plock
+            if (!enable)
+                return false;
+            if ((ps & PL_LOCK) != 0 ||
+                !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                ps = acquirePlock();
+            int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN;
+            if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                releasePlock(nps);
         }
-
-        if ((rs & STOP) == 0) {                   // try to initiate termination
-            if (!now) {                           // check quiescence
-                for (long oldSum = 0L;;) {        // repeat until stable
-                    WorkQueue[] ws; WorkQueue w; int b;
-                    long checkSum = ctl;
-                    if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
-                        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
-                            }
+        for (long c;;) {
+            if (((c = ctl) & STOP_BIT) != 0) {     // already terminating
+                if ((short)(c >>> TC_SHIFT) + parallelism <= 0) {
+                    synchronized (this) {
+                        notifyAll();               // signal when 0 workers
+                    }
+                }
+                return true;
+            }
+            if (!now) {                            // check if idle & no tasks
+                WorkQueue[] ws; WorkQueue w;
+                if ((int)(c >> AC_SHIFT) + parallelism > 0)
+                    return false;
+                if ((ws = workQueues) != null) {
+                    for (int i = 0; i < ws.length; ++i) {
+                        if ((w = ws[i]) != null &&
+                            (!w.isEmpty() ||
+                             ((i & 1) != 0 && w.eventCount >= 0))) {
+                            signalWork(ws, w);
+                            return false;
                         }
                     }
-                    if (oldSum == (oldSum = checkSum))
-                        break;
                 }
             }
-            do {} while (!U.compareAndSwapInt(this, RUNSTATE,
-                                              rs = runState, rs | STOP));
-        }
-
-        for (long oldSum = 0L;;) {                // repeat until stable
-            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt;
-            long checkSum = ctl;
-            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 (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) {
+                for (int pass = 0; pass < 3; ++pass) {
+                    WorkQueue[] ws; WorkQueue w; Thread wt;
+                    if ((ws = workQueues) != null) {
+                        int n = ws.length;
+                        for (int i = 0; i < n; ++i) {
+                            if ((w = ws[i]) != null) {
+                                w.qlock = -1;
+                                if (pass > 0) {
+                                    w.cancelAll();
+                                    if (pass > 1 && (wt = w.owner) != null) {
+                                        if (!wt.isInterrupted()) {
+                                            try {
+                                                wt.interrupt();
+                                            } catch (Throwable ignore) {
+                                            }
+                                        }
+                                        U.unpark(wt);
+                                    }
                                 }
                             }
                         }
+                        // Wake up workers parked on event queue
+                        int i, e; long cc; Thread p;
+                        while ((e = (int)(cc = ctl) & E_MASK) != 0 &&
+                               (i = e & SMASK) < n && i >= 0 &&
+                               (w = ws[i]) != null) {
+                            long nc = ((long)(w.nextWait & E_MASK) |
+                                       ((cc + AC_UNIT) & AC_MASK) |
+                                       (cc & (TC_MASK|STOP_BIT)));
+                            if (w.eventCount == (e | INT_SIGN) &&
+                                U.compareAndSwapLong(this, CTL, cc, nc)) {
+                                w.eventCount = (e + E_SEQ) & E_MASK;
+                                w.qlock = -1;
+                                if ((p = w.parker) != null)
+                                    U.unpark(p);
+                            }
+                        }
                     }
                 }
             }
-            if (oldSum == (oldSum = checkSum))
-                break;
-        }
-
-        if ((short)(ctl >>> TC_SHIFT) + (config & SMASK) <= 0) {
-            runState = (STARTED | SHUTDOWN | STOP | TERMINATED); // final write
-            synchronized (this) {
-                notifyAll();                      // for awaitTermination
-            }
-        }
-
-        return -1;
-    }
-
-    // External operations
-
-    /**
-     * 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.
-     */
-    final void externalPush(ForkJoinTask<?> task) {
-        int r;                            // initialize caller's probe
-        if ((r = ThreadLocalRandom.getProbe()) == 0) {
-            ThreadLocalRandom.localInit();
-            r = ThreadLocalRandom.getProbe();
-        }
-        for (;;) {
-            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                          // move if busy
-                r = ThreadLocalRandom.advanceProbe(r);
-        }
-    }
+    // external operations on common pool
 
     /**
-     * Pushes a possibly-external submission.
-     */
-    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;
-    }
-
-    /**
-     * Returns common pool queue for an external thread.
+     * Returns common pool queue for a thread that has submitted at
+     * least one task.
      */
     static WorkQueue commonSubmitterQueue() {
-        ForkJoinPool p = common;
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; int wl;
-        return (p != null && (ws = p.workQueues) != null &&
-                (wl = ws.length) > 0) ?
-            ws[(wl - 1) & r & SQMASK] : null;
+        Submitter z; ForkJoinPool p; WorkQueue[] ws; int m, r;
+        return ((z = submitters.get()) != null &&
+                (p = common) != null &&
+                (ws = p.workQueues) != null &&
+                (m = ws.length - 1) >= 0) ?
+            ws[m & z.seed & SQMASK] : null;
     }
 
     /**
-     * Performs tryUnpush for an external submitter.
+     * Tries to pop the given task from submitter's queue in common pool.
      */
     final boolean tryExternalUnpush(ForkJoinTask<?> task) {
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; WorkQueue w; int wl;
-        return ((ws = workQueues) != null &&
-                (wl = ws.length) > 0 &&
-                (w = ws[(wl - 1) & r & SQMASK]) != null &&
-                w.trySharedUnpush(task));
+        WorkQueue joiner; ForkJoinTask<?>[] a; int m, s;
+        Submitter z = submitters.get();
+        WorkQueue[] ws = workQueues;
+        boolean popped = false;
+        if (z != null && ws != null && (m = ws.length - 1) >= 0 &&
+            (joiner = ws[z.seed & m & SQMASK]) != null &&
+            joiner.base != (s = joiner.top) &&
+            (a = joiner.array) != null) {
+            long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+            if (U.getObject(a, j) == task &&
+                U.compareAndSwapInt(joiner, QLOCK, 0, 1)) {
+                if (joiner.top == s && joiner.array == a &&
+                    U.compareAndSwapObject(a, j, task, null)) {
+                    joiner.top = s - 1;
+                    popped = true;
+                }
+                joiner.qlock = 0;
+            }
+        }
+        return popped;
     }
 
-    /**
-     * Performs helpComplete for an external submitter.
-     */
-    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
-        WorkQueue[] ws; int wl;
-        int r = ThreadLocalRandom.getProbe();
-        return ((ws = workQueues) != null && (wl = ws.length) > 0) ?
-            helpComplete(ws[(wl - 1) & r & SQMASK], task, maxTasks) : 0;
+    final int externalHelpComplete(CountedCompleter<?> task) {
+        WorkQueue joiner; int m, j;
+        Submitter z = submitters.get();
+        WorkQueue[] ws = workQueues;
+        int s = 0;
+        if (z != null && ws != null && (m = ws.length - 1) >= 0 &&
+            (joiner = ws[(j = z.seed) & m & SQMASK]) != null && task != null) {
+            int scans = m + m + 1;
+            long c = 0L;             // for stability check
+            j |= 1;                  // poll odd queues
+            for (int k = scans; ; j += 2) {
+                WorkQueue q;
+                if ((s = task.status) < 0)
+                    break;
+                else if (joiner.externalPopAndExecCC(task))
+                    k = scans;
+                else if ((s = task.status) < 0)
+                    break;
+                else if ((q = ws[j & m]) != null && q.pollAndExecCC(task))
+                    k = scans;
+                else if (--k < 0) {
+                    if (c == (c = ctl))
+                        break;
+                    k = scans;
+                }
+            }
+        }
+        return s;
     }
 
     // Exported methods
@@ -2578,11 +2354,6 @@
      * java.lang.Runtime#availableProcessors}, using the {@linkplain
      * #defaultForkJoinWorkerThreadFactory default thread factory},
      * no UncaughtExceptionHandler, and non-async LIFO processing mode.
-     *
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool() {
         this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
@@ -2598,10 +2369,6 @@
      * @param parallelism the parallelism level
      * @throws IllegalArgumentException if parallelism less than or
      *         equal to zero, or greater than implementation limit
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool(int parallelism) {
         this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
@@ -2626,10 +2393,6 @@
      * @throws IllegalArgumentException if parallelism less than or
      *         equal to zero, or greater than implementation limit
      * @throws NullPointerException if the factory is null
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool(int parallelism,
                         ForkJoinWorkerThreadFactory factory,
@@ -2638,7 +2401,7 @@
         this(checkParallelism(parallelism),
              checkFactory(factory),
              handler,
-             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
+             (asyncMode ? FIFO_QUEUE : LIFO_QUEUE),
              "ForkJoinPool-" + nextPoolId() + "-worker-");
         checkPermission();
     }
@@ -2669,7 +2432,8 @@
         this.workerNamePrefix = workerNamePrefix;
         this.factory = factory;
         this.ueh = handler;
-        this.config = (parallelism & SMASK) | mode;
+        this.mode = (short)mode;
+        this.parallelism = (short)parallelism;
         long np = (long)(-parallelism); // offset ctl counts
         this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
     }
@@ -2686,6 +2450,7 @@
      *
      * @return the common pool instance
      * @since 1.8
+     * @hide
      */
     public static ForkJoinPool commonPool() {
         // assert common != null : "static init error";
@@ -2714,7 +2479,7 @@
     public <T> T invoke(ForkJoinTask<T> task) {
         if (task == null)
             throw new NullPointerException();
-        externalSubmit(task);
+        externalPush(task);
         return task.join();
     }
 
@@ -2727,7 +2492,9 @@
      *         scheduled for execution
      */
     public void execute(ForkJoinTask<?> task) {
-        externalSubmit(task);
+        if (task == null)
+            throw new NullPointerException();
+        externalPush(task);
     }
 
     // AbstractExecutorService methods
@@ -2745,7 +2512,7 @@
             job = (ForkJoinTask<?>) task;
         else
             job = new ForkJoinTask.RunnableExecuteAction(task);
-        externalSubmit(job);
+        externalPush(job);
     }
 
     /**
@@ -2759,7 +2526,10 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
-        return externalSubmit(task);
+        if (task == null)
+            throw new NullPointerException();
+        externalPush(task);
+        return task;
     }
 
     /**
@@ -2768,7 +2538,9 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Callable<T> task) {
-        return externalSubmit(new ForkJoinTask.AdaptedCallable<T>(task));
+        ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
+        externalPush(job);
+        return job;
     }
 
     /**
@@ -2777,7 +2549,9 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Runnable task, T result) {
-        return externalSubmit(new ForkJoinTask.AdaptedRunnable<T>(task, result));
+        ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
+        externalPush(job);
+        return job;
     }
 
     /**
@@ -2793,7 +2567,8 @@
             job = (ForkJoinTask<?>) task;
         else
             job = new ForkJoinTask.AdaptedRunnableAction(task);
-        return externalSubmit(job);
+        externalPush(job);
+        return job;
     }
 
     /**
@@ -2804,21 +2579,23 @@
         // In previous versions of this class, this method constructed
         // a task to run ForkJoinTask.invokeAll, but now external
         // invocation of multiple tasks is at least as efficient.
-        ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
 
+        boolean done = false;
         try {
             for (Callable<T> t : tasks) {
                 ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
                 futures.add(f);
-                externalSubmit(f);
+                externalPush(f);
             }
             for (int i = 0, size = futures.size(); i < size; i++)
                 ((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
+            done = true;
             return futures;
-        } catch (Throwable t) {
-            for (int i = 0, size = futures.size(); i < size; i++)
-                futures.get(i).cancel(false);
-            throw t;
+        } finally {
+            if (!done)
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(false);
         }
     }
 
@@ -2848,7 +2625,7 @@
      */
     public int getParallelism() {
         int par;
-        return ((par = config & SMASK) > 0) ? par : 1;
+        return ((par = parallelism) > 0) ? par : 1;
     }
 
     /**
@@ -2856,9 +2633,10 @@
      *
      * @return the targeted parallelism level of the common pool
      * @since 1.8
+     * @hide
      */
     public static int getCommonPoolParallelism() {
-        return COMMON_PARALLELISM;
+        return commonParallelism;
     }
 
     /**
@@ -2870,7 +2648,7 @@
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
+        return parallelism + (short)(ctl >>> TC_SHIFT);
     }
 
     /**
@@ -2880,7 +2658,7 @@
      * @return {@code true} if this pool uses async mode
      */
     public boolean getAsyncMode() {
-        return (config & FIFO_QUEUE) != 0;
+        return mode == FIFO_QUEUE;
     }
 
     /**
@@ -2911,7 +2689,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
+        int r = parallelism + (int)(ctl >> AC_SHIFT);
         return (r <= 0) ? 0 : r; // suppress momentarily negative values
     }
 
@@ -2927,7 +2705,7 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return (config & SMASK) + (int)(ctl >> AC_SHIFT) <= 0;
+        return parallelism + (int)(ctl >> AC_SHIFT) <= 0;
     }
 
     /**
@@ -2942,8 +2720,7 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        AuxState sc = auxState;
-        long count = (sc == null) ? 0L : sc.stealCount;
+        long count = stealCount;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
@@ -3020,11 +2797,10 @@
      * @return the next submission, or {@code null} if none
      */
     protected ForkJoinTask<?> pollSubmission() {
-        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)
+        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)
                     return t;
             }
         }
@@ -3074,8 +2850,7 @@
     public String toString() {
         // Use a single pass through workQueues to collect counts
         long qt = 0L, qs = 0L; int rc = 0;
-        AuxState sc = auxState;
-        long st = (sc == null) ? 0L : sc.stealCount;
+        long st = stealCount;
         long c = ctl;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
@@ -3093,16 +2868,16 @@
                 }
             }
         }
-        int pc = (config & SMASK);
+        int pc = parallelism;
         int tc = pc + (short)(c >>> TC_SHIFT);
         int ac = pc + (int)(c >> AC_SHIFT);
         if (ac < 0) // ignore transient negative
             ac = 0;
-        int rs = runState;
-        String level = ((rs & TERMINATED) != 0 ? "Terminated" :
-                        (rs & STOP)       != 0 ? "Terminating" :
-                        (rs & SHUTDOWN)   != 0 ? "Shutting down" :
-                        "Running");
+        String level;
+        if ((c & STOP_BIT) != 0)
+            level = (tc == 0) ? "Terminated" : "Terminating";
+        else
+            level = plock < 0 ? "Shutting down" : "Running";
         return super.toString() +
             "[" + level +
             ", parallelism = " + pc +
@@ -3119,15 +2894,10 @@
      * Possibly initiates an orderly shutdown in which previously
      * submitted tasks are executed, but no new tasks will be
      * accepted. Invocation has no effect on execution state if this
-     * is the {@link #commonPool()}, and no additional effect if
+     * is the {@code commonPool()}, and no additional effect if
      * already shut down.  Tasks that are in the process of being
      * submitted concurrently during the course of this method may or
      * may not be rejected.
-     *
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public void shutdown() {
         checkPermission();
@@ -3137,7 +2907,7 @@
     /**
      * Possibly attempts to cancel and/or stop all tasks, and reject
      * all subsequently submitted tasks.  Invocation has no effect on
-     * execution state if this is the {@link #commonPool()}, and no
+     * execution state if this is the {@code commonPool()}, and no
      * additional effect if already shut down. Otherwise, tasks that
      * are in the process of being submitted or executed concurrently
      * during the course of this method may or may not be
@@ -3147,10 +2917,6 @@
      * (unlike the case for some other Executors).
      *
      * @return an empty list
-     * @throws SecurityException if a security manager exists and
-     *         the caller is not permitted to modify threads
-     *         because it does not hold {@link
-     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public List<Runnable> shutdownNow() {
         checkPermission();
@@ -3164,7 +2930,9 @@
      * @return {@code true} if all tasks have completed following shut down
      */
     public boolean isTerminated() {
-        return (runState & TERMINATED) != 0;
+        long c = ctl;
+        return ((c & STOP_BIT) != 0L &&
+                (short)(c >>> TC_SHIFT) + parallelism <= 0);
     }
 
     /**
@@ -3181,8 +2949,9 @@
      * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        int rs = runState;
-        return (rs & STOP) != 0 && (rs & TERMINATED) == 0;
+        long c = ctl;
+        return ((c & STOP_BIT) != 0L &&
+                (short)(c >>> TC_SHIFT) + parallelism > 0);
     }
 
     /**
@@ -3191,14 +2960,14 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return (runState & SHUTDOWN) != 0;
+        return plock < 0;
     }
 
     /**
      * Blocks until all tasks have completed execution after a
      * shutdown request, or the timeout occurs, or the current thread
-     * is interrupted, whichever happens first. Because the {@link
-     * #commonPool()} never terminates until program shutdown, when
+     * is interrupted, whichever happens first. Because the {@code
+     * commonPool()} never terminates until program shutdown, when
      * applied to the common pool, this method is equivalent to {@link
      * #awaitQuiescence(long, TimeUnit)} but always returns {@code false}.
      *
@@ -3257,20 +3026,19 @@
         }
         long startTime = System.nanoTime();
         WorkQueue[] ws;
-        int r = 0, wl;
+        int r = 0, m;
         boolean found = true;
         while (!isQuiescent() && (ws = workQueues) != null &&
-               (wl = ws.length) > 0) {
+               (m = ws.length - 1) >= 0) {
             if (!found) {
                 if ((System.nanoTime() - startTime) > nanos)
                     return false;
                 Thread.yield(); // cannot block
             }
             found = false;
-            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) {
+            for (int j = (m + 1) << 2; j >= 0; --j) {
+                ForkJoinTask<?> t; WorkQueue q; int b;
+                if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) {
                     found = true;
                     if ((t = q.pollAt(b)) != null)
                         t.doExec();
@@ -3283,7 +3051,7 @@
 
     /**
      * Waits and/or attempts to assist performing tasks indefinitely
-     * until the {@link #commonPool()} {@link #isQuiescent}.
+     * until the {@code commonPool()} {@link #isQuiescent}.
      */
     static void quiesceCommonPool() {
         common.awaitQuiescence(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
@@ -3294,8 +3062,8 @@
      * in {@link ForkJoinPool}s.
      *
      * <p>A {@code ManagedBlocker} provides two methods.  Method
-     * {@link #isReleasable} must return {@code true} if blocking is
-     * not necessary. Method {@link #block} blocks the current thread
+     * {@code isReleasable} must return {@code true} if blocking is
+     * not necessary. Method {@code block} blocks the current thread
      * if necessary (perhaps internally invoking {@code isReleasable}
      * before actually blocking). These actions are performed by any
      * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}.
@@ -3309,7 +3077,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;
@@ -3326,7 +3094,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;
@@ -3364,46 +3132,37 @@
     }
 
     /**
-     * Runs the given possibly blocking task.  When {@linkplain
-     * ForkJoinTask#inForkJoinPool() running in a ForkJoinPool}, this
-     * method possibly arranges for a spare thread to be activated if
-     * necessary to ensure sufficient parallelism while the current
-     * thread is blocked in {@link ManagedBlocker#block blocker.block()}.
+     * Blocks in accord with the given blocker.  If the current thread
+     * is a {@link ForkJoinWorkerThread}, this method possibly
+     * arranges for a spare thread to be activated if necessary to
+     * ensure sufficient parallelism while the current thread is blocked.
      *
-     * <p>This method repeatedly calls {@code blocker.isReleasable()} and
-     * {@code blocker.block()} until either method returns {@code true}.
-     * Every call to {@code blocker.block()} is preceded by a call to
-     * {@code blocker.isReleasable()} that returned {@code false}.
-     *
-     * <p>If not running in a ForkJoinPool, this method is
+     * <p>If the caller is not a {@link ForkJoinTask}, this method is
      * behaviorally equivalent to
-     * <pre> {@code
+     *  <pre> {@code
      * while (!blocker.isReleasable())
      *   if (blocker.block())
-     *     break;}</pre>
+     *     return;
+     * }</pre>
      *
-     * If running in a ForkJoinPool, the pool may first be expanded to
-     * ensure sufficient parallelism available during the call to
-     * {@code blocker.block()}.
+     * If the caller is a {@code ForkJoinTask}, then the pool may
+     * first be expanded to ensure parallelism, and later adjusted.
      *
-     * @param blocker the blocker task
-     * @throws InterruptedException if {@code blocker.block()} did so
+     * @param blocker the blocker
+     * @throws InterruptedException if blocker.block did so
      */
     public static void managedBlock(ManagedBlocker blocker)
         throws InterruptedException {
-        ForkJoinPool p;
-        ForkJoinWorkerThread wt;
         Thread t = Thread.currentThread();
-        if ((t instanceof ForkJoinWorkerThread) &&
-            (p = (wt = (ForkJoinWorkerThread)t).pool) != null) {
-            WorkQueue w = wt.workQueue;
+        if (t instanceof ForkJoinWorkerThread) {
+            ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
             while (!blocker.isReleasable()) {
-                if (p.tryCompensate(w)) {
+                if (p.tryCompensate(p.ctl)) {
                     try {
                         do {} while (!blocker.isReleasable() &&
                                      !blocker.block());
                     } finally {
-                        U.getAndAddLong(p, CTL, AC_UNIT);
+                        p.incrementActiveCount();
                     }
                     break;
                 }
@@ -3428,40 +3187,49 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final sun.misc.Unsafe U;
     private static final long CTL;
-    private static final long RUNSTATE;
+    private static final long PARKBLOCKER;
     private static final int ABASE;
     private static final int ASHIFT;
+    private static final long STEALCOUNT;
+    private static final long PLOCK;
+    private static final long INDEXSEED;
+    private static final long QBASE;
+    private static final long QLOCK;
 
     static {
+        // initialize field offsets for CAS etc
         try {
+            U = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ForkJoinPool.class;
             CTL = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("ctl"));
-            RUNSTATE = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("runState"));
-            ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-            int scale = U.arrayIndexScale(ForkJoinTask[].class);
+                (k.getDeclaredField("ctl"));
+            STEALCOUNT = U.objectFieldOffset
+                (k.getDeclaredField("stealCount"));
+            PLOCK = U.objectFieldOffset
+                (k.getDeclaredField("plock"));
+            INDEXSEED = U.objectFieldOffset
+                (k.getDeclaredField("indexSeed"));
+            Class<?> tk = Thread.class;
+            PARKBLOCKER = U.objectFieldOffset
+                (tk.getDeclaredField("parkBlocker"));
+            Class<?> wk = WorkQueue.class;
+            QBASE = U.objectFieldOffset
+                (wk.getDeclaredField("base"));
+            QLOCK = U.objectFieldOffset
+                (wk.getDeclaredField("qlock"));
+            Class<?> ak = ForkJoinTask[].class;
+            ABASE = U.arrayBaseOffset(ak);
+            int scale = U.arrayIndexScale(ak);
             if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
+                throw new Error("data type scale not a power of two");
             ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
+        } catch (Exception 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;
-
-        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;
-
+        submitters = new ThreadLocal<Submitter>();
         defaultForkJoinWorkerThreadFactory =
             new DefaultForkJoinWorkerThreadFactory();
         modifyThreadPermission = new RuntimePermission("modifyThread");
@@ -3469,18 +3237,18 @@
         common = java.security.AccessController.doPrivileged
             (new java.security.PrivilegedAction<ForkJoinPool>() {
                 public ForkJoinPool run() { return makeCommonPool(); }});
-
-        // report 1 even if threads disabled
-        COMMON_PARALLELISM = Math.max(common.config & SMASK, 1);
+        int par = common.parallelism; // report 1 even if threads disabled
+        commonParallelism = par > 0 ? par : 1;
     }
 
     /**
      * Creates and returns the common pool, respecting user settings
      * specified via system properties.
      */
-    static ForkJoinPool makeCommonPool() {
+    private static ForkJoinPool makeCommonPool() {
         int parallelism = -1;
-        ForkJoinWorkerThreadFactory factory = null;
+        ForkJoinWorkerThreadFactory factory
+            = defaultForkJoinWorkerThreadFactory;
         UncaughtExceptionHandler handler = null;
         try {  // ignore exceptions in accessing/parsing properties
             String pp = System.getProperty
@@ -3499,52 +3267,14 @@
                            getSystemClassLoader().loadClass(hp).newInstance());
         } catch (Exception ignore) {
         }
-        if (factory == null) {
-            if (System.getSecurityManager() == null)
-                factory = defaultForkJoinWorkerThreadFactory;
-            else // use security-managed default
-                factory = new InnocuousForkJoinWorkerThreadFactory();
-        }
+
         if (parallelism < 0 && // default 1 less than #cores
-            (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
-            parallelism = 1;
+            (parallelism = Runtime.getRuntime().availableProcessors() - 1) < 0)
+            parallelism = 0;
         if (parallelism > MAX_CAP)
             parallelism = MAX_CAP;
         return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
                                 "ForkJoinPool.commonPool-worker-");
     }
 
-    /**
-     * Factory for innocuous worker threads.
-     */
-    private static final class InnocuousForkJoinWorkerThreadFactory
-        implements ForkJoinWorkerThreadFactory {
-
-        /**
-         * An ACC to restrict permissions for the factory itself.
-         * The constructed workers have no permissions set.
-         */
-        private static final AccessControlContext innocuousAcc;
-        static {
-            Permissions innocuousPerms = new Permissions();
-            innocuousPerms.add(modifyThreadPermission);
-            innocuousPerms.add(new RuntimePermission(
-                                   "enableContextClassLoaderOverride"));
-            innocuousPerms.add(new RuntimePermission(
-                                   "modifyThreadGroup"));
-            innocuousAcc = new AccessControlContext(new ProtectionDomain[] {
-                    new ProtectionDomain(null, innocuousPerms)
-                });
-        }
-
-        public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            return java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
-                    public ForkJoinWorkerThread run() {
-                        return new ForkJoinWorkerThread.
-                            InnocuousForkJoinWorkerThread(pool);
-                    }}, innocuousAcc);
-        }
-    }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
index a8d97db..3a1a381 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -7,17 +7,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.locks.ReentrantLock;
-
-// BEGIN android-note
-// removed java 9 code
-// END android-note
+import java.lang.reflect.Constructor;
 
 /**
  * Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -28,8 +24,8 @@
  *
  * <p>A "main" {@code ForkJoinTask} begins execution when it is
  * explicitly submitted to a {@link ForkJoinPool}, or, if not already
- * engaged in a ForkJoin computation, commenced in the {@link
- * ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or
+ * engaged in a ForkJoin computation, commenced in the {@code
+ * ForkJoinPool.commonPool()} via {@link #fork}, {@link #invoke}, or
  * related methods.  Once started, it will usually in turn start other
  * subtasks.  As indicated by the name of this class, many programs
  * using {@code ForkJoinTask} employ only methods {@link #fork} and
@@ -70,10 +66,9 @@
  * but doing do requires three further considerations: (1) Completion
  * of few if any <em>other</em> tasks should be dependent on a task
  * that blocks on external synchronization or I/O. Event-style async
- * tasks that are never joined (for example, those subclassing {@link
- * CountedCompleter}) often fall into this category.  (2) To minimize
- * resource impact, tasks should be small; ideally performing only the
- * (possibly) blocking action. (3) Unless the {@link
+ * tasks that are never joined often fall into this category.
+ * (2) To minimize resource impact, tasks should be small; ideally
+ * performing only the (possibly) blocking action. (3) Unless the {@link
  * ForkJoinPool.ManagedBlocker} API is used, or the number of possibly
  * blocked tasks is known to be less than the pool's {@link
  * ForkJoinPool#getParallelism} level, the pool cannot guarantee that
@@ -116,13 +111,11 @@
  * <p>The ForkJoinTask class is not usually directly subclassed.
  * Instead, you subclass one of the abstract classes that support a
  * particular style of fork/join processing, typically {@link
- * RecursiveAction} for most computations that do not return results,
- * {@link RecursiveTask} for those that do, and {@link
- * CountedCompleter} for those in which completed actions trigger
- * other actions.  Normally, a concrete ForkJoinTask subclass declares
- * fields comprising its parameters, established in a constructor, and
- * then defines a {@code compute} method that somehow uses the control
- * methods supplied by this base class.
+ * RecursiveAction} for most computations that do not return results
+ * and {@link RecursiveTask} for those that do. Normally, a concrete
+ * ForkJoinTask subclass declares fields comprising its parameters,
+ * established in a constructor, and then defines a {@code compute}
+ * method that somehow uses the control methods supplied by this base class.
  *
  * <p>Method {@link #join} and its variants are appropriate for use
  * only when completion dependencies are acyclic; that is, the
@@ -134,9 +127,9 @@
  * may be of use in constructing custom subclasses for problems that
  * are not statically structured as DAGs. To support such usages, a
  * ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
- * value using {@link #setForkJoinTaskTag} or {@link
- * #compareAndSetForkJoinTaskTag} and checked using {@link
- * #getForkJoinTaskTag}. The ForkJoinTask implementation does not use
+ * value using {@code setForkJoinTaskTag} or {@code
+ * compareAndSetForkJoinTaskTag} and checked using {@code
+ * getForkJoinTaskTag}. The ForkJoinTask implementation does not use
  * these {@code protected} methods or tags for any purpose, but they
  * may be of use in the construction of specialized subclasses.  For
  * example, parallel graph traversals can use the supplied methods to
@@ -176,6 +169,8 @@
  * @since 1.7
  * @author Doug Lea
  */
+// android-note: Removed references to hidden apis commonPool, CountedCompleter
+// etc.
 public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
 
     /*
@@ -264,22 +259,15 @@
     }
 
     /**
-     * If not done, sets SIGNAL status and performs Object.wait(timeout).
-     * This task may or may not be done on exit. Ignores interrupts.
+     * Tries to set SIGNAL status unless already completed. Used by
+     * ForkJoinPool. Other variants are directly incorporated into
+     * externalAwaitDone etc.
      *
-     * @param timeout using Object.wait conventions.
+     * @return true if successful
      */
-    final void internalWait(long timeout) {
-        int s;
-        if ((s = status) >= 0 && // force completer to issue notify
-            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-            synchronized (this) {
-                if (status >= 0)
-                    try { wait(timeout); } catch (InterruptedException ie) { }
-                else
-                    notifyAll();
-            }
-        }
+    final boolean trySetSignal() {
+        int s = status;
+        return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL);
     }
 
     /**
@@ -287,29 +275,35 @@
      * @return status upon completion
      */
     private int externalAwaitDone() {
-        int s = ((this instanceof CountedCompleter) ? // try helping
-                 ForkJoinPool.common.externalHelpComplete(
-                     (CountedCompleter<?>)this, 0) :
-                 ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
-        if (s >= 0 && (s = status) >= 0) {
-            boolean interrupted = false;
-            do {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                    synchronized (this) {
-                        if (status >= 0) {
-                            try {
-                                wait(0L);
-                            } catch (InterruptedException ie) {
-                                interrupted = true;
+        int s;
+        ForkJoinPool cp = ForkJoinPool.common;
+        if ((s = status) >= 0) {
+            if (cp != null) {
+                if (this instanceof CountedCompleter)
+                    s = cp.externalHelpComplete((CountedCompleter<?>)this);
+                else if (cp.tryExternalUnpush(this))
+                    s = doExec();
+            }
+            if (s >= 0 && (s = status) >= 0) {
+                boolean interrupted = false;
+                do {
+                    if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                        synchronized (this) {
+                            if (status >= 0) {
+                                try {
+                                    wait();
+                                } catch (InterruptedException ie) {
+                                    interrupted = true;
+                                }
                             }
+                            else
+                                notifyAll();
                         }
-                        else
-                            notifyAll();
                     }
-                }
-            } while ((s = status) >= 0);
-            if (interrupted)
-                Thread.currentThread().interrupt();
+                } while ((s = status) >= 0);
+                if (interrupted)
+                    Thread.currentThread().interrupt();
+            }
         }
         return s;
     }
@@ -319,22 +313,22 @@
      */
     private int externalInterruptibleAwaitDone() throws InterruptedException {
         int s;
+        ForkJoinPool cp = ForkJoinPool.common;
         if (Thread.interrupted())
             throw new InterruptedException();
-        if ((s = status) >= 0 &&
-            (s = ((this instanceof CountedCompleter) ?
-                  ForkJoinPool.common.externalHelpComplete(
-                      (CountedCompleter<?>)this, 0) :
-                  ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
-                  0)) >= 0) {
-            while ((s = status) >= 0) {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                    synchronized (this) {
-                        if (status >= 0)
-                            wait(0L);
-                        else
-                            notifyAll();
-                    }
+        if ((s = status) >= 0 && cp != null) {
+            if (this instanceof CountedCompleter)
+                cp.externalHelpComplete((CountedCompleter<?>)this);
+            else if (cp.tryExternalUnpush(this))
+                doExec();
+        }
+        while ((s = status) >= 0) {
+            if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                synchronized (this) {
+                    if (status >= 0)
+                        wait();
+                    else
+                        notifyAll();
                 }
             }
         }
@@ -354,7 +348,7 @@
             ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
             (w = (wt = (ForkJoinWorkerThread)t).workQueue).
             tryUnpush(this) && (s = doExec()) < 0 ? s :
-            wt.pool.awaitJoin(w, this, 0L) :
+            wt.pool.awaitJoin(w, this) :
             externalAwaitDone();
     }
 
@@ -367,8 +361,7 @@
         int s; Thread t; ForkJoinWorkerThread wt;
         return (s = doExec()) < 0 ? s :
             ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
-            (wt = (ForkJoinWorkerThread)t).pool.
-            awaitJoin(wt.workQueue, this, 0L) :
+            (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) :
             externalAwaitDone();
     }
 
@@ -409,8 +402,7 @@
         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,
-                      ReferenceQueue<Object> exceptionTableRefQueue) {
+        ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) {
             super(task, exceptionTableRefQueue);
             this.ex = ex;
             this.next = next;
@@ -436,8 +428,7 @@
                 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],
-                                                 exceptionTableRefQueue);
+                        t[i] = new ExceptionNode(this, ex, t[i]);
                         break;
                     }
                     if (e.get() == this) // already present
@@ -516,20 +507,22 @@
     }
 
     /**
-     * Returns a rethrowable exception for this task, if available.
-     * To provide accurate stack traces, if the exception was not
-     * thrown by the current thread, we try to create a new exception
-     * of the same type as the one thrown, but with the recorded
-     * exception as its cause. If there is no such constructor, we
-     * instead try to use a no-arg constructor, followed by initCause,
-     * to the same effect. If none of these apply, or any fail due to
-     * other exceptions, we return the recorded exception, which is
-     * still correct, although it may contain a misleading stack
-     * trace.
+     * Returns a rethrowable exception for the given task, if
+     * available. To provide accurate stack traces, if the exception
+     * was not thrown by the current thread, we try to create a new
+     * exception of the same type as the one thrown, but with the
+     * recorded exception as its cause. If there is no such
+     * constructor, we instead try to use a no-arg constructor,
+     * followed by initCause, to the same effect. If none of these
+     * apply, or any fail due to other exceptions, we return the
+     * recorded exception, which is still correct, although it may
+     * contain a misleading stack trace.
      *
      * @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;
@@ -546,19 +539,21 @@
         Throwable ex;
         if (e == null || (ex = e.ex) == null)
             return null;
-        if (e.thrower != Thread.currentThread().getId()) {
+        if (false && e.thrower != Thread.currentThread().getId()) {
+            Class<? extends Throwable> ec = ex.getClass();
             try {
                 Constructor<?> noArgCtor = null;
-                // public ctors only
-                for (Constructor<?> c : ex.getClass().getConstructors()) {
+                Constructor<?>[] cs = ec.getConstructors();// public ctors only
+                for (int i = 0; i < cs.length; ++i) {
+                    Constructor<?> c = cs[i];
                     Class<?>[] ps = c.getParameterTypes();
                     if (ps.length == 0)
                         noArgCtor = c;
                     else if (ps.length == 1 && ps[0] == Throwable.class)
-                        return (Throwable)c.newInstance(ex);
+                        return (Throwable)(c.newInstance(ex));
                 }
                 if (noArgCtor != null) {
-                    Throwable wx = (Throwable)noArgCtor.newInstance();
+                    Throwable wx = (Throwable)(noArgCtor.newInstance());
                     wx.initCause(ex);
                     return wx;
                 }
@@ -569,7 +564,7 @@
     }
 
     /**
-     * Polls stale refs and removes them. Call only while holding lock.
+     * Poll stale refs and remove them. Call only while holding lock.
      */
     private static void expungeStaleExceptions() {
         for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
@@ -596,7 +591,7 @@
     }
 
     /**
-     * If lock is available, polls stale refs and removes them.
+     * If lock is available, poll stale refs and remove them.
      * Called from ForkJoinPool when pools become quiescent.
      */
     static final void helpExpungeStaleExceptions() {
@@ -611,23 +606,21 @@
     }
 
     /**
-     * A version of "sneaky throw" to relay exceptions.
+     * A version of "sneaky throw" to relay exceptions
      */
     static void rethrow(Throwable ex) {
-        ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
+        if (ex != null)
+            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 {
-        if (t != null)
-            throw (T)t; // rely on vacuous cast
-        else
-            throw new Error("Unknown Exception");
+        void uncheckedThrow(Throwable t) throws T {
+        throw (T)t; // rely on vacuous cast
     }
 
     /**
@@ -644,8 +637,8 @@
 
     /**
      * Arranges to asynchronously execute this task in the pool the
-     * current task is running in, if applicable, or using the {@link
-     * ForkJoinPool#commonPool()} if not {@link #inForkJoinPool}.  While
+     * current task is running in, if applicable, or using the {@code
+     * ForkJoinPool.commonPool()} if not {@link #inForkJoinPool}.  While
      * it is not necessarily enforced, it is a usage error to fork a
      * task more than once unless it has completed and been
      * reinitialized.  Subsequent modifications to the state of this
@@ -943,6 +936,7 @@
      * invocations of {@code join} and related operations.
      *
      * @since 1.8
+     * @hide
      */
     public final void quietlyComplete() {
         setCompletion(NORMAL);
@@ -962,10 +956,11 @@
     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)
-            throw new ExecutionException(getThrowableException());
+        if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
+            throw new ExecutionException(ex);
         return getRawResult();
     }
 
@@ -985,46 +980,75 @@
      */
     public final V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
-        int s;
-        long nanos = unit.toNanos(timeout);
         if (Thread.interrupted())
             throw new InterruptedException();
-        if ((s = status) >= 0 && nanos > 0L) {
-            long d = System.nanoTime() + nanos;
-            long deadline = (d == 0L) ? 1L : d; // avoid 0
+        // Messy in part because we measure in nanosecs, but wait in millisecs
+        int s; long ms;
+        long ns = unit.toNanos(timeout);
+        ForkJoinPool cp;
+        if ((s = status) >= 0 && ns > 0L) {
+            long deadline = System.nanoTime() + ns;
+            ForkJoinPool p = null;
+            ForkJoinPool.WorkQueue w = null;
             Thread t = Thread.currentThread();
             if (t instanceof ForkJoinWorkerThread) {
                 ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
-                s = wt.pool.awaitJoin(wt.workQueue, this, deadline);
+                p = wt.pool;
+                w = wt.workQueue;
+                p.helpJoinOnce(w, this); // no retries on failure
             }
-            else if ((s = ((this instanceof CountedCompleter) ?
-                           ForkJoinPool.common.externalHelpComplete(
-                               (CountedCompleter<?>)this, 0) :
-                           ForkJoinPool.common.tryExternalUnpush(this) ?
-                           doExec() : 0)) >= 0) {
-                long ns, ms; // measure in nanosecs, but wait in millisecs
-                while ((s = status) >= 0 &&
-                       (ns = deadline - System.nanoTime()) > 0L) {
-                    if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
-                        U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                        synchronized (this) {
-                            if (status >= 0)
-                                wait(ms); // OK to throw InterruptedException
-                            else
-                                notifyAll();
+            else if ((cp = ForkJoinPool.common) != null) {
+                if (this instanceof CountedCompleter)
+                    cp.externalHelpComplete((CountedCompleter<?>)this);
+                else if (cp.tryExternalUnpush(this))
+                    doExec();
+            }
+            boolean canBlock = false;
+            boolean interrupted = false;
+            try {
+                while ((s = status) >= 0) {
+                    if (w != null && w.qlock < 0)
+                        cancelIgnoringExceptions(this);
+                    else if (!canBlock) {
+                        if (p == null || p.tryCompensate(p.ctl))
+                            canBlock = true;
+                    }
+                    else {
+                        if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
+                            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                            synchronized (this) {
+                                if (status >= 0) {
+                                    try {
+                                        wait(ms);
+                                    } catch (InterruptedException ie) {
+                                        if (p == null)
+                                            interrupted = true;
+                                    }
+                                }
+                                else
+                                    notifyAll();
+                            }
                         }
+                        if ((s = status) < 0 || interrupted ||
+                            (ns = deadline - System.nanoTime()) <= 0L)
+                            break;
                     }
                 }
+            } finally {
+                if (p != null && canBlock)
+                    p.incrementActiveCount();
             }
+            if (interrupted)
+                throw new InterruptedException();
         }
-        if (s >= 0)
-            s = status;
         if ((s &= DONE_MASK) != NORMAL) {
+            Throwable ex;
             if (s == CANCELLED)
                 throw new CancellationException();
             if (s != EXCEPTIONAL)
                 throw new TimeoutException();
-            throw new ExecutionException(getThrowableException());
+            if ((ex = getThrowableException()) != null)
+                throw new ExecutionException(ex);
         }
         return getRawResult();
     }
@@ -1050,10 +1074,10 @@
 
     /**
      * Possibly executes tasks until the pool hosting the current task
-     * {@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.
+     * {@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.
      */
     public static void helpQuiesce() {
         Thread t;
@@ -1089,12 +1113,10 @@
     }
 
     /**
-     * Returns the pool hosting the current thread, or {@code null}
-     * if the current thread is executing outside of any ForkJoinPool.
+     * Returns the pool hosting the current task execution, or null
+     * if this task is executing outside of any ForkJoinPool.
      *
-     * <p>This method returns {@code null} if and only if {@link
-     * #inForkJoinPool} returns {@code false}.
-     *
+     * @see #inForkJoinPool
      * @return the pool, or {@code null} if none
      */
     public static ForkJoinPool getPool() {
@@ -1261,25 +1283,6 @@
             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 9
-     * @hide
-     */
-    // android-changed - hidden
-    protected static ForkJoinTask<?> pollSubmission() {
-        Thread t;
-        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
-            ((ForkJoinWorkerThread)t).pool.pollSubmission() : null;
-    }
-
     // tag operations
 
     /**
@@ -1287,22 +1290,24 @@
      *
      * @return the tag for this task
      * @since 1.8
+     * @hide
      */
     public final short getForkJoinTaskTag() {
         return (short)status;
     }
 
     /**
-     * Atomically sets the tag value for this task and returns the old value.
+     * Atomically sets the tag value for this task.
      *
-     * @param newValue the new tag value
+     * @param tag the tag value
      * @return the previous value of the tag
      * @since 1.8
+     * @hide
      */
-    public final short setForkJoinTaskTag(short newValue) {
+    public final short setForkJoinTaskTag(short tag) {
         for (int s;;) {
             if (U.compareAndSwapInt(this, STATUS, s = status,
-                                    (s & ~SMASK) | (newValue & SMASK)))
+                                    (s & ~SMASK) | (tag & SMASK)))
                 return (short)s;
         }
     }
@@ -1315,24 +1320,25 @@
      * before processing, otherwise exiting because the node has
      * already been visited.
      *
-     * @param expect the expected tag value
-     * @param update the new tag value
+     * @param e the expected tag value
+     * @param tag the new tag value
      * @return {@code true} if successful; i.e., the current value was
-     * equal to {@code expect} and was changed to {@code update}.
+     * equal to e and is now tag.
      * @since 1.8
+     * @hide
      */
-    public final boolean compareAndSetForkJoinTaskTag(short expect, short update) {
+    public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
         for (int s;;) {
-            if ((short)(s = status) != expect)
+            if ((short)(s = status) != e)
                 return false;
             if (U.compareAndSwapInt(this, STATUS, s,
-                                    (s & ~SMASK) | (update & SMASK)))
+                                    (s & ~SMASK) | (tag & SMASK)))
                 return true;
         }
     }
 
     /**
-     * Adapter for Runnables. This implements RunnableFuture
+     * Adaptor for Runnables. This implements RunnableFuture
      * to be compliant with AbstractExecutorService constraints
      * when used in ForkJoinPool.
      */
@@ -1353,7 +1359,7 @@
     }
 
     /**
-     * Adapter for Runnables without results.
+     * Adaptor for Runnables without results
      */
     static final class AdaptedRunnableAction extends ForkJoinTask<Void>
         implements RunnableFuture<Void> {
@@ -1370,7 +1376,7 @@
     }
 
     /**
-     * Adapter for Runnables in which failure forces worker exception.
+     * Adaptor for Runnables in which failure forces worker exception
      */
     static final class RunnableExecuteAction extends ForkJoinTask<Void> {
         final Runnable runnable;
@@ -1388,7 +1394,7 @@
     }
 
     /**
-     * Adapter for Callables.
+     * Adaptor for Callables
      */
     static final class AdaptedCallable<T> extends ForkJoinTask<T>
         implements RunnableFuture<T> {
@@ -1461,8 +1467,6 @@
     /**
      * Saves this task to a stream (that is, serializes it).
      *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData the current run status and the exception thrown
      * during execution, or {@code null} if none
      */
@@ -1474,10 +1478,6 @@
 
     /**
      * Reconstitutes this task 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 {
@@ -1488,7 +1488,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final sun.misc.Unsafe U;
     private static final long STATUS;
 
     static {
@@ -1496,11 +1496,12 @@
         exceptionTableRefQueue = new ReferenceQueue<Object>();
         exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
         try {
+            U = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ForkJoinTask.class;
             STATUS = U.objectFieldOffset
-                (ForkJoinTask.class.getDeclaredField("status"));
-        } catch (ReflectiveOperationException e) {
+                (k.getDeclaredField("status"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
index 664d56e..ae28700 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
@@ -6,9 +6,6 @@
 
 package java.util.concurrent;
 
-import java.security.AccessControlContext;
-import java.security.ProtectionDomain;
-
 /**
  * A thread managed by a {@link ForkJoinPool}, which executes
  * {@link ForkJoinTask}s.
@@ -35,10 +32,6 @@
      * completes. This leads to a visibility race, that is tolerated
      * by requiring that the workQueue field is only accessed by the
      * owning thread.
-     *
-     * Support for (non-public) subclass InnocuousForkJoinWorkerThread
-     * requires that we break quite a lot of encapsulation (via Unsafe)
-     * both here and in the subclass to access and set Thread fields.
      */
 
     final ForkJoinPool pool;                // the pool this thread works in
@@ -58,18 +51,6 @@
     }
 
     /**
-     * Version for InnocuousForkJoinWorkerThread.
-     */
-    ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
-                         AccessControlContext acc) {
-        super(threadGroup, null, "aForkJoinWorkerThread");
-        U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
-        eraseThreadLocals(); // clear before registering
-        this.pool = pool;
-        this.workQueue = pool.registerWorker(this);
-    }
-
-    /**
      * Returns the pool hosting this thread.
      *
      * @return the pool
@@ -89,7 +70,7 @@
      * @return the index number
      */
     public int getPoolIndex() {
-        return workQueue.getPoolIndex();
+        return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
     }
 
     /**
@@ -121,124 +102,21 @@
      * {@link ForkJoinTask}s.
      */
     public void run() {
-        if (workQueue.array == null) { // only run once
-            Throwable exception = null;
-            try {
-                onStart();
-                pool.runWorker(workQueue);
-            } catch (Throwable ex) {
-                exception = ex;
-            } finally {
-                try {
-                    onTermination(exception);
-                } catch (Throwable ex) {
-                    if (exception == null)
-                        exception = ex;
-                } finally {
-                    pool.deregisterWorker(this, exception);
-                }
-            }
-        }
-    }
-
-    /**
-     * Erases ThreadLocals by nulling out Thread maps.
-     */
-    final void eraseThreadLocals() {
-        U.putObject(this, THREADLOCALS, null);
-        U.putObject(this, INHERITABLETHREADLOCALS, null);
-    }
-
-    /**
-     * Non-public hook method for InnocuousForkJoinWorkerThread.
-     */
-    void afterTopLevelExec() {
-    }
-
-    // Set up to allow setting thread fields in constructor
-    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 {
+        Throwable exception = null;
         try {
-            THREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocals"));
-            INHERITABLETHREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritableThreadLocals"));
-            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
-    /**
-     * A worker thread that has no permissions, is not a member of any
-     * user-defined ThreadGroup, and erases all ThreadLocals after
-     * running each top-level task.
-     */
-    static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
-        /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
-        private static final ThreadGroup innocuousThreadGroup =
-            createThreadGroup();
-
-        /** An AccessControlContext supporting no privileges */
-        private static final AccessControlContext INNOCUOUS_ACC =
-            new AccessControlContext(
-                new ProtectionDomain[] {
-                    new ProtectionDomain(null, null)
-                });
-
-        InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
-            super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
-        }
-
-        @Override // to erase ThreadLocals
-        void afterTopLevelExec() {
-            eraseThreadLocals();
-        }
-
-        @Override // to always report system loader
-        public ClassLoader getContextClassLoader() {
-            return ClassLoader.getSystemClassLoader();
-        }
-
-        @Override // to silently fail
-        public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
-
-        @Override // paranoically
-        public void setContextClassLoader(ClassLoader cl) {
-            throw new SecurityException("setContextClassLoader");
-        }
-
-        /**
-         * Returns a new group with the system ThreadGroup (the
-         * topmost, parent-less group) as parent.  Uses Unsafe to
-         * traverse Thread.group and ThreadGroup.parent fields.
-         */
-        private static ThreadGroup createThreadGroup() {
+            onStart();
+            pool.runWorker(workQueue);
+        } catch (Throwable ex) {
+            exception = ex;
+        } finally {
             try {
-                sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
-                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) {
-                    ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);
-                    if (parent == null)
-                        return new ThreadGroup(group,
-                                               "InnocuousForkJoinWorkerThreadGroup");
-                    group = parent;
-                }
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                onTermination(exception);
+            } catch (Throwable ex) {
+                if (exception == null)
+                    exception = ex;
+            } finally {
+                pool.deregisterWorker(this, exception);
             }
-            // fall through if null as cannot-happen safeguard
-            throw new Error("Cannot create ThreadGroup");
         }
     }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/Future.java b/luni/src/main/java/java/util/concurrent/Future.java
index 28d2de5..32e8145 100644
--- a/luni/src/main/java/java/util/concurrent/Future.java
+++ b/luni/src/main/java/java/util/concurrent/Future.java
@@ -23,9 +23,8 @@
  *
  * <p>
  * <b>Sample Usage</b> (Note that the following classes are all
- * made-up.)
- *
- * <pre> {@code
+ * made-up.) <p>
+ *  <pre> {@code
  * interface ArchiveSearcher { String search(String target); }
  * class App {
  *   ExecutorService executor = ...
@@ -47,9 +46,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<>(new Callable<String>() {
+ *   new FutureTask<String>(new Callable<String>() {
  *     public String call() {
  *       return searcher.search(target);
  *   }});
diff --git a/luni/src/main/java/java/util/concurrent/FutureTask.java b/luni/src/main/java/java/util/concurrent/FutureTask.java
index ed42817..5e24fc8 100644
--- a/luni/src/main/java/java/util/concurrent/FutureTask.java
+++ b/luni/src/main/java/java/util/concurrent/FutureTask.java
@@ -367,7 +367,7 @@
         throws InterruptedException {
         // The code below is very delicate, to achieve these goals:
         // - call nanoTime exactly once for each call to park
-        // - if nanos <= 0L, return promptly without allocation or nanoTime
+        // - if nanos <= 0, 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
@@ -467,7 +467,7 @@
                 (FutureTask.class.getDeclaredField("runner"));
             WAITERS = U.objectFieldOffset
                 (FutureTask.class.getDeclaredField("waiters"));
-        } catch (ReflectiveOperationException e) {
+        } catch (Exception e) {
             throw new Error(e);
         }
 
diff --git a/luni/src/main/java/java/util/concurrent/Helpers.java b/luni/src/main/java/java/util/concurrent/Helpers.java
deleted file mode 100644
index 9051e2f..0000000
--- a/luni/src/main/java/java/util/concurrent/Helpers.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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;
-    }
-}
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
index b1d196d..64b0bf1 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
@@ -10,11 +10,8 @@
 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.function.Consumer;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -43,7 +40,7 @@
  *
  * @since 1.6
  * @author  Doug Lea
- * @param <E> the type of elements held in this deque
+ * @param <E> the type of elements held in this collection
  */
 public class LinkedBlockingDeque<E>
     extends AbstractQueue<E>
@@ -289,8 +286,8 @@
     // BlockingDeque methods
 
     /**
-     * @throws IllegalStateException if this deque is full
-     * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalStateException {@inheritDoc}
+     * @throws NullPointerException  {@inheritDoc}
      */
     public void addFirst(E e) {
         if (!offerFirst(e))
@@ -298,7 +295,7 @@
     }
 
     /**
-     * @throws IllegalStateException if this deque is full
+     * @throws IllegalStateException {@inheritDoc}
      * @throws NullPointerException  {@inheritDoc}
      */
     public void addLast(E e) {
@@ -383,7 +380,7 @@
         lock.lockInterruptibly();
         try {
             while (!linkFirst(node)) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -406,7 +403,7 @@
         lock.lockInterruptibly();
         try {
             while (!linkLast(node)) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -488,7 +485,7 @@
         try {
             E x;
             while ( (x = unlinkFirst()) == null) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -506,7 +503,7 @@
         try {
             E x;
             while ( (x = unlinkLast()) == null) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -597,7 +594,8 @@
      *
      * <p>This method is equivalent to {@link #addLast}.
      *
-     * @throws IllegalStateException if this deque is full
+     * @throws IllegalStateException if the element cannot be added at this
+     *         time due to capacity restrictions
      * @throws NullPointerException if the specified element is null
      */
     public boolean add(E e) {
@@ -734,8 +732,8 @@
     // Stack methods
 
     /**
-     * @throws IllegalStateException if this deque is full
-     * @throws NullPointerException {@inheritDoc}
+     * @throws IllegalStateException {@inheritDoc}
+     * @throws NullPointerException  {@inheritDoc}
      */
     public void push(E e) {
         addFirst(e);
@@ -825,7 +823,7 @@
 //      * @throws ClassCastException            {@inheritDoc}
 //      * @throws NullPointerException          {@inheritDoc}
 //      * @throws IllegalArgumentException      {@inheritDoc}
-//      * @throws IllegalStateException if this deque is full
+//      * @throws IllegalStateException         {@inheritDoc}
 //      * @see #add(Object)
 //      */
 //     public boolean addAll(Collection<? extends E> c) {
@@ -895,7 +893,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()}.
@@ -930,7 +928,26 @@
     }
 
     public String toString() {
-        return Helpers.collectionToString(this);
+        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();
+        }
     }
 
     /**
@@ -960,8 +977,12 @@
      * Returns an iterator over the elements in this deque in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this deque in proper sequence
      */
@@ -974,8 +995,12 @@
      * sequential order.  The elements will be returned in order from
      * last (tail) to first (head).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this deque in reverse order
      */
@@ -984,11 +1009,11 @@
     }
 
     /**
-     * Base class for LinkedBlockingDeque iterators.
+     * Base class for Iterators for LinkedBlockingDeque
      */
     private abstract class AbstractItr implements Iterator<E> {
         /**
-         * The next node to return in next().
+         * The next node to return in next()
          */
         Node<E> next;
 
@@ -1097,149 +1122,9 @@
         Node<E> nextNode(Node<E> n) { return n.prev; }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LBDSpliterator<E> implements Spliterator<E> {
-        static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedBlockingDeque<E> queue;
-        Node<E> current;    // current node; null until initialized
-        int batch;          // batch size for splits
-        boolean exhausted;  // true when no more nodes
-        long est;           // size estimate
-        LBDSpliterator(LinkedBlockingDeque<E> queue) {
-            this.queue = queue;
-            this.est = queue.size();
-        }
-
-        public long estimateSize() { return est; }
-
-        public Spliterator<E> trySplit() {
-            Node<E> h;
-            final LinkedBlockingDeque<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((h = current) != null || (h = q.first) != null) &&
-                h.next != null) {
-                Object[] a = new Object[n];
-                final ReentrantLock lock = q.lock;
-                int i = 0;
-                Node<E> p = current;
-                lock.lock();
-                try {
-                    if (p != null || (p = q.first) != null) {
-                        do {
-                            if ((a[i] = p.item) != null)
-                                ++i;
-                        } while ((p = p.next) != null && i < n);
-                    }
-                } finally {
-                    lock.unlock();
-                }
-                if ((current = p) == null) {
-                    est = 0L;
-                    exhausted = true;
-                }
-                else if ((est -= i) < 0L)
-                    est = 0L;
-                if (i > 0) {
-                    batch = i;
-                    return Spliterators.spliterator
-                        (a, 0, i, (Spliterator.ORDERED |
-                                   Spliterator.NONNULL |
-                                   Spliterator.CONCURRENT));
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
-            if (!exhausted) {
-                exhausted = true;
-                Node<E> p = current;
-                do {
-                    E e = null;
-                    lock.lock();
-                    try {
-                        if (p == null)
-                            p = q.first;
-                        while (p != null) {
-                            e = p.item;
-                            p = p.next;
-                            if (e != null)
-                                break;
-                        }
-                    } finally {
-                        lock.unlock();
-                    }
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
-            if (!exhausted) {
-                E e = null;
-                lock.lock();
-                try {
-                    if (current == null)
-                        current = q.first;
-                    while (current != null) {
-                        e = current.item;
-                        current = current.next;
-                        if (e != null)
-                            break;
-                    }
-                } finally {
-                    lock.unlock();
-                }
-                if (current == null)
-                    exhausted = true;
-                if (e != null) {
-                    action.accept(e);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
-        }
-    }
-
-    /**
-     * Returns a {@link Spliterator} over the elements in this deque.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this deque
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new LBDSpliterator<E>(this);
-    }
-
     /**
      * 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 capacity (int), followed by elements (each an
      * {@code Object}) in the proper order, followed by a null
      */
@@ -1262,10 +1147,6 @@
 
     /**
      * 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 {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index 86ed04a..0719828 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -6,16 +6,13 @@
 
 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;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -46,7 +43,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class LinkedBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
@@ -88,7 +85,7 @@
      */
 
     /**
-     * Linked list node class.
+     * Linked list node class
      */
     static class Node<E> {
         E item;
@@ -351,7 +348,7 @@
         putLock.lockInterruptibly();
         try {
             while (count.get() == capacity) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
@@ -433,7 +430,7 @@
         takeLock.lockInterruptibly();
         try {
             while (count.get() == 0) {
-                if (nanos <= 0L)
+                if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
@@ -478,7 +475,11 @@
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lock();
         try {
-            return (count.get() > 0) ? head.next.item : null;
+            Node<E> first = head.next;
+            if (first == null)
+                return null;
+            else
+                return first.item;
         } finally {
             takeLock.unlock();
         }
@@ -597,7 +598,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()}.
@@ -632,7 +633,25 @@
     }
 
     public String toString() {
-        return Helpers.collectionToString(this);
+        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();
+        }
     }
 
     /**
@@ -715,8 +734,12 @@
      * Returns an iterator over the elements in this queue in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this queue in proper sequence
      */
@@ -750,26 +773,34 @@
             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;
-                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;
-                    }
-                }
+                current = nextNode(current);
+                currentElement = (current == null) ? null : current.item;
+                return x;
             } finally {
                 fullyUnlock();
             }
@@ -796,146 +827,9 @@
         }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LBQSpliterator<E> implements Spliterator<E> {
-        static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedBlockingQueue<E> queue;
-        Node<E> current;    // current node; null until initialized
-        int batch;          // batch size for splits
-        boolean exhausted;  // true when no more nodes
-        long est;           // size estimate
-        LBQSpliterator(LinkedBlockingQueue<E> queue) {
-            this.queue = queue;
-            this.est = queue.size();
-        }
-
-        public long estimateSize() { return est; }
-
-        public Spliterator<E> trySplit() {
-            Node<E> h;
-            final LinkedBlockingQueue<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((h = current) != null || (h = q.head.next) != null) &&
-                h.next != null) {
-                Object[] a = new Object[n];
-                int i = 0;
-                Node<E> p = current;
-                q.fullyLock();
-                try {
-                    if (p != null || (p = q.head.next) != null) {
-                        do {
-                            if ((a[i] = p.item) != null)
-                                ++i;
-                        } while ((p = p.next) != null && i < n);
-                    }
-                } finally {
-                    q.fullyUnlock();
-                }
-                if ((current = p) == null) {
-                    est = 0L;
-                    exhausted = true;
-                }
-                else if ((est -= i) < 0L)
-                    est = 0L;
-                if (i > 0) {
-                    batch = i;
-                    return Spliterators.spliterator
-                        (a, 0, i, (Spliterator.ORDERED |
-                                   Spliterator.NONNULL |
-                                   Spliterator.CONCURRENT));
-                }
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingQueue<E> q = this.queue;
-            if (!exhausted) {
-                exhausted = true;
-                Node<E> p = current;
-                do {
-                    E e = null;
-                    q.fullyLock();
-                    try {
-                        if (p == null)
-                            p = q.head.next;
-                        while (p != null) {
-                            e = p.item;
-                            p = p.next;
-                            if (e != null)
-                                break;
-                        }
-                    } finally {
-                        q.fullyUnlock();
-                    }
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingQueue<E> q = this.queue;
-            if (!exhausted) {
-                E e = null;
-                q.fullyLock();
-                try {
-                    if (current == null)
-                        current = q.head.next;
-                    while (current != null) {
-                        e = current.item;
-                        current = current.next;
-                        if (e != null)
-                            break;
-                    }
-                } finally {
-                    q.fullyUnlock();
-                }
-                if (current == null)
-                    exhausted = true;
-                if (e != null) {
-                    action.accept(e);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
-        }
-    }
-
-    /**
-     * Returns a {@link Spliterator} over the elements in this queue.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this queue
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new LBQSpliterator<E>(this);
-    }
-
     /**
      * Saves this queue to a stream (that is, serializes it).
      *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData The capacity is emitted (int), followed by all of
      * its elements (each an {@code Object}) in the proper order,
      * followed by a null
@@ -961,10 +855,6 @@
 
     /**
      * Reconstitutes this queue 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 {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
index 185ebfd..db48420 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
@@ -7,15 +7,11 @@
 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.Spliterator;
-import java.util.Spliterators;
 import java.util.concurrent.locks.LockSupport;
-import java.util.function.Consumer;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -54,7 +50,7 @@
  *
  * @since 1.7
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class LinkedTransferQueue<E> extends AbstractQueue<E>
     implements TransferQueue<E>, java.io.Serializable {
@@ -186,7 +182,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
@@ -427,12 +423,12 @@
 
         // CAS methods for fields
         final boolean casNext(Node cmp, Node val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
         }
 
         final boolean casItem(Object cmp, Object val) {
             // assert cmp == null || cmp.getClass() != Node.class;
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
         }
 
         /**
@@ -440,7 +436,7 @@
          * only be seen after publication via casNext.
          */
         Node(Object item, boolean isData) {
-            U.putObject(this, ITEM, item); // relaxed write
+            UNSAFE.putObject(this, itemOffset, item); // relaxed write
             this.isData = isData;
         }
 
@@ -449,7 +445,7 @@
          * only after CASing head field, so uses relaxed write.
          */
         final void forgetNext() {
-            U.putObject(this, NEXT, this);
+            UNSAFE.putObject(this, nextOffset, this);
         }
 
         /**
@@ -462,8 +458,8 @@
          * else we don't care).
          */
         final void forgetContents() {
-            U.putObject(this, ITEM, this);
-            U.putObject(this, WAITER, null);
+            UNSAFE.putObject(this, itemOffset, this);
+            UNSAFE.putObject(this, waiterOffset, null);
         }
 
         /**
@@ -509,19 +505,21 @@
         private static final long serialVersionUID = -3375979862319811754L;
 
         // Unsafe mechanics
-        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;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long itemOffset;
+        private static final long nextOffset;
+        private static final long waiterOffset;
         static {
             try {
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                WAITER = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waiter"));
-            } catch (ReflectiveOperationException e) {
+                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) {
                 throw new Error(e);
             }
         }
@@ -538,15 +536,15 @@
 
     // CAS methods for fields
     private boolean casTail(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
     }
 
     private boolean casHead(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
 
     private boolean casSweepVotes(int cmp, int val) {
-        return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
+        return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
     }
 
     /*
@@ -557,6 +555,12 @@
     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.
      *
@@ -593,8 +597,7 @@
                                 break;        // unless slack < 2
                         }
                         LockSupport.unpark(p.waiter);
-                        @SuppressWarnings("unchecked") E itemE = (E) item;
-                        return itemE;
+                        return LinkedTransferQueue.<E>cast(item);
                     }
                 }
                 Node n = p.next;
@@ -672,15 +675,15 @@
             if (item != e) {                  // matched
                 // assert item != s;
                 s.forgetContents();           // avoid garbage
-                @SuppressWarnings("unchecked") E itemE = (E) item;
-                return itemE;
+                return LinkedTransferQueue.<E>cast(item);
             }
-            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 ((w.isInterrupted() || (timed && nanos <= 0)) &&
+                    s.casItem(e, s)) {        // cancel
+                unsplice(pred, s);
+                return e;
             }
-            else if (spins < 0) {            // establish spins at/near front
+
+            if (spins < 0) {                  // establish spins at/near front
                 if ((spins = spinsFor(pred, s.isData)) > 0)
                     randomYields = ThreadLocalRandom.current();
             }
@@ -732,25 +735,32 @@
     }
 
     /**
-     * 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.
+     * Returns the first unmatched node of the given mode, or null if
+     * none.  Used by methods isEmpty, hasWaitingConsumer.
      */
-    final Node firstDataNode() {
-        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;
-            }
-            return null;
+    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;
+    }
+
+    /**
+     * 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;
     }
 
     /**
@@ -758,140 +768,23 @@
      * Used by methods size and getWaitingConsumerCount.
      */
     private int countOfMode(boolean data) {
-        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)
+        int count = 0;
+        for (Node p = head; p != null; ) {
+            if (!p.isMatched()) {
+                if (p.isData != data)
+                    return 0;
+                if (++count == Integer.MAX_VALUE) // saturated
                     break;
-                if (p == (p = p.next))
-                    continue restartFromHead;
             }
-
-            if (size == 0)
-                return "[]";
-
-            return Helpers.toString(a, size, charLength);
+            Node n = p.next;
+            if (n != p)
+                p = n;
+            else {
+                count = 0;
+                p = head;
+            }
         }
-    }
-
-    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;
-            }
-            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.
-     *
-     * <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);
+        return count;
     }
 
     final class Itr implements Iterator<E> {
@@ -940,8 +833,7 @@
                 Object item = s.item;
                 if (s.isData) {
                     if (item != null && item != s) {
-                        @SuppressWarnings("unchecked") E itemE = (E) item;
-                        nextItem = itemE;
+                        nextItem = LinkedTransferQueue.<E>cast(item);
                         nextNode = s;
                         return;
                     }
@@ -988,111 +880,6 @@
         }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    final class LTQSpliterator<E> implements Spliterator<E> {
-        static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        Node current;       // current node; null until initialized
-        int batch;          // batch size for splits
-        boolean exhausted;  // true when no more nodes
-        LTQSpliterator() {}
-
-        public Spliterator<E> trySplit() {
-            Node p;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((p = current) != null || (p = firstDataNode()) != null) &&
-                p.next != null) {
-                Object[] a = new Object[n];
-                int i = 0;
-                do {
-                    Object e = p.item;
-                    if (e != p && (a[i] = e) != null)
-                        ++i;
-                    if (p == (p = p.next))
-                        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));
-                }
-            }
-            return null;
-        }
-
-        @SuppressWarnings("unchecked")
-        public void forEachRemaining(Consumer<? super E> action) {
-            Node p;
-            if (action == null) throw new NullPointerException();
-            if (!exhausted &&
-                ((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 = firstDataNode();
-                } while (p != null && p.isData);
-            }
-        }
-
-        @SuppressWarnings("unchecked")
-        public boolean tryAdvance(Consumer<? super E> action) {
-            Node p;
-            if (action == null) throw new NullPointerException();
-            if (!exhausted &&
-                ((p = current) != null || (p = firstDataNode()) != null)) {
-                Object e;
-                do {
-                    if ((e = p.item) == p)
-                        e = null;
-                    if (p == (p = p.next))
-                        p = firstDataNode();
-                } while (e == null && p != null && p.isData);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (e != null) {
-                    action.accept((E)e);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public long estimateSize() { return Long.MAX_VALUE; }
-
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
-        }
-    }
-
-    /**
-     * Returns a {@link Spliterator} over the elements in this queue.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
-     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} implements {@code trySplit} to permit limited
-     * parallelism.
-     *
-     * @return a {@code Spliterator} over the elements in this queue
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new LTQSpliterator<E>();
-    }
-
     /* -------------- Removal methods -------------- */
 
     /**
@@ -1104,7 +891,7 @@
      * @param s the node to be unspliced
      */
     final void unsplice(Node pred, Node s) {
-        s.waiter = null; // disable signals
+        s.forgetContents(); // forget unneeded fields
         /*
          * See above for rationale. Briefly: if pred still points to
          * s, try to unlink s.  If s cannot be unlinked, because it is
@@ -1372,8 +1159,12 @@
      * Returns an iterator over the elements in this queue in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this queue in proper sequence
      */
@@ -1382,22 +1173,7 @@
     }
 
     public E peek() {
-        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;
-        }
+        return firstDataItem();
     }
 
     /**
@@ -1406,24 +1182,15 @@
      * @return {@code true} if this queue contains no elements
      */
     public boolean isEmpty() {
-        return firstDataNode() == null;
+        for (Node p = head; p != null; p = succ(p)) {
+            if (!p.isMatched())
+                return !p.isData;
+        }
+        return true;
     }
 
     public boolean hasWaitingConsumer() {
-        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;
-        }
+        return firstOfMode(false) != null;
     }
 
     /**
@@ -1470,16 +1237,15 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        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;
+        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;
             }
+            else if (item == null)
+                break;
         }
         return false;
     }
@@ -1499,8 +1265,6 @@
     /**
      * Saves this queue to a stream (that is, serializes it).
      *
-     * @param s the stream
-     * @throws java.io.IOException if an I/O error occurs
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
      */
@@ -1515,10 +1279,6 @@
 
     /**
      * Reconstitutes this queue 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 {
@@ -1535,19 +1295,21 @@
 
     // Unsafe mechanics
 
-    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;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long headOffset;
+    private static final long tailOffset;
+    private static final long sweepVotesOffset;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("tail"));
-            SWEEPVOTES = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
-        } catch (ReflectiveOperationException e) {
+            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) {
             throw new Error(e);
         }
 
diff --git a/luni/src/main/java/java/util/concurrent/Phaser.java b/luni/src/main/java/java/util/concurrent/Phaser.java
index 9b2a7a1..c5faf16 100644
--- a/luni/src/main/java/java/util/concurrent/Phaser.java
+++ b/luni/src/main/java/java/util/concurrent/Phaser.java
@@ -42,7 +42,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
@@ -55,7 +55,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},
@@ -66,10 +66,9 @@
  *       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}.
- *       Progress is ensured if the pool's parallelismLevel can
- *       accommodate the maximum number of simultaneously blocked
- *       parties.
+ *       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.
  *
  * </ul>
  *
@@ -125,7 +124,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
@@ -146,7 +145,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) {
@@ -170,7 +169,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())
@@ -180,7 +179,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) {
@@ -200,7 +199,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) {
@@ -301,7 +300,7 @@
     }
 
     /**
-     * The parent of this phaser, or null if none.
+     * The parent of this phaser, or null if none
      */
     private final Phaser parent;
 
@@ -359,7 +358,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s-=adjust)) {
+            if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adjust)) {
                 if (unarrived == 1) {
                     long n = s & PARTIES_MASK;  // base of next state
                     int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -372,12 +371,13 @@
                             n |= nextUnarrived;
                         int nextPhase = (phase + 1) & MAX_PHASE;
                         n |= (long)nextPhase << PHASE_SHIFT;
-                        U.compareAndSwapLong(this, STATE, s, n);
+                        UNSAFE.compareAndSwapLong(this, stateOffset, s, n);
                         releaseWaiters(phase);
                     }
                     else if (nextUnarrived == 0) { // propagate deregistration
                         phase = parent.doArrive(ONE_DEREGISTER);
-                        U.compareAndSwapLong(this, STATE, s, s | EMPTY);
+                        UNSAFE.compareAndSwapLong(this, stateOffset,
+                                                  s, s | EMPTY);
                     }
                     else
                         phase = parent.doArrive(ONE_ARRIVAL);
@@ -388,7 +388,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.
@@ -412,13 +412,14 @@
                 if (parent == null || reconcileState() == s) {
                     if (unarrived == 0)             // wait out advance
                         root.internalAwaitAdvance(phase, null);
-                    else if (U.compareAndSwapLong(this, STATE, s, s + adjust))
+                    else if (UNSAFE.compareAndSwapLong(this, stateOffset,
+                                                       s, s + adjust))
                         break;
                 }
             }
             else if (parent == null) {              // 1st root registration
                 long next = ((long)phase << PHASE_SHIFT) | adjust;
-                if (U.compareAndSwapLong(this, STATE, s, next))
+                if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next))
                     break;
             }
             else {
@@ -430,8 +431,8 @@
                         // finish registration whenever parent registration
                         // succeeded, even when racing with termination,
                         // since these are part of the same "transaction".
-                        while (!U.compareAndSwapLong
-                               (this, STATE, s,
+                        while (!UNSAFE.compareAndSwapLong
+                               (this, stateOffset, s,
                                 ((long)phase << PHASE_SHIFT) | adjust)) {
                             s = state;
                             phase = (int)(root.state >>> PHASE_SHIFT);
@@ -462,8 +463,8 @@
             // CAS to root phase with current parties, tripping unarrived
             while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
                    (int)(s >>> PHASE_SHIFT) &&
-                   !U.compareAndSwapLong
-                   (this, STATE, s,
+                   !UNSAFE.compareAndSwapLong
+                   (this, stateOffset, s,
                     s = (((long)phase << PHASE_SHIFT) |
                          ((phase < 0) ? (s & COUNTS_MASK) :
                           (((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -652,7 +653,8 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s -= ONE_ARRIVAL)) {
+            if (UNSAFE.compareAndSwapLong(this, stateOffset, s,
+                                          s -= ONE_ARRIVAL)) {
                 if (unarrived > 1)
                     return root.internalAwaitAdvance(phase, null);
                 if (root != this)
@@ -667,7 +669,7 @@
                     n |= nextUnarrived;
                 int nextPhase = (phase + 1) & MAX_PHASE;
                 n |= (long)nextPhase << PHASE_SHIFT;
-                if (!U.compareAndSwapLong(this, STATE, s, n))
+                if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n))
                     return (int)(state >>> PHASE_SHIFT); // terminated
                 releaseWaiters(phase);
                 return nextPhase;
@@ -783,7 +785,8 @@
         final Phaser root = this.root;
         long s;
         while ((s = root.state) >= 0) {
-            if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
+            if (UNSAFE.compareAndSwapLong(root, stateOffset,
+                                          s, s | TERMINATION_BIT)) {
                 // signal all threads
                 releaseWaiters(0); // Waiters on evenQ
                 releaseWaiters(1); // Waiters on oddQ
@@ -922,7 +925,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() +
@@ -1031,7 +1034,7 @@
             else {
                 try {
                     ForkJoinPool.managedBlock(node);
-                } catch (InterruptedException cantHappen) {
+                } catch (InterruptedException ie) {
                     node.wasInterrupted = true;
                 }
             }
@@ -1050,7 +1053,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;
@@ -1087,34 +1090,40 @@
                 thread = null;
                 return true;
             }
-            if (timed &&
-                (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
-                thread = null;
-                return true;
+            if (timed) {
+                if (nanos > 0L) {
+                    nanos = deadline - System.nanoTime();
+                }
+                if (nanos <= 0L) {
+                    thread = null;
+                    return true;
+                }
             }
             return false;
         }
 
         public boolean block() {
-            while (!isReleasable()) {
-                if (timed)
-                    LockSupport.parkNanos(this, nanos);
-                else
-                    LockSupport.park(this);
-            }
-            return true;
+            if (isReleasable())
+                return true;
+            else if (!timed)
+                LockSupport.park(this);
+            else if (nanos > 0L)
+                LockSupport.parkNanos(this, nanos);
+            return isReleasable();
         }
     }
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long stateOffset;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (Phaser.class.getDeclaredField("state"));
-        } catch (ReflectiveOperationException e) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = Phaser.class;
+            stateOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("state"));
+        } catch (Exception e) {
             throw new Error(e);
         }
 
diff --git a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 2044406..40b3510 100644
--- a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -6,19 +6,9 @@
 
 package java.util.concurrent;
 
-import java.util.AbstractQueue;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.PriorityQueue;
-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;
+import java.util.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -53,7 +43,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);
@@ -74,7 +64,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 @SuppressWarnings("unchecked")
 public class PriorityBlockingQueue<E> extends AbstractQueue<E>
@@ -132,12 +122,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;
 
@@ -260,7 +250,8 @@
         lock.unlock(); // must release and then re-acquire main lock
         Object[] newArray = null;
         if (allocationSpinLock == 0 &&
-            U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
+            UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
+                                     0, 1)) {
             try {
                 int newCap = oldCap + ((oldCap < 64) ?
                                        (oldCap + 2) : // grow faster if small
@@ -642,7 +633,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;
@@ -678,8 +669,48 @@
         }
     }
 
+    /**
+     * 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() {
-        return Helpers.collectionToString(this);
+        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();
+        }
     }
 
     /**
@@ -738,29 +769,6 @@
     }
 
     /**
-     * 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.
@@ -782,7 +790,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()}.
@@ -817,8 +825,12 @@
      * Returns an iterator over the elements in this queue. The
      * iterator does not return the elements in any particular order.
      *
-     * <p>The returned iterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
      * @return an iterator over the elements in this queue
      */
@@ -864,9 +876,6 @@
      * For compatibility with previous version of this class, elements
      * are first copied to a java.util.PriorityQueue, which is then
      * serialized.
-     *
-     * @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 {
@@ -884,10 +893,6 @@
 
     /**
      * Reconstitutes this queue 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 {
@@ -901,93 +906,16 @@
         }
     }
 
-    // Similar to Collections.ArraySnapshotSpliterator but avoids
-    // commitment to toArray until needed
-    static final class PBQSpliterator<E> implements Spliterator<E> {
-        final PriorityBlockingQueue<E> queue;
-        Object[] array;
-        int index;
-        int fence;
-
-        PBQSpliterator(PriorityBlockingQueue<E> queue, Object[] array,
-                       int index, int fence) {
-            this.queue = queue;
-            this.array = array;
-            this.index = index;
-            this.fence = fence;
-        }
-
-        final int getFence() {
-            int hi;
-            if ((hi = fence) < 0)
-                hi = fence = (array = queue.toArray()).length;
-            return hi;
-        }
-
-        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);
-        }
-
-        @SuppressWarnings("unchecked")
-        public void forEachRemaining(Consumer<? super E> action) {
-            Object[] a; int i, hi; // hoist accesses and checks from loop
-            if (action == null)
-                throw new NullPointerException();
-            if ((a = array) == null)
-                fence = (a = queue.toArray()).length;
-            if ((hi = fence) <= a.length &&
-                (i = index) >= 0 && i < (index = hi)) {
-                do { action.accept((E)a[i]); } while (++i < hi);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null)
-                throw new NullPointerException();
-            if (getFence() > index && index >= 0) {
-                @SuppressWarnings("unchecked") E e = (E) array[index++];
-                action.accept(e);
-                return true;
-            }
-            return false;
-        }
-
-        public long estimateSize() { return (long)(getFence() - index); }
-
-        public int characteristics() {
-            return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED;
-        }
-    }
-
-    /**
-     * Returns a {@link Spliterator} over the elements in this queue.
-     *
-     * <p>The returned spliterator is
-     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
-     * {@link Spliterator#NONNULL}.
-     *
-     * @implNote
-     * The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}.
-     *
-     * @return a {@code Spliterator} over the elements in this queue
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new PBQSpliterator<E>(this, null, 0, -1);
-    }
-
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long ALLOCATIONSPINLOCK;
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long allocationSpinLockOffset;
     static {
         try {
-            ALLOCATIONSPINLOCK = U.objectFieldOffset
-                (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
-        } catch (ReflectiveOperationException e) {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = PriorityBlockingQueue.class;
+            allocationSpinLockOffset = UNSAFE.objectFieldOffset
+                (k.getDeclaredField("allocationSpinLock"));
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveAction.java b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
index 8631a89..e3a6340 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveAction.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
@@ -16,7 +16,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) {
@@ -50,7 +50,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) {
@@ -81,7 +81,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);
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveTask.java b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
index 5cba1da..d201bd6 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveTask.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
@@ -11,11 +11,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; }
- *   protected Integer compute() {
+ *   Integer compute() {
  *     if (n <= 1)
  *       return n;
  *     Fibonacci f1 = new Fibonacci(n - 1);
diff --git a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
index 604f180..7125233 100644
--- a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
+++ b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
@@ -19,11 +19,11 @@
 public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
 
     /**
-     * Returns {@code true} if this task is periodic. A periodic task may
+     * Returns true if this is a periodic task. A periodic task may
      * re-run according to some schedule. A non-periodic task can be
      * run only once.
      *
-     * @return {@code true} if this task is periodic
+     * @return true if this task is periodic
      */
     boolean isPeriodic();
 }
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index eae47b3..c07a5b9 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -41,7 +41,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 =
@@ -100,37 +100,23 @@
     /**
      * 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.
-     *
-     * <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.
+     * 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.
      *
      * @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 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.
+     *         the task, and whose {@code get()} method will throw an
+     *         exception upon cancellation
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      * @throws NullPointerException if command is null
@@ -145,21 +131,10 @@
      * 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.
-     *
-     * <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}.
+     * 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.
      *
      * @param command the task to execute
      * @param initialDelay the time to delay first execution
@@ -167,10 +142,8 @@
      * 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 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.
+     *         the task, and whose {@code get()} method will throw an
+     *         exception upon cancellation
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      * @throws NullPointerException if command is null
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index f9a2000..821342d 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -6,18 +6,12 @@
 
 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 static java.util.concurrent.TimeUnit.MILLISECONDS;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.*;
 
 // BEGIN android-note
 // omit class-level docs on setRemoveOnCancelPolicy()
@@ -38,17 +32,17 @@
  * 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.
+ * 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.
  *
  * <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>
+ * {@link #scheduleAtFixedRate} or
+ * {@link #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
@@ -78,7 +72,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> { ... }
@@ -105,10 +99,11 @@
     /*
      * This class specializes ThreadPoolExecutor implementation by
      *
-     * 1. Using a custom task type ScheduledFutureTask, even for tasks
-     *    that don't require scheduling because they are submitted
-     *    using ExecutorService rather than ScheduledExecutorService
-     *    methods, which are treated as tasks with a delay of zero.
+     * 1. Using a custom task type, ScheduledFutureTask for
+     *    tasks, even those that don't require scheduling (i.e.,
+     *    those submitted using ExecutorService execute, not
+     *    ScheduledExecutorService methods) which are treated as
+     *    delayed tasks with a delay of zero.
      *
      * 2. Using a custom queue (DelayedWorkQueue), a variant of
      *    unbounded DelayQueue. The lack of capacity constraint and
@@ -141,7 +136,7 @@
     /**
      * True if ScheduledFutureTask.cancel should remove from queue.
      */
-    volatile boolean removeOnCancel;
+    private volatile boolean removeOnCancel = false;
 
     /**
      * Sequence number to break scheduling ties, and in turn to
@@ -149,17 +144,24 @@
      */
     private static final AtomicLong sequencer = new AtomicLong();
 
+    /**
+     * Returns current nanosecond time.
+     */
+    final long now() {
+        return System.nanoTime();
+    }
+
     private class ScheduledFutureTask<V>
             extends FutureTask<V> implements RunnableScheduledFuture<V> {
 
         /** Sequence number to break ties FIFO */
         private final long sequenceNumber;
 
-        /** The nanoTime-based time when the task is enabled to execute. */
-        private volatile long time;
+        /** The time the task is enabled to execute in nanoTime units */
+        private long time;
 
         /**
-         * Period for repeating tasks, in nanoseconds.
+         * 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.
@@ -177,12 +179,11 @@
         /**
          * Creates a one-shot action with given nanoTime-based trigger time.
          */
-        ScheduledFutureTask(Runnable r, V result, long triggerTime,
-                            long sequenceNumber) {
+        ScheduledFutureTask(Runnable r, V result, long triggerTime) {
             super(r, result);
             this.time = triggerTime;
             this.period = 0;
-            this.sequenceNumber = sequenceNumber;
+            this.sequenceNumber = sequencer.getAndIncrement();
         }
 
         /**
@@ -190,26 +191,25 @@
          * trigger time and period.
          */
         ScheduledFutureTask(Runnable r, V result, long triggerTime,
-                            long period, long sequenceNumber) {
+                            long period) {
             super(r, result);
             this.time = triggerTime;
             this.period = period;
-            this.sequenceNumber = sequenceNumber;
+            this.sequenceNumber = sequencer.getAndIncrement();
         }
 
         /**
          * Creates a one-shot action with given nanoTime-based trigger time.
          */
-        ScheduledFutureTask(Callable<V> callable, long triggerTime,
-                            long sequenceNumber) {
+        ScheduledFutureTask(Callable<V> callable, long triggerTime) {
             super(callable);
             this.time = triggerTime;
             this.period = 0;
-            this.sequenceNumber = sequenceNumber;
+            this.sequenceNumber = sequencer.getAndIncrement();
         }
 
         public long getDelay(TimeUnit unit) {
-            return unit.convert(time - System.nanoTime(), NANOSECONDS);
+            return unit.convert(time - now(), NANOSECONDS);
         }
 
         public int compareTo(Delayed other) {
@@ -252,9 +252,6 @@
         }
 
         public boolean cancel(boolean mayInterruptIfRunning) {
-            // The racy read of heapIndex below is benign:
-            // if heapIndex < 0, then OOTA guarantees that we have surely
-            // been removed; else we recheck under lock in remove()
             boolean cancelled = super.cancel(mayInterruptIfRunning);
             if (cancelled && removeOnCancel && heapIndex >= 0)
                 remove(this);
@@ -269,8 +266,8 @@
             if (!canRunInCurrentRunState(periodic))
                 cancel(false);
             else if (!periodic)
-                super.run();
-            else if (super.runAndReset()) {
+                ScheduledFutureTask.super.run();
+            else if (ScheduledFutureTask.super.runAndReset()) {
                 setNextRunTime();
                 reExecutePeriodic(outerTask);
             }
@@ -496,7 +493,7 @@
      * Returns the nanoTime-based trigger time of a delayed action.
      */
     long triggerTime(long delay) {
-        return System.nanoTime() +
+        return now() +
             ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
     }
 
@@ -528,8 +525,7 @@
             throw new NullPointerException();
         RunnableScheduledFuture<Void> t = decorateTask(command,
             new ScheduledFutureTask<Void>(command, null,
-                                          triggerTime(delay, unit),
-                                          sequencer.getAndIncrement()));
+                                          triggerTime(delay, unit)));
         delayedExecute(t);
         return t;
     }
@@ -545,8 +541,7 @@
             throw new NullPointerException();
         RunnableScheduledFuture<V> t = decorateTask(callable,
             new ScheduledFutureTask<V>(callable,
-                                       triggerTime(delay, unit),
-                                       sequencer.getAndIncrement()));
+                                       triggerTime(delay, unit)));
         delayedExecute(t);
         return t;
     }
@@ -562,14 +557,13 @@
                                                   TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        if (period <= 0L)
+        if (period <= 0)
             throw new IllegalArgumentException();
         ScheduledFutureTask<Void> sft =
             new ScheduledFutureTask<Void>(command,
                                           null,
                                           triggerTime(initialDelay, unit),
-                                          unit.toNanos(period),
-                                          sequencer.getAndIncrement());
+                                          unit.toNanos(period));
         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
         sft.outerTask = t;
         delayedExecute(t);
@@ -587,14 +581,13 @@
                                                      TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        if (delay <= 0L)
+        if (delay <= 0)
             throw new IllegalArgumentException();
         ScheduledFutureTask<Void> sft =
             new ScheduledFutureTask<Void>(command,
                                           null,
                                           triggerTime(initialDelay, unit),
-                                          -unit.toNanos(delay),
-                                          sequencer.getAndIncrement());
+                                          unit.toNanos(-delay));
         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
         sft.outerTask = t;
         delayedExecute(t);
@@ -766,8 +759,7 @@
     /**
      * Attempts to stop all actively executing tasks, halts the
      * processing of waiting tasks, and returns a list of the tasks
-     * that were awaiting execution. These tasks are drained (removed)
-     * from the task queue upon return from this method.
+     * that were awaiting execution.
      *
      * <p>This method does not wait for actively executing tasks to
      * terminate.  Use {@link #awaitTermination awaitTermination} to
@@ -775,7 +767,7 @@
      *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  This implementation
-     * interrupts tasks via {@link Thread#interrupt}; any task that
+     * cancels tasks via {@link Thread#interrupt}, so any task that
      * fails to respond to interrupts may never terminate.
      *
      * @return list of tasks that never commenced execution.
@@ -783,8 +775,8 @@
      *         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}.
+     *         {@link #execute}, the element will be a zero-delay {@code
+     *         ScheduledFuture}.
      */
     // android-note: Removed "throws SecurityException" doc.
     public List<Runnable> shutdownNow() {
@@ -792,16 +784,12 @@
     }
 
     /**
-     * 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}.
+     * Returns the task queue used by this executor.
+     * 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}.
+     * For tasks submitted using {@link #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.
@@ -1073,9 +1061,10 @@
             lock.lock();
             try {
                 RunnableScheduledFuture<?> first = queue[0];
-                return (first == null || first.getDelay(NANOSECONDS) > 0)
-                    ? null
-                    : finishPoll(first);
+                if (first == null || first.getDelay(NANOSECONDS) > 0)
+                    return null;
+                else
+                    return finishPoll(first);
             } finally {
                 lock.unlock();
             }
@@ -1091,7 +1080,7 @@
                         available.await();
                     else {
                         long delay = first.getDelay(NANOSECONDS);
-                        if (delay <= 0L)
+                        if (delay <= 0)
                             return finishPoll(first);
                         first = null; // don't retain ref while waiting
                         if (leader != null)
@@ -1124,15 +1113,15 @@
                 for (;;) {
                     RunnableScheduledFuture<?> first = queue[0];
                     if (first == null) {
-                        if (nanos <= 0L)
+                        if (nanos <= 0)
                             return null;
                         else
                             nanos = available.awaitNanos(nanos);
                     } else {
                         long delay = first.getDelay(NANOSECONDS);
-                        if (delay <= 0L)
+                        if (delay <= 0)
                             return finishPoll(first);
-                        if (nanos <= 0L)
+                        if (nanos <= 0)
                             return null;
                         first = null; // don't retain ref while waiting
                         if (nanos < delay || leader != null)
@@ -1264,8 +1253,8 @@
          */
         private class Itr implements Iterator<Runnable> {
             final RunnableScheduledFuture<?>[] array;
-            int cursor;        // index of next element to return; initially 0
-            int lastRet = -1;  // index of last element returned; -1 if no such
+            int cursor = 0;     // index of next element to return
+            int lastRet = -1;   // index of last element, or -1 if no such
 
             Itr(RunnableScheduledFuture<?>[] array) {
                 this.array = array;
diff --git a/luni/src/main/java/java/util/concurrent/Semaphore.java b/luni/src/main/java/java/util/concurrent/Semaphore.java
index 856b02b..b4b7edd 100644
--- a/luni/src/main/java/java/util/concurrent/Semaphore.java
+++ b/luni/src/main/java/java/util/concurrent/Semaphore.java
@@ -20,7 +20,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);
@@ -113,13 +113,8 @@
  *
  * <p>This class also provides convenience methods to {@link
  * #acquire(int) acquire} and {@link #release(int) release} multiple
- * 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.
+ * permits at a time.  Beware of the increased risk of indefinite
+ * postponement when these methods are used without fairness set true.
  *
  * <p>Memory consistency effects: Actions in a thread prior to calling
  * a "release" method such as {@code release()}
@@ -410,16 +405,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. 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:
+     * by the given amount.
      *
      * <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 and the current thread is next to be assigned
+     * methods for this semaphore, 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.
@@ -452,14 +445,12 @@
      *
      * <p>Acquires the given number of permits, if they are available,
      * and returns immediately, reducing the number of available permits
-     * 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:
+     * by the given amount.
      *
      * <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 and the current thread is next to be assigned
+     * methods for this semaphore, 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}
@@ -521,7 +512,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 and the current thread is next to be assigned
+     * methods for this semaphore, 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
@@ -568,7 +559,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 thread
+     * If any threads are trying to acquire permits, then one
      * 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;
@@ -652,7 +643,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
+     * structures.  This method is designed for use in monitoring of the
      * system state, not for synchronization control.
      *
      * @return the estimated number of threads waiting for this lock
diff --git a/luni/src/main/java/java/util/concurrent/SubmissionPublisher.java b/luni/src/main/java/java/util/concurrent/SubmissionPublisher.java
deleted file mode 100644
index 53817e5..0000000
--- a/luni/src/main/java/java/util/concurrent/SubmissionPublisher.java
+++ /dev/null
@@ -1,1603 +0,0 @@
-/*
- * 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 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")
-    @jdk.internal.vm.annotation.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;
-        }
-    }
-}
diff --git a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
index a46f672..69452af 100644
--- a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -7,14 +7,9 @@
 
 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.*;
 
 // BEGIN android-note
 // removed link to collections framework docs
@@ -54,7 +49,7 @@
  *
  * @since 1.5
  * @author Doug Lea and Bill Scherer and Michael Scott
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class SynchronousQueue<E> extends AbstractQueue<E>
     implements BlockingQueue<E>, java.io.Serializable {
@@ -157,6 +152,9 @@
         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
@@ -164,21 +162,20 @@
      * seems not to vary with number of CPUs (beyond 2) so is just
      * a constant.
      */
-    static final int MAX_TIMED_SPINS =
-        (Runtime.getRuntime().availableProcessors() < 2) ? 0 : 32;
+    static final int maxTimedSpins = (NCPUS < 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 MAX_UNTIMED_SPINS = MAX_TIMED_SPINS * 16;
+    static final int maxUntimedSpins = maxTimedSpins * 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 SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
+    static final long spinForTimeoutThreshold = 1000L;
 
     /** Dual stack */
     static final class TransferStack<E> extends Transferer<E> {
@@ -218,7 +215,7 @@
 
             boolean casNext(SNode cmp, SNode val) {
                 return cmp == next &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
             }
 
             /**
@@ -231,7 +228,7 @@
              */
             boolean tryMatch(SNode s) {
                 if (match == null &&
-                    U.compareAndSwapObject(this, MATCH, null, s)) {
+                    UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
                     Thread w = waiter;
                     if (w != null) {    // waiters need at most one unpark
                         waiter = null;
@@ -246,7 +243,7 @@
              * Tries to cancel a wait by matching node to itself.
              */
             void tryCancel() {
-                U.compareAndSwapObject(this, MATCH, null, this);
+                UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
             }
 
             boolean isCancelled() {
@@ -254,17 +251,19 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-            private static final long MATCH;
-            private static final long NEXT;
+            private static final sun.misc.Unsafe UNSAFE;
+            private static final long matchOffset;
+            private static final long nextOffset;
 
             static {
                 try {
-                    MATCH = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("match"));
-                    NEXT = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("next"));
-                } catch (ReflectiveOperationException e) {
+                    UNSAFE = sun.misc.Unsafe.getUnsafe();
+                    Class<?> k = SNode.class;
+                    matchOffset = UNSAFE.objectFieldOffset
+                        (k.getDeclaredField("match"));
+                    nextOffset = UNSAFE.objectFieldOffset
+                        (k.getDeclaredField("next"));
+                } catch (Exception e) {
                     throw new Error(e);
                 }
             }
@@ -275,7 +274,7 @@
 
         boolean casHead(SNode h, SNode nh) {
             return h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh);
+                UNSAFE.compareAndSwapObject(this, headOffset, h, nh);
         }
 
         /**
@@ -324,7 +323,7 @@
             for (;;) {
                 SNode h = head;
                 if (h == null || h.mode == mode) {  // empty or same-mode
-                    if (timed && nanos <= 0L) {     // can't wait
+                    if (timed && nanos <= 0) {      // can't wait
                         if (h != null && h.isCancelled())
                             casHead(h, h.next);     // pop cancelled node
                         else
@@ -406,9 +405,8 @@
              */
             final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
-            int spins = shouldSpin(s)
-                ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
-                : 0;
+            int spins = (shouldSpin(s) ?
+                         (timed ? maxTimedSpins : maxUntimedSpins) : 0);
             for (;;) {
                 if (w.isInterrupted())
                     s.tryCancel();
@@ -423,12 +421,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 > SPIN_FOR_TIMEOUT_THRESHOLD)
+                else if (nanos > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanos);
             }
         }
@@ -480,13 +478,15 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long headOffset;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferStack.class.getDeclaredField("head"));
-            } catch (ReflectiveOperationException e) {
+                UNSAFE = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = TransferStack.class;
+                headOffset = UNSAFE.objectFieldOffset
+                    (k.getDeclaredField("head"));
+            } catch (Exception e) {
                 throw new Error(e);
             }
         }
@@ -517,19 +517,19 @@
 
             boolean casNext(QNode cmp, QNode val) {
                 return next == cmp &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
             }
 
             boolean casItem(Object cmp, Object val) {
                 return item == cmp &&
-                    U.compareAndSwapObject(this, ITEM, cmp, val);
+                    UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
             }
 
             /**
              * Tries to cancel by CAS'ing ref to this as item.
              */
             void tryCancel(Object cmp) {
-                U.compareAndSwapObject(this, ITEM, cmp, this);
+                UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this);
             }
 
             boolean isCancelled() {
@@ -546,17 +546,19 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-            private static final long ITEM;
-            private static final long NEXT;
+            private static final sun.misc.Unsafe UNSAFE;
+            private static final long itemOffset;
+            private static final long nextOffset;
 
             static {
                 try {
-                    ITEM = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("item"));
-                    NEXT = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("next"));
-                } catch (ReflectiveOperationException e) {
+                    UNSAFE = sun.misc.Unsafe.getUnsafe();
+                    Class<?> k = QNode.class;
+                    itemOffset = UNSAFE.objectFieldOffset
+                        (k.getDeclaredField("item"));
+                    nextOffset = UNSAFE.objectFieldOffset
+                        (k.getDeclaredField("next"));
+                } catch (Exception e) {
                     throw new Error(e);
                 }
             }
@@ -585,7 +587,7 @@
          */
         void advanceHead(QNode h, QNode nh) {
             if (h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh))
+                UNSAFE.compareAndSwapObject(this, headOffset, h, nh))
                 h.next = h; // forget old next
         }
 
@@ -594,7 +596,7 @@
          */
         void advanceTail(QNode t, QNode nt) {
             if (tail == t)
-                U.compareAndSwapObject(this, TAIL, t, nt);
+                UNSAFE.compareAndSwapObject(this, tailOffset, t, nt);
         }
 
         /**
@@ -602,7 +604,7 @@
          */
         boolean casCleanMe(QNode cmp, QNode val) {
             return cleanMe == cmp &&
-                U.compareAndSwapObject(this, CLEANME, cmp, val);
+                UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
         }
 
         /**
@@ -652,7 +654,7 @@
                         advanceTail(t, tn);
                         continue;
                     }
-                    if (timed && nanos <= 0L)       // can't wait
+                    if (timed && nanos <= 0)        // can't wait
                         return null;
                     if (s == null)
                         s = new QNode(e, isData);
@@ -707,9 +709,8 @@
             /* Same idea as TransferStack.awaitFulfill */
             final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
-            int spins = (head.next == s)
-                ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
-                : 0;
+            int spins = ((head.next == s) ?
+                         (timed ? maxTimedSpins : maxUntimedSpins) : 0);
             for (;;) {
                 if (w.isInterrupted())
                     s.tryCancel(e);
@@ -729,7 +730,7 @@
                     s.waiter = w;
                 else if (!timed)
                     LockSupport.park(this);
-                else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
+                else if (nanos > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanos);
             }
         }
@@ -788,19 +789,21 @@
             }
         }
 
-        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;
+        private static final sun.misc.Unsafe UNSAFE;
+        private static final long headOffset;
+        private static final long tailOffset;
+        private static final long cleanMeOffset;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("head"));
-                TAIL = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("tail"));
-                CLEANME = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("cleanMe"));
-            } catch (ReflectiveOperationException e) {
+                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) {
                 throw new Error(e);
             }
         }
@@ -1031,19 +1034,19 @@
      *
      * @return an empty iterator
      */
+    @SuppressWarnings("unchecked")
     public Iterator<E> iterator() {
-        return Collections.emptyIterator();
+        return (Iterator<E>) EmptyIterator.EMPTY_ITERATOR;
     }
 
-    /**
-     * Returns an empty spliterator in which calls to
-     * {@link java.util.Spliterator#trySplit()} always return {@code null}.
-     *
-     * @return an empty spliterator
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return Spliterators.emptySpliterator();
+    // Replicated from a previous version of Collections
+    private static class EmptyIterator<E> implements Iterator<E> {
+        static final EmptyIterator<Object> EMPTY_ITERATOR
+            = new EmptyIterator<Object>();
+
+        public boolean hasNext() { return false; }
+        public E next() { throw new NoSuchElementException(); }
+        public void remove() { throw new IllegalStateException(); }
     }
 
     /**
@@ -1069,14 +1072,6 @@
     }
 
     /**
-     * Always returns {@code "[]"}.
-     * @return {@code "[]"}
-     */
-    public String toString() {
-        return "[]";
-    }
-
-    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -1136,8 +1131,6 @@
 
     /**
      * Saves this queue to a stream (that is, serializes it).
-     * @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 {
@@ -1157,10 +1150,6 @@
 
     /**
      * Reconstitutes this queue 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 {
@@ -1171,6 +1160,19 @@
             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
diff --git a/luni/src/main/java/java/util/concurrent/ThreadFactory.java b/luni/src/main/java/java/util/concurrent/ThreadFactory.java
index fdedea3..d1a4eb6 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadFactory.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadFactory.java
@@ -13,7 +13,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);
diff --git a/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java b/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
index 8c65bde..b007af2 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
@@ -6,19 +6,7 @@
 
 package java.util.concurrent;
 
-import java.io.ObjectStreamField;
 import java.util.Random;
-import java.util.Spliterator;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-// TODO(streams):
-// import java.util.stream.DoubleStream;
-// import java.util.stream.IntStream;
-// import java.util.stream.LongStream;
-// import java.util.stream.StreamSupport;
 
 /**
  * A random number generator isolated to the current thread.  Like the
@@ -41,98 +29,50 @@
  * <p>This class also provides additional commonly used bounded random
  * generation methods.
  *
- * <p>Instances of {@code ThreadLocalRandom} are not cryptographically
- * secure.  Consider instead using {@link java.security.SecureRandom}
- * in security-sensitive applications. Additionally,
- * default-constructed instances do not use a cryptographically random
- * seed unless the {@linkplain System#getProperty system property}
- * {@code java.util.secureRandomSeed} is set to {@code true}.
- *
  * @since 1.7
  * @author Doug Lea
  */
 public class ThreadLocalRandom extends Random {
-    /*
-     * This class implements the java.util.Random API (and subclasses
-     * Random) using a single static instance that accesses random
-     * number state held in class Thread (primarily, field
-     * threadLocalRandomSeed). In doing so, it also provides a home
-     * for managing package-private utilities that rely on exactly the
-     * same state as needed to maintain the ThreadLocalRandom
-     * instances. We leverage the need for an initialization flag
-     * field to also use it as a "probe" -- a self-adjusting thread
-     * hash used for contention avoidance, as well as a secondary
-     * simpler (xorShift) random seed that is conservatively used to
-     * avoid otherwise surprising users by hijacking the
-     * ThreadLocalRandom sequence.  The dual use is a marriage of
-     * convenience, but is a simple and efficient way of reducing
-     * application-level overhead and footprint of most concurrent
-     * programs.
-     *
-     * Even though this class subclasses java.util.Random, it uses the
-     * same basic algorithm as java.util.SplittableRandom.  (See its
-     * internal documentation for explanations, which are not repeated
-     * here.)  Because ThreadLocalRandoms are not splittable
-     * though, we use only a single 64bit gamma.
-     *
-     * Because this class is in a different package than class Thread,
-     * field access methods use Unsafe to bypass access control rules.
-     * To conform to the requirements of the Random superclass
-     * constructor, the common static ThreadLocalRandom maintains an
-     * "initialized" field for the sake of rejecting user calls to
-     * setSeed while still allowing a call from constructor.  Note
-     * that serialization is completely unnecessary because there is
-     * only a static singleton.  But we generate a serial form
-     * containing "rnd" and "initialized" fields to ensure
-     * compatibility across versions.
-     *
-     * Implementations of non-core methods are mostly the same as in
-     * SplittableRandom, that were in part derived from a previous
-     * version of this class.
-     *
-     * The nextLocalGaussian ThreadLocal supports the very rarely used
-     * nextGaussian method by providing a holder for the second of a
-     * pair of them. As is true for the base class version of this
-     * method, this time/space tradeoff is probably never worthwhile,
-     * but we provide identical statistical properties.
-     */
-
-    private static long mix64(long z) {
-        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
-        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
-        return z ^ (z >>> 33);
-    }
-
-    private static int mix32(long z) {
-        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
-        return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
-    }
+    // same constants as Random, but must be redeclared because private
+    private static final long multiplier = 0x5DEECE66DL;
+    private static final long addend = 0xBL;
+    private static final long mask = (1L << 48) - 1;
 
     /**
-     * Field used only during singleton initialization.
-     * True when constructor completes.
+     * The random seed. We can't use super.seed.
+     */
+    private long rnd;
+
+    /**
+     * Initialization flag to permit calls to setSeed to succeed only
+     * while executing the Random constructor.  We can't allow others
+     * since it would cause setting seed in one part of a program to
+     * unintentionally impact other usages by the thread.
      */
     boolean initialized;
 
-    /** Constructor used only for static singleton */
-    private ThreadLocalRandom() {
-        initialized = true; // false during super() call
-    }
+    // Padding to help avoid memory contention among seed updates in
+    // different TLRs in the common case that they are located near
+    // each other.
+    private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
 
     /**
-     * Initialize Thread fields for the current thread.  Called only
-     * when Thread.threadLocalRandomProbe is zero, indicating that a
-     * thread local seed value needs to be generated. Note that even
-     * though the initialization is purely thread-local, we need to
-     * rely on (static) atomic generators to initialize the values.
+     * The actual ThreadLocal
      */
-    static final void localInit() {
-        int p = probeGenerator.addAndGet(PROBE_INCREMENT);
-        int probe = (p == 0) ? 1 : p; // skip 0
-        long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
-        Thread t = Thread.currentThread();
-        U.putLong(t, SEED, seed);
-        U.putInt(t, PROBE, probe);
+    private static final ThreadLocal<ThreadLocalRandom> localRandom =
+        new ThreadLocal<ThreadLocalRandom>() {
+            protected ThreadLocalRandom initialValue() {
+                return new ThreadLocalRandom();
+            }
+    };
+
+
+    /**
+     * Constructor called only by localRandom.initialValue.
+     */
+    ThreadLocalRandom() {
+        super();
+        initialized = true;
     }
 
     /**
@@ -141,9 +81,7 @@
      * @return the current thread's {@code ThreadLocalRandom}
      */
     public static ThreadLocalRandom current() {
-        if (U.getInt(Thread.currentThread(), PROBE) == 0)
-            localInit();
-        return instance;
+        return localRandom.get();
     }
 
     /**
@@ -153,894 +91,107 @@
      * @throws UnsupportedOperationException always
      */
     public void setSeed(long seed) {
-        // only allow call from super() constructor
         if (initialized)
             throw new UnsupportedOperationException();
+        rnd = (seed ^ multiplier) & mask;
     }
 
-    final long nextSeed() {
-        Thread t; long r; // read and update per-thread seed
-        U.putLong(t = Thread.currentThread(), SEED,
-                  r = U.getLong(t, SEED) + GAMMA);
-        return r;
-    }
-
-    // We must define this, but never use it.
     protected int next(int bits) {
-        return (int)(mix64(nextSeed()) >>> (64 - bits));
+        rnd = (rnd * multiplier + addend) & mask;
+        return (int) (rnd >>> (48-bits));
     }
 
     /**
-     * The form of nextLong used by LongStream Spliterators.  If
-     * origin is greater than bound, acts as unbounded form of
-     * nextLong, else as bounded form.
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
      *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final long internalNextLong(long origin, long bound) {
-        long r = mix64(nextSeed());
-        if (origin < bound) {
-            long n = bound - origin, m = n - 1;
-            if ((n & m) == 0L)  // power of two
-                r = (r & m) + origin;
-            else if (n > 0L) {  // reject over-represented candidates
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = mix64(nextSeed()) >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {              // range not representable as long
-                while (r < origin || r >= bound)
-                    r = mix64(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextInt used by IntStream Spliterators.
-     * Exactly the same as long version, except for types.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final int internalNextInt(int origin, int bound) {
-        int r = mix32(nextSeed());
-        if (origin < bound) {
-            int n = bound - origin, m = n - 1;
-            if ((n & m) == 0)
-                r = (r & m) + origin;
-            else if (n > 0) {
-                for (int u = r >>> 1;
-                     u + m - (r = u % n) < 0;
-                     u = mix32(nextSeed()) >>> 1)
-                    ;
-                r += origin;
-            }
-            else {
-                while (r < origin || r >= bound)
-                    r = mix32(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextDouble used by DoubleStream Spliterators.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final double internalNextDouble(double origin, double bound) {
-        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // correct for rounding
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value.
-     *
-     * @return a pseudorandom {@code int} value
-     */
-    public int nextInt() {
-        return mix32(nextSeed());
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code int} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public int nextInt(int bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        int r = mix32(nextSeed());
-        int m = bound - 1;
-        if ((bound & m) == 0) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (int u = r >>> 1;
-                 u + m - (r = u % bound) < 0;
-                 u = mix32(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
+     * @param least the least value returned
      * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code int} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
      */
-    public int nextInt(int origin, int bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextInt(origin, bound);
+    public int nextInt(int least, int bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextInt(bound - least) + least;
     }
 
     /**
-     * Returns a pseudorandom {@code long} value.
+     * Returns a pseudorandom, uniformly distributed value
+     * between 0 (inclusive) and the specified value (exclusive).
      *
-     * @return a pseudorandom {@code long} value
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
      */
-    public long nextLong() {
-        return mix64(nextSeed());
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code long} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public long nextLong(long bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        long r = mix64(nextSeed());
-        long m = bound - 1;
-        if ((bound & m) == 0L) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (long u = r >>> 1;
-                 u + m - (r = u % bound) < 0L;
-                 u = mix64(nextSeed()) >>> 1)
-                ;
+    public long nextLong(long n) {
+        if (n <= 0)
+            throw new IllegalArgumentException("n must be positive");
+        // Divide n by two until small enough for nextInt. On each
+        // iteration (at most 31 of them but usually much less),
+        // randomly choose both whether to include high bit in result
+        // (offset) and whether to continue with the lower vs upper
+        // half (which makes a difference only if odd).
+        long offset = 0;
+        while (n >= Integer.MAX_VALUE) {
+            int bits = next(2);
+            long half = n >>> 1;
+            long nextn = ((bits & 2) == 0) ? half : n - half;
+            if ((bits & 1) == 0)
+                offset += n - nextn;
+            n = nextn;
         }
-        return r;
+        return offset + nextInt((int) n);
     }
 
     /**
-     * Returns a pseudorandom {@code long} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
      *
-     * @param origin the least value returned
+     * @param least the least value returned
      * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code long} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
      */
-    public long nextLong(long origin, long bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextLong(origin, bound);
+    public long nextLong(long least, long bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextLong(bound - least) + least;
     }
 
     /**
-     * Returns a pseudorandom {@code double} value between zero
-     * (inclusive) and one (exclusive).
+     * Returns a pseudorandom, uniformly distributed {@code double} value
+     * between 0 (inclusive) and the specified value (exclusive).
      *
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and one (exclusive)
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
      */
-    public double nextDouble() {
-        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
+    public double nextDouble(double n) {
+        if (!(n > 0))
+            throw new IllegalArgumentException("n must be positive");
+        return nextDouble() * n;
     }
 
     /**
-     * Returns a pseudorandom {@code double} value between 0.0
-     * (inclusive) and the specified bound (exclusive).
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
      *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public double nextDouble(double bound) {
-        if (!(bound > 0.0))
-            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);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between the specified
-     * origin (inclusive) and bound (exclusive).
-     *
-     * @param origin the least value returned
+     * @param least the least value returned
      * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code double} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
      */
-    public double nextDouble(double origin, double bound) {
-        if (!(origin < bound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextDouble(origin, bound);
+    public double nextDouble(double least, double bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextDouble() * (bound - least) + least;
     }
 
-    /**
-     * Returns a pseudorandom {@code boolean} value.
-     *
-     * @return a pseudorandom {@code boolean} value
-     */
-    public boolean nextBoolean() {
-        return mix32(nextSeed()) < 0;
-    }
-
-    /**
-     * Returns a pseudorandom {@code float} value between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @return a pseudorandom {@code float} value between zero
-     *         (inclusive) and one (exclusive)
-     */
-    public float nextFloat() {
-        return (mix32(nextSeed()) >>> 8) * FLOAT_UNIT;
-    }
-
-    public double nextGaussian() {
-        // Use nextLocalGaussian instead of nextGaussian field
-        Double d = nextLocalGaussian.get();
-        if (d != null) {
-            nextLocalGaussian.set(null);
-            return d.doubleValue();
-        }
-        double v1, v2, s;
-        do {
-            v1 = 2 * nextDouble() - 1; // between -1 and 1
-            v2 = 2 * nextDouble() - 1; // between -1 and 1
-            s = v1 * v1 + v2 * v2;
-        } while (s >= 1 || s == 0);
-        double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
-        nextLocalGaussian.set(new Double(v2 * multiplier));
-        return v1 * multiplier;
-    }
-
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    // TODO(streams):
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number of
-    //  * pseudorandom {@code int} values.
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @return a stream of pseudorandom {@code int} values
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero
-    //  * @since 1.8
-    //  */
-    // public IntStream ints(long streamSize) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     return StreamSupport.intStream
-    //         (new RandomIntsSpliterator
-    //          (0L, streamSize, Integer.MAX_VALUE, 0),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code int}
-    //  * values.
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * ints(Long.MAX_VALUE)}.
-    //  *
-    //  * @return a stream of pseudorandom {@code int} values
-    //  * @since 1.8
-    //  */
-    // public IntStream ints() {
-    //     return StreamSupport.intStream
-    //         (new RandomIntsSpliterator
-    //          (0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number
-    //  * of pseudorandom {@code int} values, each conforming to the given
-    //  * origin (inclusive) and bound (exclusive).
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code int} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero, or {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public IntStream ints(long streamSize, int randomNumberOrigin,
-    //                       int randomNumberBound) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     if (randomNumberOrigin >= randomNumberBound)
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.intStream
-    //         (new RandomIntsSpliterator
-    //          (0L, streamSize, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code
-    //  * int} values, each conforming to the given origin (inclusive) and bound
-    //  * (exclusive).
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-    //  *
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code int} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-    //     if (randomNumberOrigin >= randomNumberBound)
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.intStream
-    //         (new RandomIntsSpliterator
-    //          (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number of
-    //  * pseudorandom {@code long} values.
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @return a stream of pseudorandom {@code long} values
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero
-    //  * @since 1.8
-    //  */
-    // public LongStream longs(long streamSize) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     return StreamSupport.longStream
-    //         (new RandomLongsSpliterator
-    //          (0L, streamSize, Long.MAX_VALUE, 0L),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code long}
-    //  * values.
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * longs(Long.MAX_VALUE)}.
-    //  *
-    //  * @return a stream of pseudorandom {@code long} values
-    //  * @since 1.8
-    //  */
-    // public LongStream longs() {
-    //     return StreamSupport.longStream
-    //         (new RandomLongsSpliterator
-    //          (0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number of
-    //  * pseudorandom {@code long}, each conforming to the given origin
-    //  * (inclusive) and bound (exclusive).
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code long} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero, or {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public LongStream longs(long streamSize, long randomNumberOrigin,
-    //                         long randomNumberBound) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     if (randomNumberOrigin >= randomNumberBound)
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.longStream
-    //         (new RandomLongsSpliterator
-    //          (0L, streamSize, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code
-    //  * long} values, each conforming to the given origin (inclusive) and bound
-    //  * (exclusive).
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-    //  *
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code long} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-    //     if (randomNumberOrigin >= randomNumberBound)
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.longStream
-    //         (new RandomLongsSpliterator
-    //          (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number of
-    //  * pseudorandom {@code double} values, each between zero
-    //  * (inclusive) and one (exclusive).
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @return a stream of {@code double} values
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero
-    //  * @since 1.8
-    //  */
-    // public DoubleStream doubles(long streamSize) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     return StreamSupport.doubleStream
-    //         (new RandomDoublesSpliterator
-    //          (0L, streamSize, Double.MAX_VALUE, 0.0),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code
-    //  * double} values, each between zero (inclusive) and one
-    //  * (exclusive).
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * doubles(Long.MAX_VALUE)}.
-    //  *
-    //  * @return a stream of pseudorandom {@code double} values
-    //  * @since 1.8
-    //  */
-    // public DoubleStream doubles() {
-    //     return StreamSupport.doubleStream
-    //         (new RandomDoublesSpliterator
-    //          (0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns a stream producing the given {@code streamSize} number of
-    //  * pseudorandom {@code double} values, each conforming to the given origin
-    //  * (inclusive) and bound (exclusive).
-    //  *
-    //  * @param streamSize the number of values to generate
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code double} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code streamSize} is
-    //  *         less than zero
-    //  * @throws IllegalArgumentException if {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public DoubleStream doubles(long streamSize, double randomNumberOrigin,
-    //                             double randomNumberBound) {
-    //     if (streamSize < 0L)
-    //         throw new IllegalArgumentException(BAD_SIZE);
-    //     if (!(randomNumberOrigin < randomNumberBound))
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.doubleStream
-    //         (new RandomDoublesSpliterator
-    //          (0L, streamSize, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    // /**
-    //  * Returns an effectively unlimited stream of pseudorandom {@code
-    //  * double} values, each conforming to the given origin (inclusive) and bound
-    //  * (exclusive).
-    //  *
-    //  * @implNote This method is implemented to be equivalent to {@code
-    //  * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-    //  *
-    //  * @param randomNumberOrigin the origin (inclusive) of each random value
-    //  * @param randomNumberBound the bound (exclusive) of each random value
-    //  * @return a stream of pseudorandom {@code double} values,
-    //  *         each with the given origin (inclusive) and bound (exclusive)
-    //  * @throws IllegalArgumentException if {@code randomNumberOrigin}
-    //  *         is greater than or equal to {@code randomNumberBound}
-    //  * @since 1.8
-    //  */
-    // public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-    //     if (!(randomNumberOrigin < randomNumberBound))
-    //         throw new IllegalArgumentException(BAD_RANGE);
-    //     return StreamSupport.doubleStream
-    //         (new RandomDoublesSpliterator
-    //          (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-    //          false);
-    // }
-
-    /**
-     * Spliterator for int streams.  We multiplex the four int
-     * versions into one class by treating a bound less than origin as
-     * unbounded, and also by treating "infinite" as equivalent to
-     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
-     * approach. The long and double versions of this class are
-     * identical except for types.
-     */
-    private static final class RandomIntsSpliterator
-            implements Spliterator.OfInt {
-        long index;
-        final long fence;
-        final int origin;
-        final int bound;
-        RandomIntsSpliterator(long index, long fence,
-                              int origin, int bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomIntsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomIntsSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                int o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextInt(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    private static final class RandomLongsSpliterator
-            implements Spliterator.OfLong {
-        long index;
-        final long fence;
-        final long origin;
-        final long bound;
-        RandomLongsSpliterator(long index, long fence,
-                               long origin, long bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomLongsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomLongsSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                long o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextLong(o, b));
-                } while (++i < f);
-            }
-        }
-
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    private static final class RandomDoublesSpliterator
-            implements Spliterator.OfDouble {
-        long index;
-        final long fence;
-        final double origin;
-        final double bound;
-        RandomDoublesSpliterator(long index, long fence,
-                                 double origin, double bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomDoublesSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomDoublesSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                double o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextDouble(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-
-    // Within-package utilities
-
-    /*
-     * Descriptions of the usages of the methods below can be found in
-     * the classes that use them. Briefly, a thread's "probe" value is
-     * a non-zero hash code that (probably) does not collide with
-     * other existing threads with respect to any power of two
-     * collision space. When it does collide, it is pseudo-randomly
-     * adjusted (using a Marsaglia XorShift). The nextSecondarySeed
-     * method is used in the same contexts as ThreadLocalRandom, but
-     * only for transient usages such as random adaptive spin/block
-     * sequences for which a cheap RNG suffices and for which it could
-     * in principle disrupt user-visible statistical properties of the
-     * main ThreadLocalRandom if we were to use it.
-     *
-     * Note: Because of package-protection issues, versions of some
-     * these methods also appear in some subpackage classes.
-     */
-
-    /**
-     * Returns the probe value for the current thread without forcing
-     * initialization. Note that invoking ThreadLocalRandom.current()
-     * can be used to force initialization on zero return.
-     */
-    static final int getProbe() {
-        return U.getInt(Thread.currentThread(), PROBE);
-    }
-
-    /**
-     * Pseudo-randomly advances and records the given probe value for the
-     * given thread.
-     */
-    static final int advanceProbe(int probe) {
-        probe ^= probe << 13;   // xorshift
-        probe ^= probe >>> 17;
-        probe ^= probe << 5;
-        U.putInt(Thread.currentThread(), PROBE, probe);
-        return probe;
-    }
-
-    /**
-     * Returns the pseudo-randomly initialized or updated secondary seed.
-     */
-    static final int nextSecondarySeed() {
-        int r;
-        Thread t = Thread.currentThread();
-        if ((r = U.getInt(t, SECONDARY)) != 0) {
-            r ^= r << 13;   // xorshift
-            r ^= r >>> 17;
-            r ^= r << 5;
-        }
-        else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
-            r = 1; // avoid zero
-        U.putInt(t, SECONDARY, r);
-        return r;
-    }
-
-    // Serialization support
-
     private static final long serialVersionUID = -5851777807851030925L;
-
-    /**
-     * @serialField rnd long
-     *              seed for random computations
-     * @serialField initialized boolean
-     *              always true
-     */
-    private static final ObjectStreamField[] serialPersistentFields = {
-        new ObjectStreamField("rnd", long.class),
-        new ObjectStreamField("initialized", boolean.class),
-    };
-
-    /**
-     * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it).
-     * @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 {
-
-        java.io.ObjectOutputStream.PutField fields = s.putFields();
-        fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
-        fields.put("initialized", true);
-        s.writeFields();
-    }
-
-    /**
-     * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
-     * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
-     */
-    private Object readResolve() {
-        return current();
-    }
-
-    // Static initialization
-
-    /**
-     * The seed increment.
-     */
-    private static final long GAMMA = 0x9e3779b97f4a7c15L;
-
-    /**
-     * The increment for generating probe values.
-     */
-    private static final int PROBE_INCREMENT = 0x9e3779b9;
-
-    /**
-     * The increment of seeder per new instance.
-     */
-    private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
-
-    // Constants from SplittableRandom
-    private static final double DOUBLE_UNIT = 0x1.0p-53;  // 1.0  / (1L << 53)
-    private static final float  FLOAT_UNIT  = 0x1.0p-24f; // 1.0f / (1 << 24)
-
-    // IllegalArgumentException messages
-    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";
-
-    // Unsafe mechanics
-    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 {
-            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);
-        }
-    }
-
-    /** Rarely-used holder for the second of a pair of Gaussians */
-    private static final ThreadLocal<Double> nextLocalGaussian =
-        new ThreadLocal<>();
-
-    /** Generates per-thread initialization/probe field */
-    private static final AtomicInteger probeGenerator = new AtomicInteger();
-
-    /** The common ThreadLocalRandom */
-    static final ThreadLocalRandom instance = new ThreadLocalRandom();
-
-    /**
-     * The next seed for default constructors.
-     */
-    private static final AtomicLong seeder
-        = new AtomicLong(mix64(System.currentTimeMillis()) ^
-                         mix64(System.nanoTime()));
-
-    // at end of <clinit> to survive static initialization circularity
-    static {
-        if (java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Boolean>() {
-                public Boolean run() {
-                    return Boolean.getBoolean("java.util.secureRandomSeed");
-                }})) {
-            byte[] seedBytes = java.security.SecureRandom.getSeed(8);
-            long s = (long)seedBytes[0] & 0xffL;
-            for (int i = 1; i < 8; ++i)
-                s = (s << 8) | ((long)seedBytes[i] & 0xffL);
-            seeder.set(s);
-        }
-    }
 }
diff --git a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index e601b6a..c484920 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -6,15 +6,11 @@
 
 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.*;
 
 // BEGIN android-note
 // removed security manager docs
@@ -49,8 +45,7 @@
  *
  * <dt>Core and maximum pool sizes</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * A {@code ThreadPoolExecutor} will automatically adjust the
+ * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
  * pool size (see {@link #getPoolSize})
  * according to the bounds set by
  * corePoolSize (see {@link #getCorePoolSize}) and
@@ -72,8 +67,7 @@
  *
  * <dt>On-demand construction</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * By default, even core threads are initially created and
+ * <dd>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
@@ -81,8 +75,7 @@
  *
  * <dt>Creating new threads</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * New threads are created using a {@link ThreadFactory}.  If not
+ * <dd>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
@@ -90,17 +83,11 @@
  * alter the thread's name, thread group, priority, daemon status,
  * etc. If a {@code ThreadFactory} fails to create a thread when asked
  * by returning null from {@code newThread}, the executor will
- * continue, but might not be able to execute any tasks. Threads
- * should possess the "modifyThread" {@code RuntimePermission}. If
- * worker threads or other threads using the pool do not possess this
- * permission, service may be degraded: configuration changes may not
- * take effect in a timely manner, and a shutdown pool may remain in a
- * state in which termination is possible but not completed.</dd>
+ * continue, but might not be able to execute any tasks.</dd>
  *
  * <dt>Keep-alive times</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * If the pool currently has more than corePoolSize threads,
+ * <dd>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
@@ -110,37 +97,36 @@
  * 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 style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * Any {@link BlockingQueue} may be used to transfer and hold
+ * <dd>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.
+ * rather than queuing.</li>
  *
- * <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.
+ * thread.</li>
  *
- * <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.
+ * rejected.</li>
  *
  * </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
@@ -149,7 +135,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.
+ * arrive on average faster than they can be processed.  </li>
  *
  * <li><em> Unbounded queues.</em> Using an unbounded queue (for
  * example a {@link LinkedBlockingQueue} without a predefined
@@ -162,7 +148,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.
+ * average faster than they can be processed.  </li>
  *
  * <li><em>Bounded queues.</em> A bounded queue (for example, an
  * {@link ArrayBlockingQueue}) helps prevent resource exhaustion when
@@ -175,7 +161,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.
+ * decreases throughput.  </li>
  *
  * </ol>
  *
@@ -183,8 +169,7 @@
  *
  * <dt>Rejected tasks</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * New tasks submitted in method {@link #execute(Runnable)} will be
+ * <dd>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
@@ -195,22 +180,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.
+ * rejection. </li>
  *
- * <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.
+ * new tasks are submitted. </li>
  *
- * <li>In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
- * cannot be executed is simply dropped.
+ * <li> In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
+ * cannot be executed is simply dropped.  </li>
  *
  * <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.)
+ * causing this to be repeated.) </li>
  *
  * </ol>
  *
@@ -221,8 +206,7 @@
  *
  * <dt>Hook methods</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * This class provides {@code protected} overridable
+ * <dd>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
@@ -232,14 +216,12 @@
  * any special processing that needs to be done once the Executor has
  * fully terminated.
  *
- * <p>If hook, callback, or BlockingQueue methods throw exceptions,
- * internal worker threads may in turn fail, abruptly terminate, and
- * possibly be replaced.</dd>
+ * <p>If hook or callback methods throw exceptions, internal worker
+ * threads may in turn fail and abruptly terminate.</dd>
  *
  * <dt>Queue maintenance</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * Method {@link #getQueue()} allows access to the work queue
+ * <dd>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
@@ -248,8 +230,7 @@
  *
  * <dt>Finalization</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * A pool that is no longer referenced in a program <em>AND</em>
+ * <dd>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
@@ -263,7 +244,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();
@@ -452,10 +433,10 @@
      * Set containing all worker threads in pool. Accessed only when
      * holding mainLock.
      */
-    private final HashSet<Worker> workers = new HashSet<>();
+    private final HashSet<Worker> workers = new HashSet<Worker>();
 
     /**
-     * Wait condition to support awaitTermination.
+     * Wait condition to support awaitTermination
      */
     private final Condition termination = mainLock.newCondition();
 
@@ -531,7 +512,7 @@
     private volatile int maximumPoolSize;
 
     /**
-     * The default rejected execution handler.
+     * The default rejected execution handler
      */
     private static final RejectedExecutionHandler defaultHandler =
         new AbortPolicy();
@@ -658,7 +639,6 @@
      *        (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) ||
@@ -841,7 +821,7 @@
      */
     private List<Runnable> drainQueue() {
         BlockingQueue<Runnable> q = workQueue;
-        ArrayList<Runnable> taskList = new ArrayList<>();
+        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
         q.drainTo(taskList);
         if (!q.isEmpty()) {
             for (Runnable r : q.toArray(new Runnable[0])) {
@@ -1396,7 +1376,7 @@
      *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  This implementation
-     * interrupts tasks via {@link Thread#interrupt}; any task that
+     * cancels tasks via {@link Thread#interrupt}, so any task that
      * fails to respond to interrupts may never terminate.
      */
     // android-note: Removed @throws SecurityException
@@ -1446,12 +1426,13 @@
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            while (!runStateAtLeast(ctl.get(), TERMINATED)) {
-                if (nanos <= 0L)
+            for (;;) {
+                if (runStateAtLeast(ctl.get(), TERMINATED))
+                    return true;
+                if (nanos <= 0)
                     return false;
                 nanos = termination.awaitNanos(nanos);
             }
-            return true;
         } finally {
             mainLock.unlock();
         }
@@ -1520,12 +1501,10 @@
      *
      * @param corePoolSize the new core size
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
-     *         or {@code corePoolSize} is greater than the {@linkplain
-     *         #getMaximumPoolSize() maximum pool size}
      * @see #getCorePoolSize
      */
     public void setCorePoolSize(int corePoolSize) {
-        if (corePoolSize < 0 || maximumPoolSize < corePoolSize)
+        if (corePoolSize < 0)
             throw new IllegalArgumentException();
         int delta = corePoolSize - this.corePoolSize;
         this.corePoolSize = corePoolSize;
@@ -1668,13 +1647,11 @@
     }
 
     /**
-     * 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.
+     * 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.
      *
      * @param time the time to wait.  A time value of zero will cause
      *        excess threads to terminate immediately after executing tasks.
@@ -1697,11 +1674,8 @@
 
     /**
      * Returns 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}.
+     * that threads in excess of the core pool size may remain
+     * idle before being terminated.
      *
      * @param unit the desired time unit of the result
      * @return the time limit
@@ -1732,8 +1706,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.
@@ -1905,12 +1879,11 @@
             mainLock.unlock();
         }
         int c = ctl.get();
-        String runState =
-            runStateLessThan(c, SHUTDOWN) ? "Running" :
-            runStateAtLeast(c, TERMINATED) ? "Terminated" :
-            "Shutting down";
+        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
+                     (runStateAtLeast(c, TERMINATED) ? "Terminated" :
+                      "Shutting down"));
         return super.toString() +
-            "[" + runState +
+            "[" + rs +
             ", pool size = " + nworkers +
             ", active threads = " + nactive +
             ", queued tasks = " + workQueue.size() +
@@ -1957,23 +1930,20 @@
      * 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<?>
-     *         && ((Future<?>)r).isDone()) {
+     *     if (t == null && r instanceof Future<?>) {
      *       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) {
-     *         // ignore/reset
-     *         Thread.currentThread().interrupt();
+     *           Thread.currentThread().interrupt(); // ignore/reset
      *       }
      *     }
      *     if (t != null)
diff --git a/luni/src/main/java/java/util/concurrent/TimeUnit.java b/luni/src/main/java/java/util/concurrent/TimeUnit.java
index fff02d8..8e6a5f7 100644
--- a/luni/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/luni/src/main/java/java/util/concurrent/TimeUnit.java
@@ -6,12 +6,6 @@
 
 package java.util.concurrent;
 
-import java.util.Objects;
-
-// BEGIN android-note
-// removed java 9 ChronoUnit related code
-// END android-note
-
 /**
  * A {@code TimeUnit} represents time durations at a given unit of
  * granularity and provides utility methods to convert across units,
@@ -29,12 +23,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>
  *
@@ -47,7 +41,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; }
@@ -62,7 +56,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)); }
@@ -77,7 +71,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)); }
@@ -92,7 +86,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)); }
@@ -107,7 +101,7 @@
     },
 
     /**
-     * Time unit representing sixty seconds.
+     * Time unit representing sixty seconds
      * @since 1.6
      */
     MINUTES {
@@ -123,7 +117,7 @@
     },
 
     /**
-     * Time unit representing sixty minutes.
+     * Time unit representing sixty minutes
      * @since 1.6
      */
     HOURS {
@@ -139,7 +133,7 @@
     },
 
     /**
-     * Time unit representing twenty four hours.
+     * Time unit representing twenty four hours
      * @since 1.6
      */
     DAYS {
@@ -170,7 +164,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;
     }
@@ -306,7 +300,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) {
@@ -366,4 +360,5 @@
             Thread.sleep(ms, ns);
         }
     }
+
 }
diff --git a/luni/src/main/java/java/util/concurrent/TransferQueue.java b/luni/src/main/java/java/util/concurrent/TransferQueue.java
index d4166b5..4c2be6f 100644
--- a/luni/src/main/java/java/util/concurrent/TransferQueue.java
+++ b/luni/src/main/java/java/util/concurrent/TransferQueue.java
@@ -34,7 +34,7 @@
  *
  * @since 1.7
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public interface TransferQueue<E> extends BlockingQueue<E> {
     /**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index 01e4b07..f51e6af 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -6,6 +6,8 @@
 
 package java.util.concurrent.atomic;
 
+import sun.misc.Unsafe;
+
 /**
  * A {@code boolean} value that may be updated atomically. See the
  * {@link java.util.concurrent.atomic} package specification for
@@ -19,17 +21,15 @@
  */
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    // setup to use Unsafe.compareAndSwapInt for updates
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long valueOffset;
 
     static {
         try {
-            VALUE = U.objectFieldOffset
+            valueOffset = unsafe.objectFieldOffset
                 (AtomicBoolean.class.getDeclaredField("value"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+        } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile int value;
@@ -64,13 +64,13 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+        int e = expect ? 1 : 0;
+        int u = update ? 1 : 0;
+        return unsafe.compareAndSwapInt(this, valueOffset, e, u);
     }
 
     /**
@@ -83,12 +83,12 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean weakCompareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+        int e = expect ? 1 : 0;
+        int u = update ? 1 : 0;
+        return unsafe.compareAndSwapInt(this, valueOffset, e, u);
     }
 
     /**
@@ -107,7 +107,8 @@
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
+        int v = newValue ? 1 : 0;
+        unsafe.putOrderedInt(this, valueOffset, v);
     }
 
     /**
@@ -117,11 +118,11 @@
      * @return the previous value
      */
     public final boolean getAndSet(boolean newValue) {
-        boolean prev;
-        do {
-            prev = get();
-        } while (!compareAndSet(prev, newValue));
-        return prev;
+        for (;;) {
+            boolean current = get();
+            if (compareAndSet(current, newValue))
+                return current;
+        }
     }
 
     /**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index 849fd8a..8a15298 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent.atomic;
 
-import java.util.function.IntBinaryOperator;
-import java.util.function.IntUnaryOperator;
+import sun.misc.Unsafe;
 
 /**
  * An {@code int} value that may be updated atomically.  See the
@@ -21,20 +20,19 @@
  *
  * @since 1.5
  * @author Doug Lea
- */
+*/
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    // setup to use Unsafe.compareAndSwapInt for updates
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long valueOffset;
 
     static {
         try {
-            VALUE = U.objectFieldOffset
+            valueOffset = unsafe.objectFieldOffset
                 (AtomicInteger.class.getDeclaredField("value"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+        } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile int value;
@@ -79,7 +77,7 @@
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putOrderedInt(this, VALUE, newValue);
+        unsafe.putOrderedInt(this, valueOffset, newValue);
     }
 
     /**
@@ -89,7 +87,11 @@
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        return U.getAndSetInt(this, VALUE, newValue);
+        for (;;) {
+            int current = get();
+            if (compareAndSet(current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -98,11 +100,11 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
     }
 
     /**
@@ -115,10 +117,10 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
     }
 
     /**
@@ -127,7 +129,12 @@
      * @return the previous value
      */
     public final int getAndIncrement() {
-        return U.getAndAddInt(this, VALUE, 1);
+        for (;;) {
+            int current = get();
+            int next = current + 1;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -136,7 +143,12 @@
      * @return the previous value
      */
     public final int getAndDecrement() {
-        return U.getAndAddInt(this, VALUE, -1);
+        for (;;) {
+            int current = get();
+            int next = current - 1;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -146,7 +158,12 @@
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        return U.getAndAddInt(this, VALUE, delta);
+        for (;;) {
+            int current = get();
+            int next = current + delta;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -155,7 +172,12 @@
      * @return the updated value
      */
     public final int incrementAndGet() {
-        return U.getAndAddInt(this, VALUE, 1) + 1;
+        for (;;) {
+            int current = get();
+            int next = current + 1;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -164,7 +186,12 @@
      * @return the updated value
      */
     public final int decrementAndGet() {
-        return U.getAndAddInt(this, VALUE, -1) - 1;
+        for (;;) {
+            int current = get();
+            int next = current - 1;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -174,93 +201,12 @@
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        return U.getAndAddInt(this, VALUE, delta) + delta;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final int getAndUpdate(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int updateAndGet(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the previous value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final int getAndAccumulate(int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the updated value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int accumulateAndGet(int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        for (;;) {
+            int current = get();
+            int next = current + delta;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -273,7 +219,6 @@
 
     /**
      * Returns the value of this {@code AtomicInteger} as an {@code int}.
-     * Equivalent to {@link #get()}.
      */
     public int intValue() {
         return get();
@@ -282,7 +227,6 @@
     /**
      * Returns the value of this {@code AtomicInteger} as a {@code long}
      * after a widening primitive conversion.
-     * @jls 5.1.2 Widening Primitive Conversions
      */
     public long longValue() {
         return (long)get();
@@ -291,7 +235,6 @@
     /**
      * Returns the value of this {@code AtomicInteger} as a {@code float}
      * after a widening primitive conversion.
-     * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
         return (float)get();
@@ -300,7 +243,6 @@
     /**
      * Returns the value of this {@code AtomicInteger} as a {@code double}
      * after a widening primitive conversion.
-     * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 7597e53..fd492d1 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent.atomic;
 
-import java.util.function.IntBinaryOperator;
-import java.util.function.IntUnaryOperator;
+import sun.misc.Unsafe;
 
 /**
  * An {@code int} array in which elements may be updated atomically.
@@ -20,17 +19,16 @@
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final int base = unsafe.arrayBaseOffset(int[].class);
+    private static final int shift;
     private final int[] array;
 
     static {
-        ABASE = U.arrayBaseOffset(int[].class);
-        int scale = U.arrayIndexScale(int[].class);
+        int scale = unsafe.arrayIndexScale(int[].class);
         if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            throw new Error("data type scale not a power of two");
+        shift = 31 - Integer.numberOfLeadingZeros(scale);
     }
 
     private long checkedByteOffset(int i) {
@@ -41,7 +39,7 @@
     }
 
     private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
+        return ((long) i << shift) + base;
     }
 
     /**
@@ -86,7 +84,7 @@
     }
 
     private int getRaw(long offset) {
-        return U.getIntVolatile(array, offset);
+        return unsafe.getIntVolatile(array, offset);
     }
 
     /**
@@ -96,7 +94,7 @@
      * @param newValue the new value
      */
     public final void set(int i, int newValue) {
-        U.putIntVolatile(array, checkedByteOffset(i), newValue);
+        unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -107,7 +105,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putOrderedInt(array, checkedByteOffset(i), newValue);
+        unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -119,7 +117,12 @@
      * @return the previous value
      */
     public final int getAndSet(int i, int newValue) {
-        return U.getAndSetInt(array, checkedByteOffset(i), newValue);
+        long offset = checkedByteOffset(i);
+        while (true) {
+            int current = getRaw(offset);
+            if (compareAndSetRaw(offset, current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -129,7 +132,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, int expect, int update) {
@@ -137,7 +140,7 @@
     }
 
     private boolean compareAndSetRaw(long offset, int expect, int update) {
-        return U.compareAndSwapInt(array, offset, expect, update);
+        return unsafe.compareAndSwapInt(array, offset, expect, update);
     }
 
     /**
@@ -151,7 +154,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, int expect, int update) {
         return compareAndSet(i, expect, update);
@@ -185,7 +188,12 @@
      * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
-        return U.getAndAddInt(array, checkedByteOffset(i), delta);
+        long offset = checkedByteOffset(i);
+        while (true) {
+            int current = getRaw(offset);
+            if (compareAndSetRaw(offset, current, current + delta))
+                return current;
+        }
     }
 
     /**
@@ -195,7 +203,7 @@
      * @return the updated value
      */
     public final int incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return addAndGet(i, 1);
     }
 
     /**
@@ -205,7 +213,7 @@
      * @return the updated value
      */
     public final int decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return addAndGet(i, -1);
     }
 
     /**
@@ -216,101 +224,13 @@
      * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
-        return getAndAdd(i, delta) + delta;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
         long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final int getAndAccumulate(int i, int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int accumulateAndGet(int i, int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        while (true) {
+            int current = getRaw(offset);
+            int next = current + delta;
+            if (compareAndSetRaw(offset, current, next))
+                return next;
+        }
     }
 
     /**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 9c55491..15e8840 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -7,15 +7,12 @@
 package java.util.concurrent.atomic;
 
 import dalvik.system.VMStack; // android-added
+import sun.misc.Unsafe;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
-import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import java.util.function.IntBinaryOperator;
-import java.util.function.IntUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import java.security.PrivilegedActionException;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -52,11 +49,8 @@
      * or the field is inaccessible to the caller according to Java language
      * access control
      */
-    @CallerSensitive
-    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
-                                                              String fieldName) {
-        return new AtomicIntegerFieldUpdaterImpl<U>
-            (tclass, fieldName, VMStack.getStackClass1()); // android-changed
+    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+        return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
     }
 
     /**
@@ -75,7 +69,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor
      */
@@ -95,7 +89,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor
      */
@@ -139,11 +133,11 @@
      * @return the previous value
      */
     public int getAndSet(T obj, int newValue) {
-        int prev;
-        do {
-            prev = get(obj);
-        } while (!compareAndSet(obj, prev, newValue));
-        return prev;
+        for (;;) {
+            int current = get(obj);
+            if (compareAndSet(obj, current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -154,12 +148,12 @@
      * @return the previous value
      */
     public int getAndIncrement(T obj) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev + 1;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            int current = get(obj);
+            int next = current + 1;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -170,12 +164,12 @@
      * @return the previous value
      */
     public int getAndDecrement(T obj) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev - 1;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            int current = get(obj);
+            int next = current - 1;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -187,12 +181,12 @@
      * @return the previous value
      */
     public int getAndAdd(T obj, int delta) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev + delta;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            int current = get(obj);
+            int next = current + delta;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -203,12 +197,12 @@
      * @return the updated value
      */
     public int incrementAndGet(T obj) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev + 1;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            int current = get(obj);
+            int next = current + 1;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
     /**
@@ -219,12 +213,12 @@
      * @return the updated value
      */
     public int decrementAndGet(T obj) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev - 1;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            int current = get(obj);
+            int next = current - 1;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
     /**
@@ -236,131 +230,31 @@
      * @return the updated value
      */
     public int addAndGet(T obj, int delta) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = prev + delta;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            int current = get(obj);
+            int next = current + delta;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
+     * Standard hotspot implementation using intrinsics
      */
-    public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final int getAndAccumulate(T obj, int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final int accumulateAndGet(T obj, int x,
-                                      IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
-    }
-
-    /**
-     * Standard hotspot implementation using intrinsics.
-     */
-    private static final class AtomicIntegerFieldUpdaterImpl<T>
-        extends AtomicIntegerFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
         private final long offset;
-        /**
-         * if field is protected, the subclass constructing updater, else
-         * the same as tclass
-         */
-        private final Class<?> cclass;
-        /** class holding the field */
         private final Class<T> tclass;
+        private final Class<?> cclass;
 
-        AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
-                                      final String fieldName,
-                                      final Class<?> caller) {
+        AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName) {
             final Field field;
+            final Class<?> caller;
             final int modifiers;
             try {
-                field = AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<Field>() {
-                        public Field run() throws NoSuchFieldException {
-                            return tclass.getDeclaredField(fieldName);
-                        }
-                    });
+                field = tclass.getDeclaredField(fieldName); // android-changed
+                caller = VMStack.getStackClass2(); // android-changed
+
                 modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
@@ -369,7 +263,7 @@
                 // ClassLoader ccl = caller.getClassLoader();
                 // if ((ccl != null) && (ccl != cl) &&
                 //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                 // }
                 // END android-removed
             // BEGIN android-removed
@@ -380,15 +274,17 @@
                 throw new RuntimeException(ex);
             }
 
-            if (field.getType() != int.class)
+            Class<?> fieldt = field.getType();
+            if (fieldt != int.class)
                 throw new IllegalArgumentException("Must be integer type");
 
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
-            this.offset = U.objectFieldOffset(field);
+            offset = unsafe.objectFieldOffset(field);
         }
 
         // BEGIN android-removed
@@ -397,7 +293,7 @@
         //  * classloader's delegation chain.
         //  * Equivalent to the inaccessible: first.isAncestor(second).
         //  */
-        // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+        //  private static boolean isAncestor(ClassLoader first, ClassLoader second) {
         //     ClassLoader acl = first;
         //     do {
         //         acl = acl.getParent();
@@ -408,88 +304,51 @@
         //     return false;
         // }
         // END android-removed
-
-        /**
-         * Checks that target argument is instance of cclass.  On
-         * failure, throws cause.
-         */
-        private final void accessCheck(T obj) {
-            if (!cclass.isInstance(obj))
-                throwAccessCheckException(obj);
-        }
-
-        /**
-         * Throws access exception if accessCheck failed due to
-         * protected access, else ClassCastException.
-         */
-        private final void throwAccessCheckException(T obj) {
-            if (cclass == tclass)
+        private void fullCheck(T obj) {
+            if (!tclass.isInstance(obj))
                 throw new ClassCastException();
-            else
-                throw new RuntimeException(
-                    new IllegalAccessException(
-                        "Class " +
-                        cclass.getName() +
-                        " can not access a protected member of class " +
-                        tclass.getName() +
-                        " using an instance of " +
-                        obj.getClass().getName()));
+            if (cclass != null)
+                ensureProtectedAccess(obj);
         }
 
-        public final boolean compareAndSet(T obj, int expect, int update) {
-            accessCheck(obj);
-            return U.compareAndSwapInt(obj, offset, expect, update);
+        public boolean compareAndSet(T obj, int expect, int update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.compareAndSwapInt(obj, offset, expect, update);
         }
 
-        public final boolean weakCompareAndSet(T obj, int expect, int update) {
-            accessCheck(obj);
-            return U.compareAndSwapInt(obj, offset, expect, update);
+        public boolean weakCompareAndSet(T obj, int expect, int update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.compareAndSwapInt(obj, offset, expect, update);
         }
 
-        public final void set(T obj, int newValue) {
-            accessCheck(obj);
-            U.putIntVolatile(obj, offset, newValue);
+        public void set(T obj, int newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            unsafe.putIntVolatile(obj, offset, newValue);
         }
 
-        public final void lazySet(T obj, int newValue) {
-            accessCheck(obj);
-            U.putOrderedInt(obj, offset, newValue);
+        public void lazySet(T obj, int newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            unsafe.putOrderedInt(obj, offset, newValue);
         }
 
         public final int get(T obj) {
-            accessCheck(obj);
-            return U.getIntVolatile(obj, offset);
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getIntVolatile(obj, offset);
         }
 
-        public final int getAndSet(T obj, int newValue) {
-            accessCheck(obj);
-            return U.getAndSetInt(obj, offset, newValue);
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException(
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
         }
-
-        public final int getAndAdd(T obj, int delta) {
-            accessCheck(obj);
-            return U.getAndAddInt(obj, offset, delta);
-        }
-
-        public final int getAndIncrement(T obj) {
-            return getAndAdd(obj, 1);
-        }
-
-        public final int getAndDecrement(T obj) {
-            return getAndAdd(obj, -1);
-        }
-
-        public final int incrementAndGet(T obj) {
-            return getAndAdd(obj, 1) + 1;
-        }
-
-        public final int decrementAndGet(T obj) {
-            return getAndAdd(obj, -1) - 1;
-        }
-
-        public final int addAndGet(T obj, int delta) {
-            return getAndAdd(obj, delta) + delta;
-        }
-
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index fdb5f55..ab2961a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent.atomic;
 
-import java.util.function.LongBinaryOperator;
-import java.util.function.LongUnaryOperator;
+import sun.misc.Unsafe;
 
 /**
  * A {@code long} value that may be updated atomically.  See the
@@ -25,8 +24,9 @@
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    // setup to use Unsafe.compareAndSwapLong for updates
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long valueOffset;
 
     /**
      * Records whether the underlying JVM supports lockless
@@ -44,11 +44,9 @@
 
     static {
         try {
-            VALUE = U.objectFieldOffset
+            valueOffset = unsafe.objectFieldOffset
                 (AtomicLong.class.getDeclaredField("value"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+        } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile long value;
@@ -83,9 +81,7 @@
      * @param newValue the new value
      */
     public final void set(long newValue) {
-        // Use putLongVolatile instead of ordinary volatile store when
-        // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, VALUE, newValue);
+        value = newValue;
     }
 
     /**
@@ -95,7 +91,7 @@
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putOrderedLong(this, VALUE, newValue);
+        unsafe.putOrderedLong(this, valueOffset, newValue);
     }
 
     /**
@@ -105,7 +101,11 @@
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        return U.getAndSetLong(this, VALUE, newValue);
+        while (true) {
+            long current = get();
+            if (compareAndSet(current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -114,11 +114,11 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
     }
 
     /**
@@ -131,10 +131,10 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
     }
 
     /**
@@ -143,7 +143,12 @@
      * @return the previous value
      */
     public final long getAndIncrement() {
-        return U.getAndAddLong(this, VALUE, 1L);
+        while (true) {
+            long current = get();
+            long next = current + 1;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -152,7 +157,12 @@
      * @return the previous value
      */
     public final long getAndDecrement() {
-        return U.getAndAddLong(this, VALUE, -1L);
+        while (true) {
+            long current = get();
+            long next = current - 1;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -162,7 +172,12 @@
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        return U.getAndAddLong(this, VALUE, delta);
+        while (true) {
+            long current = get();
+            long next = current + delta;
+            if (compareAndSet(current, next))
+                return current;
+        }
     }
 
     /**
@@ -171,7 +186,12 @@
      * @return the updated value
      */
     public final long incrementAndGet() {
-        return U.getAndAddLong(this, VALUE, 1L) + 1L;
+        for (;;) {
+            long current = get();
+            long next = current + 1;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -180,7 +200,12 @@
      * @return the updated value
      */
     public final long decrementAndGet() {
-        return U.getAndAddLong(this, VALUE, -1L) - 1L;
+        for (;;) {
+            long current = get();
+            long next = current - 1;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -190,93 +215,12 @@
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        return U.getAndAddLong(this, VALUE, delta) + delta;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndUpdate(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long updateAndGet(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the previous value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndAccumulate(long x,
-                                       LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the updated value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long accumulateAndGet(long x,
-                                       LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        for (;;) {
+            long current = get();
+            long next = current + delta;
+            if (compareAndSet(current, next))
+                return next;
+        }
     }
 
     /**
@@ -290,7 +234,6 @@
     /**
      * Returns the value of this {@code AtomicLong} as an {@code int}
      * after a narrowing primitive conversion.
-     * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public int intValue() {
         return (int)get();
@@ -298,7 +241,6 @@
 
     /**
      * Returns the value of this {@code AtomicLong} as a {@code long}.
-     * Equivalent to {@link #get()}.
      */
     public long longValue() {
         return get();
@@ -307,7 +249,6 @@
     /**
      * Returns the value of this {@code AtomicLong} as a {@code float}
      * after a widening primitive conversion.
-     * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
         return (float)get();
@@ -316,7 +257,6 @@
     /**
      * Returns the value of this {@code AtomicLong} as a {@code double}
      * after a widening primitive conversion.
-     * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index 8da1501..b7f3d1e 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent.atomic;
 
-import java.util.function.LongBinaryOperator;
-import java.util.function.LongUnaryOperator;
+import sun.misc.Unsafe;
 
 /**
  * A {@code long} array in which elements may be updated atomically.
@@ -19,17 +18,16 @@
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final int base = unsafe.arrayBaseOffset(long[].class);
+    private static final int shift;
     private final long[] array;
 
     static {
-        ABASE = U.arrayBaseOffset(long[].class);
-        int scale = U.arrayIndexScale(long[].class);
+        int scale = unsafe.arrayIndexScale(long[].class);
         if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            throw new Error("data type scale not a power of two");
+        shift = 31 - Integer.numberOfLeadingZeros(scale);
     }
 
     private long checkedByteOffset(int i) {
@@ -40,7 +38,7 @@
     }
 
     private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
+        return ((long) i << shift) + base;
     }
 
     /**
@@ -85,7 +83,7 @@
     }
 
     private long getRaw(long offset) {
-        return U.getLongVolatile(array, offset);
+        return unsafe.getLongVolatile(array, offset);
     }
 
     /**
@@ -95,7 +93,7 @@
      * @param newValue the new value
      */
     public final void set(int i, long newValue) {
-        U.putLongVolatile(array, checkedByteOffset(i), newValue);
+        unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -106,7 +104,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putOrderedLong(array, checkedByteOffset(i), newValue);
+        unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -118,7 +116,12 @@
      * @return the previous value
      */
     public final long getAndSet(int i, long newValue) {
-        return U.getAndSetLong(array, checkedByteOffset(i), newValue);
+        long offset = checkedByteOffset(i);
+        while (true) {
+            long current = getRaw(offset);
+            if (compareAndSetRaw(offset, current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -128,7 +131,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, long expect, long update) {
@@ -136,7 +139,7 @@
     }
 
     private boolean compareAndSetRaw(long offset, long expect, long update) {
-        return U.compareAndSwapLong(array, offset, expect, update);
+        return unsafe.compareAndSwapLong(array, offset, expect, update);
     }
 
     /**
@@ -150,7 +153,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, long expect, long update) {
         return compareAndSet(i, expect, update);
@@ -184,7 +187,12 @@
      * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
-        return U.getAndAddLong(array, checkedByteOffset(i), delta);
+        long offset = checkedByteOffset(i);
+        while (true) {
+            long current = getRaw(offset);
+            if (compareAndSetRaw(offset, current, current + delta))
+                return current;
+        }
     }
 
     /**
@@ -194,7 +202,7 @@
      * @return the updated value
      */
     public final long incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return addAndGet(i, 1);
     }
 
     /**
@@ -204,7 +212,7 @@
      * @return the updated value
      */
     public final long decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return addAndGet(i, -1);
     }
 
     /**
@@ -215,101 +223,13 @@
      * @return the updated value
      */
     public long addAndGet(int i, long delta) {
-        return getAndAdd(i, delta) + delta;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndUpdate(int i, LongUnaryOperator updateFunction) {
         long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long updateAndGet(int i, LongUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndAccumulate(int i, long x,
-                                      LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long accumulateAndGet(int i, long x,
-                                      LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        while (true) {
+            long current = getRaw(offset);
+            long next = current + delta;
+            if (compareAndSetRaw(offset, current, next))
+                return next;
+        }
     }
 
     /**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index c1a02b5..65bd452 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -7,15 +7,9 @@
 package java.util.concurrent.atomic;
 
 import dalvik.system.VMStack; // android-added
+import sun.misc.Unsafe;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.function.LongBinaryOperator;
-import java.util.function.LongUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -52,14 +46,11 @@
      * or the field is inaccessible to the caller according to Java language
      * access control
      */
-    @CallerSensitive
-    public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
-                                                           String fieldName) {
-      Class<?> caller = VMStack.getStackClass1(); // android-changed
+    public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
         if (AtomicLong.VM_SUPPORTS_LONG_CAS)
-            return new CASUpdater<U>(tclass, fieldName, caller);
+            return new CASUpdater<U>(tclass, fieldName);
         else
-            return new LockedUpdater<U>(tclass, fieldName, caller);
+            return new LockedUpdater<U>(tclass, fieldName);
     }
 
     /**
@@ -78,7 +69,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor
      */
@@ -98,7 +89,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor
      */
@@ -142,11 +133,11 @@
      * @return the previous value
      */
     public long getAndSet(T obj, long newValue) {
-        long prev;
-        do {
-            prev = get(obj);
-        } while (!compareAndSet(obj, prev, newValue));
-        return prev;
+        for (;;) {
+            long current = get(obj);
+            if (compareAndSet(obj, current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -157,12 +148,12 @@
      * @return the previous value
      */
     public long getAndIncrement(T obj) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev + 1;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            long current = get(obj);
+            long next = current + 1;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -173,12 +164,12 @@
      * @return the previous value
      */
     public long getAndDecrement(T obj) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev - 1;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            long current = get(obj);
+            long next = current - 1;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -190,12 +181,12 @@
      * @return the previous value
      */
     public long getAndAdd(T obj, long delta) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev + delta;
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
+        for (;;) {
+            long current = get(obj);
+            long next = current + delta;
+            if (compareAndSet(obj, current, next))
+                return current;
+        }
     }
 
     /**
@@ -206,12 +197,12 @@
      * @return the updated value
      */
     public long incrementAndGet(T obj) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev + 1;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            long current = get(obj);
+            long next = current + 1;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
     /**
@@ -222,12 +213,12 @@
      * @return the updated value
      */
     public long decrementAndGet(T obj) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev - 1;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            long current = get(obj);
+            long next = current - 1;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
     /**
@@ -239,121 +230,27 @@
      * @return the updated value
      */
     public long addAndGet(T obj, long delta) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = prev + delta;
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            long current = get(obj);
+            long next = current + delta;
+            if (compareAndSet(obj, current, next))
+                return next;
+        }
     }
 
-    /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final long getAndAccumulate(T obj, long x,
-                                       LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final long accumulateAndGet(T obj, long x,
-                                       LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
-    }
-
-    private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
         private final long offset;
-        /**
-         * if field is protected, the subclass constructing updater, else
-         * the same as tclass
-         */
-        private final Class<?> cclass;
-        /** class holding the field */
         private final Class<T> tclass;
+        private final Class<?> cclass;
 
-        CASUpdater(final Class<T> tclass, final String fieldName,
-                   final Class<?> caller) {
+        CASUpdater(final Class<T> tclass, final String fieldName) {
             final Field field;
+            final Class<?> caller;
             final int modifiers;
             try {
                 field = tclass.getDeclaredField(fieldName); // android-changed
+                caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
@@ -362,128 +259,92 @@
                 // ClassLoader ccl = caller.getClassLoader();
                 // if ((ccl != null) && (ccl != cl) &&
                 //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                 // }
                 // END android-removed
             // BEGIN android-removed
             // } catch (PrivilegedActionException pae) {
-            //     throw new RuntimeException(pae.getException());
+            //    throw new RuntimeException(pae.getException());
             // END android-removed
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
 
-            if (field.getType() != long.class)
+            Class<?> fieldt = field.getType();
+            if (fieldt != long.class)
                 throw new IllegalArgumentException("Must be long type");
 
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
-            this.offset = U.objectFieldOffset(field);
+            offset = unsafe.objectFieldOffset(field);
         }
 
-        /**
-         * Checks that target argument is instance of cclass.  On
-         * failure, throws cause.
-         */
-        private final void accessCheck(T obj) {
-            if (!cclass.isInstance(obj))
-                throwAccessCheckException(obj);
-        }
-
-        /**
-         * Throws access exception if accessCheck failed due to
-         * protected access, else ClassCastException.
-         */
-        private final void throwAccessCheckException(T obj) {
-            if (cclass == tclass)
+        private void fullCheck(T obj) {
+            if (!tclass.isInstance(obj))
                 throw new ClassCastException();
-            else
-                throw new RuntimeException(
-                    new IllegalAccessException(
-                        "Class " +
-                        cclass.getName() +
-                        " can not access a protected member of class " +
-                        tclass.getName() +
-                        " using an instance of " +
-                        obj.getClass().getName()));
+            if (cclass != null)
+                ensureProtectedAccess(obj);
         }
 
-        public final boolean compareAndSet(T obj, long expect, long update) {
-            accessCheck(obj);
-            return U.compareAndSwapLong(obj, offset, expect, update);
+        public boolean compareAndSet(T obj, long expect, long update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.compareAndSwapLong(obj, offset, expect, update);
         }
 
-        public final boolean weakCompareAndSet(T obj, long expect, long update) {
-            accessCheck(obj);
-            return U.compareAndSwapLong(obj, offset, expect, update);
+        public boolean weakCompareAndSet(T obj, long expect, long update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.compareAndSwapLong(obj, offset, expect, update);
         }
 
-        public final void set(T obj, long newValue) {
-            accessCheck(obj);
-            U.putLongVolatile(obj, offset, newValue);
+        public void set(T obj, long newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            unsafe.putLongVolatile(obj, offset, newValue);
         }
 
-        public final void lazySet(T obj, long newValue) {
-            accessCheck(obj);
-            U.putOrderedLong(obj, offset, newValue);
+        public void lazySet(T obj, long newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            unsafe.putOrderedLong(obj, offset, newValue);
         }
 
-        public final long get(T obj) {
-            accessCheck(obj);
-            return U.getLongVolatile(obj, offset);
+        public long get(T obj) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+            return unsafe.getLongVolatile(obj, offset);
         }
 
-        public final long getAndSet(T obj, long newValue) {
-            accessCheck(obj);
-            return U.getAndSetLong(obj, offset, newValue);
-        }
-
-        public final long getAndAdd(T obj, long delta) {
-            accessCheck(obj);
-            return U.getAndAddLong(obj, offset, delta);
-        }
-
-        public final long getAndIncrement(T obj) {
-            return getAndAdd(obj, 1);
-        }
-
-        public final long getAndDecrement(T obj) {
-            return getAndAdd(obj, -1);
-        }
-
-        public final long incrementAndGet(T obj) {
-            return getAndAdd(obj, 1) + 1;
-        }
-
-        public final long decrementAndGet(T obj) {
-            return getAndAdd(obj, -1) - 1;
-        }
-
-        public final long addAndGet(T obj, long delta) {
-            return getAndAdd(obj, delta) + delta;
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException(
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
         }
     }
 
-    private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private final long offset;
-        /**
-         * if field is protected, the subclass constructing updater, else
-         * the same as tclass
-         */
-        private final Class<?> cclass;
-        /** class holding the field */
-        private final Class<T> tclass;
 
-        LockedUpdater(final Class<T> tclass, final String fieldName,
-                      final Class<?> caller) {
+    private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
+        private final long offset;
+        private final Class<T> tclass;
+        private final Class<?> cclass;
+
+        LockedUpdater(final Class<T> tclass, final String fieldName) {
             Field field = null;
+            Class<?> caller = null;
             int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName); // android-changed
+                caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
@@ -492,7 +353,7 @@
                 // ClassLoader ccl = caller.getClassLoader();
                 // if ((ccl != null) && (ccl != cl) &&
                 //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                 // }
                 // END android-removed
             // BEGIN android-removed
@@ -503,76 +364,73 @@
                 throw new RuntimeException(ex);
             }
 
-            if (field.getType() != long.class)
+            Class<?> fieldt = field.getType();
+            if (fieldt != long.class)
                 throw new IllegalArgumentException("Must be long type");
 
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
-            this.offset = U.objectFieldOffset(field);
+            offset = unsafe.objectFieldOffset(field);
         }
 
-        /**
-         * Checks that target argument is instance of cclass.  On
-         * failure, throws cause.
-         */
-        private final void accessCheck(T obj) {
-            if (!cclass.isInstance(obj))
-                throw accessCheckException(obj);
+        private void fullCheck(T obj) {
+            if (!tclass.isInstance(obj))
+                throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
         }
 
-        /**
-         * Returns access exception if accessCheck failed due to
-         * protected access, else ClassCastException.
-         */
-        private final RuntimeException accessCheckException(T obj) {
-            if (cclass == tclass)
-                return new ClassCastException();
-            else
-                return new RuntimeException(
-                    new IllegalAccessException(
-                        "Class " +
-                        cclass.getName() +
-                        " can not access a protected member of class " +
-                        tclass.getName() +
-                        " using an instance of " +
-                        obj.getClass().getName()));
-        }
-
-        public final boolean compareAndSet(T obj, long expect, long update) {
-            accessCheck(obj);
+        public boolean compareAndSet(T obj, long expect, long update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized (this) {
-                long v = U.getLong(obj, offset);
+                long v = unsafe.getLong(obj, offset);
                 if (v != expect)
                     return false;
-                U.putLong(obj, offset, update);
+                unsafe.putLong(obj, offset, update);
                 return true;
             }
         }
 
-        public final boolean weakCompareAndSet(T obj, long expect, long update) {
+        public boolean weakCompareAndSet(T obj, long expect, long update) {
             return compareAndSet(obj, expect, update);
         }
 
-        public final void set(T obj, long newValue) {
-            accessCheck(obj);
+        public void set(T obj, long newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized (this) {
-                U.putLong(obj, offset, newValue);
+                unsafe.putLong(obj, offset, newValue);
             }
         }
 
-        public final void lazySet(T obj, long newValue) {
+        public void lazySet(T obj, long newValue) {
             set(obj, newValue);
         }
 
-        public final long get(T obj) {
-            accessCheck(obj);
+        public long get(T obj) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized (this) {
-                return U.getLong(obj, offset);
+                return unsafe.getLong(obj, offset);
             }
         }
+
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException(
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
+        }
     }
 
     // BEGIN android-removed
@@ -581,13 +439,13 @@
     //  * classloader's delegation chain.
     //  * Equivalent to the inaccessible: first.isAncestor(second).
     //  */
-    // static boolean isAncestor(ClassLoader first, ClassLoader second) {
+    // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
     //     ClassLoader acl = first;
     //     do {
     //         acl = acl.getParent();
     //         if (second == acl) {
     //             return true;
-    //         }
+    //        }
     //     } while (acl != null);
     //     return false;
     // }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index d11be10..18d148f 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -91,7 +91,7 @@
      * @param newReference the new value for the reference
      * @param expectedMark the expected value of the mark
      * @param newMark the new value for the mark
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean weakCompareAndSet(V       expectedReference,
                                      V       newReference,
@@ -111,7 +111,7 @@
      * @param newReference the new value for the reference
      * @param expectedMark the expected value of the mark
      * @param newMark the new value for the mark
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean compareAndSet(V       expectedReference,
                                  V       newReference,
@@ -149,7 +149,7 @@
      *
      * @param expectedReference the expected value of the reference
      * @param newMark the new value for the mark
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean attemptMark(V expectedReference, boolean newMark) {
         Pair<V> current = pair;
@@ -161,18 +161,23 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
-    static {
-        try {
-            PAIR = U.objectFieldOffset
-                (AtomicMarkableReference.class.getDeclaredField("pair"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long pairOffset =
+        objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class);
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+    }
+
+    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;
+        }
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index c3a5ede..7ea6066 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -6,8 +6,7 @@
 
 package java.util.concurrent.atomic;
 
-import java.util.function.BinaryOperator;
-import java.util.function.UnaryOperator;
+import sun.misc.Unsafe;
 
 /**
  * An object reference that may be updated atomically. See the {@link
@@ -20,16 +19,14 @@
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long valueOffset;
 
     static {
         try {
-            VALUE = U.objectFieldOffset
+            valueOffset = unsafe.objectFieldOffset
                 (AtomicReference.class.getDeclaredField("value"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+        } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile V value;
@@ -74,7 +71,7 @@
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putOrderedObject(this, VALUE, newValue);
+        unsafe.putOrderedObject(this, valueOffset, newValue);
     }
 
     /**
@@ -82,11 +79,11 @@
      * if the current value {@code ==} the expected value.
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
     }
 
     /**
@@ -99,10 +96,10 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
     }
 
     /**
@@ -111,95 +108,12 @@
      * @param newValue the new value
      * @return the previous value
      */
-    @SuppressWarnings("unchecked")
     public final V getAndSet(V newValue) {
-        return (V)U.getAndSetObject(this, VALUE, newValue);
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final V getAndUpdate(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final V updateAndGet(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the previous value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final V getAndAccumulate(V x,
-                                    BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the current value with the results of
-     * applying the given function to the current and given values,
-     * returning the updated value. The function should be
-     * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final V accumulateAndGet(V x,
-                                    BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        while (true) {
+            V x = get();
+            if (compareAndSet(x, newValue))
+                return x;
+        }
     }
 
     /**
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index f5596e8..052b839 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -6,10 +6,9 @@
 
 package java.util.concurrent.atomic;
 
-import java.lang.reflect.Array;
 import java.util.Arrays;
-import java.util.function.BinaryOperator;
-import java.util.function.UnaryOperator;
+import java.lang.reflect.Array;
+import sun.misc.Unsafe;
 
 /**
  * An array of object references in which elements may be updated
@@ -23,22 +22,23 @@
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     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 Unsafe unsafe;
+    private static final int base;
+    private static final int shift;
+    private static final long arrayFieldOffset;
     private final Object[] array; // must have exact type Object[]
 
     static {
         try {
-            ARRAY = U.objectFieldOffset
+            unsafe = Unsafe.getUnsafe();
+            arrayFieldOffset = unsafe.objectFieldOffset
                 (AtomicReferenceArray.class.getDeclaredField("array"));
-            ABASE = U.arrayBaseOffset(Object[].class);
-            int scale = U.arrayIndexScale(Object[].class);
+            base = unsafe.arrayBaseOffset(Object[].class);
+            int scale = unsafe.arrayIndexScale(Object[].class);
             if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
+                throw new Error("data type scale not a power of two");
+            shift = 31 - Integer.numberOfLeadingZeros(scale);
+        } catch (Exception e) {
             throw new Error(e);
         }
     }
@@ -51,7 +51,7 @@
     }
 
     private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
+        return ((long) i << shift) + base;
     }
 
     /**
@@ -97,7 +97,7 @@
 
     @SuppressWarnings("unchecked")
     private E getRaw(long offset) {
-        return (E) U.getObjectVolatile(array, offset);
+        return (E) unsafe.getObjectVolatile(array, offset);
     }
 
     /**
@@ -107,7 +107,7 @@
      * @param newValue the new value
      */
     public final void set(int i, E newValue) {
-        U.putObjectVolatile(array, checkedByteOffset(i), newValue);
+        unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -118,7 +118,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putOrderedObject(array, checkedByteOffset(i), newValue);
+        unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
     }
 
     /**
@@ -129,9 +129,13 @@
      * @param newValue the new value
      * @return the previous value
      */
-    @SuppressWarnings("unchecked")
     public final E getAndSet(int i, E newValue) {
-        return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
+        long offset = checkedByteOffset(i);
+        while (true) {
+            E current = getRaw(offset);
+            if (compareAndSetRaw(offset, current, newValue))
+                return current;
+        }
     }
 
     /**
@@ -141,7 +145,7 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that
+     * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, E expect, E update) {
@@ -149,7 +153,7 @@
     }
 
     private boolean compareAndSetRaw(long offset, E expect, E update) {
-        return U.compareAndSwapObject(array, offset, expect, update);
+        return unsafe.compareAndSwapObject(array, offset, expect, update);
     }
 
     /**
@@ -163,107 +167,13 @@
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, E expect, E update) {
         return compareAndSet(i, expect, update);
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
-     *
-     * @param i the index
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final E getAndAccumulate(int i, E x,
-                                    BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
-     *
-     * @param i the index
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final E accumulateAndGet(int i, E x,
-                                    BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
-    }
-
-    /**
      * Returns the String representation of the current values of array.
      * @return the String representation of the current values of array
      */
@@ -284,20 +194,17 @@
 
     /**
      * Reconstitutes the instance 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 {
+        throws java.io.IOException, ClassNotFoundException,
+        java.io.InvalidObjectException {
         // Note: This must be changed if any additional fields are defined
         Object a = s.readFields().get("array", null);
         if (a == null || !a.getClass().isArray())
             throw new java.io.InvalidObjectException("Not array type");
         if (a.getClass() != Object[].class)
             a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
-        U.putObjectVolatile(this, ARRAY, a);
+        unsafe.putObjectVolatile(this, arrayFieldOffset, a);
     }
 
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 1dc2eb9..13ad3eb 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -7,15 +7,9 @@
 package java.util.concurrent.atomic;
 
 import dalvik.system.VMStack; // android-added
+import sun.misc.Unsafe;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.function.BinaryOperator;
-import java.util.function.UnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -25,7 +19,7 @@
  * independently subject to atomic updates. For example, a tree node
  * might be declared as
  *
- * <pre> {@code
+ *  <pre> {@code
  * class Node {
  *   private volatile Node left, right;
  *
@@ -66,19 +60,17 @@
      * @param <U> the type of instances of tclass
      * @param <W> the type of instances of vclass
      * @return the updater
-     * @throws ClassCastException if the field is of the wrong type
-     * @throws IllegalArgumentException if the field is not volatile
+     * @throws IllegalArgumentException if the field is not a volatile reference type
      * @throws RuntimeException with a nested reflection-based
      * exception if the class does not hold field or is the wrong type,
      * or the field is inaccessible to the caller according to Java language
      * access control
      */
-    @CallerSensitive
     public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
                                                                     Class<W> vclass,
                                                                     String fieldName) {
         return new AtomicReferenceFieldUpdaterImpl<U,W>
-            (tclass, vclass, fieldName, VMStack.getStackClass1()); // android-changed
+            (tclass, vclass, fieldName);
     }
 
     /**
@@ -97,7 +89,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public abstract boolean compareAndSet(T obj, V expect, V update);
 
@@ -115,7 +107,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
 
@@ -157,116 +149,20 @@
      * @return the previous value
      */
     public V getAndSet(T obj, V newValue) {
-        V prev;
-        do {
-            prev = get(obj);
-        } while (!compareAndSet(obj, prev, newValue));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the previous value
-     * @since 1.8
-     */
-    public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
-     *
-     * @param obj An object whose field to get and set
-     * @param updateFunction a side-effect-free function
-     * @return the updated value
-     * @since 1.8
-     */
-    public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get(obj);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the previous value
-     * @since 1.8
-     */
-    public final V getAndAccumulate(T obj, V x,
-                                    BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return prev;
-    }
-
-    /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
-     *
-     * @param obj An object whose field to get and set
-     * @param x the update value
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @return the updated value
-     * @since 1.8
-     */
-    public final V accumulateAndGet(T obj, V x,
-                                    BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get(obj);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(obj, prev, next));
-        return next;
+        for (;;) {
+            V current = get(obj);
+            if (compareAndSet(obj, current, newValue))
+                return current;
+        }
     }
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
         private final long offset;
-        /**
-         * if field is protected, the subclass constructing updater, else
-         * the same as tclass
-         */
-        private final Class<?> cclass;
-        /** class holding the field */
         private final Class<T> tclass;
-        /** field value type */
         private final Class<V> vclass;
+        private final Class<?> cclass;
 
         /*
          * Internal type checks within all update methods contain
@@ -281,25 +177,26 @@
          */
 
         AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
-                                        final Class<V> vclass,
-                                        final String fieldName,
-                                        final Class<?> caller) {
+                                        Class<V> vclass,
+                                        final String fieldName) {
             final Field field;
             final Class<?> fieldClass;
+            final Class<?> caller;
             final int modifiers;
             try {
                 field = tclass.getDeclaredField(fieldName); // android-changed
+                caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
-                // BEGIN android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // ClassLoader cl = tclass.getClassLoader();
-                // ClassLoader ccl = caller.getClassLoader();
-                // if ((ccl != null) && (ccl != cl) &&
-                //     ((cl == null) || !isAncestor(cl, ccl))) {
-                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // }
-                // END android-removed
+            // BEGIN android-removed
+            //     sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+            //         caller, tclass, null, modifiers);
+            //     ClassLoader cl = tclass.getClassLoader();
+            //     ClassLoader ccl = caller.getClassLoader();
+            //     if ((ccl != null) && (ccl != cl) &&
+            //         ((cl == null) || !isAncestor(cl, ccl))) {
+            //       sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+            //     }
+            // END android-removed
                 fieldClass = field.getType();
             // BEGIN android-removed
             // } catch (PrivilegedActionException pae) {
@@ -311,16 +208,18 @@
 
             if (vclass != fieldClass)
                 throw new ClassCastException();
-            if (vclass.isPrimitive())
-                throw new IllegalArgumentException("Must be reference type");
 
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
-            this.vclass = vclass;
-            this.offset = U.objectFieldOffset(field);
+            if (vclass == Object.class)
+                this.vclass = null;
+            else
+                this.vclass = vclass;
+            offset = unsafe.objectFieldOffset(field);
         }
 
         // BEGIN android-removed
@@ -329,90 +228,87 @@
         //  * classloader's delegation chain.
         //  * Equivalent to the inaccessible: first.isAncestor(second).
         //  */
+        //
         // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
         //     ClassLoader acl = first;
         //     do {
         //         acl = acl.getParent();
         //         if (second == acl) {
         //             return true;
-        //         }
+        //        }
         //     } while (acl != null);
         //     return false;
         // }
         // END android-removed
 
-        /**
-         * Checks that target argument is instance of cclass.  On
-         * failure, throws cause.
-         */
-        private final void accessCheck(T obj) {
-            if (!cclass.isInstance(obj))
-                throwAccessCheckException(obj);
-        }
-
-        /**
-         * Throws access exception if accessCheck failed due to
-         * protected access, else ClassCastException.
-         */
-        private final void throwAccessCheckException(T obj) {
-            if (cclass == tclass)
+        void targetCheck(T obj) {
+            if (!tclass.isInstance(obj))
                 throw new ClassCastException();
-            else
-                throw new RuntimeException(
-                    new IllegalAccessException(
-                        "Class " +
-                        cclass.getName() +
-                        " can not access a protected member of class " +
-                        tclass.getName() +
-                        " using an instance of " +
-                        obj.getClass().getName()));
+            if (cclass != null)
+                ensureProtectedAccess(obj);
         }
 
-        private final void valueCheck(V v) {
-            if (v != null && !(vclass.isInstance(v)))
-                throwCCE();
+        void updateCheck(T obj, V update) {
+            if (!tclass.isInstance(obj) ||
+                (update != null && vclass != null && !vclass.isInstance(update)))
+                throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
         }
 
-        static void throwCCE() {
-            throw new ClassCastException();
+        public boolean compareAndSet(T obj, V expect, V update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (update != null && vclass != null &&
+                 vclass != update.getClass()))
+                updateCheck(obj, update);
+            return unsafe.compareAndSwapObject(obj, offset, expect, update);
         }
 
-        public final boolean compareAndSet(T obj, V expect, V update) {
-            accessCheck(obj);
-            valueCheck(update);
-            return U.compareAndSwapObject(obj, offset, expect, update);
-        }
-
-        public final boolean weakCompareAndSet(T obj, V expect, V update) {
+        public boolean weakCompareAndSet(T obj, V expect, V update) {
             // same implementation as strong form for now
-            accessCheck(obj);
-            valueCheck(update);
-            return U.compareAndSwapObject(obj, offset, expect, update);
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (update != null && vclass != null &&
+                 vclass != update.getClass()))
+                updateCheck(obj, update);
+            return unsafe.compareAndSwapObject(obj, offset, expect, update);
         }
 
-        public final void set(T obj, V newValue) {
-            accessCheck(obj);
-            valueCheck(newValue);
-            U.putObjectVolatile(obj, offset, newValue);
+        public void set(T obj, V newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (newValue != null && vclass != null &&
+                 vclass != newValue.getClass()))
+                updateCheck(obj, newValue);
+            unsafe.putObjectVolatile(obj, offset, newValue);
         }
 
-        public final void lazySet(T obj, V newValue) {
-            accessCheck(obj);
-            valueCheck(newValue);
-            U.putOrderedObject(obj, offset, newValue);
+        public void lazySet(T obj, V newValue) {
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (newValue != null && vclass != null &&
+                 vclass != newValue.getClass()))
+                updateCheck(obj, newValue);
+            unsafe.putOrderedObject(obj, offset, newValue);
         }
 
         @SuppressWarnings("unchecked")
-        public final V get(T obj) {
-            accessCheck(obj);
-            return (V)U.getObjectVolatile(obj, offset);
+        public V get(T obj) {
+            if (obj == null || obj.getClass() != tclass || cclass != null)
+                targetCheck(obj);
+            return (V)unsafe.getObjectVolatile(obj, offset);
         }
 
-        @SuppressWarnings("unchecked")
-        public final V getAndSet(T obj, V newValue) {
-            accessCheck(obj);
-            valueCheck(newValue);
-            return (V)U.getAndSetObject(obj, offset, newValue);
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException(
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
         }
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index 69fab23..1449856 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -91,7 +91,7 @@
      * @param newReference the new value for the reference
      * @param expectedStamp the expected value of the stamp
      * @param newStamp the new value for the stamp
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean weakCompareAndSet(V   expectedReference,
                                      V   newReference,
@@ -111,7 +111,7 @@
      * @param newReference the new value for the reference
      * @param expectedStamp the expected value of the stamp
      * @param newStamp the new value for the stamp
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean compareAndSet(V   expectedReference,
                                  V   newReference,
@@ -149,7 +149,7 @@
      *
      * @param expectedReference the expected value of the reference
      * @param newStamp the new value for the stamp
-     * @return {@code true} if successful
+     * @return true if successful
      */
     public boolean attemptStamp(V expectedReference, int newStamp) {
         Pair<V> current = pair;
@@ -161,18 +161,23 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
-    static {
-        try {
-            PAIR = U.objectFieldOffset
-                (AtomicStampedReference.class.getDeclaredField("pair"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long pairOffset =
+        objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+    }
+
+    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;
+        }
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java b/luni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java
deleted file mode 100644
index 1ea088d..0000000
--- a/luni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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.atomic;
-
-import java.io.Serializable;
-import java.util.function.DoubleBinaryOperator;
-
-/**
- * One or more variables that together maintain a running {@code double}
- * value updated using a supplied function.  When updates (method
- * {@link #accumulate}) are contended across threads, the set of variables
- * may grow dynamically to reduce contention.  Method {@link #get}
- * (or, equivalently, {@link #doubleValue}) returns the current value
- * across the variables maintaining updates.
- *
- * <p>This class is usually preferable to alternatives when multiple
- * threads update a common value that is used for purposes such as
- * summary statistics that are frequently updated but less frequently
- * read.
- *
- * <p>The supplied accumulator function should be side-effect-free,
- * since it may be re-applied when attempted updates fail due to
- * contention among threads. The function is applied with the current
- * value as its first argument, and the given update as the second
- * argument.  For example, to maintain a running maximum value, you
- * could supply {@code Double::max} along with {@code
- * Double.NEGATIVE_INFINITY} as the identity. The order of
- * accumulation within or across threads is not guaranteed. Thus, this
- * class may not be applicable if numerical stability is required,
- * especially when combining values of substantially different orders
- * of magnitude.
- *
- * <p>Class {@link DoubleAdder} provides analogs of the functionality
- * of this class for the common special case of maintaining sums.  The
- * call {@code new DoubleAdder()} is equivalent to {@code new
- * DoubleAccumulator((x, y) -> x + y, 0.0)}.
- *
- * <p>This class extends {@link Number}, but does <em>not</em> define
- * methods such as {@code equals}, {@code hashCode} and {@code
- * compareTo} because instances are expected to be mutated, and so are
- * not useful as collection keys.
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class DoubleAccumulator extends Striped64 implements Serializable {
-    private static final long serialVersionUID = 7249069246863182397L;
-
-    private final DoubleBinaryOperator function;
-    private final long identity; // use long representation
-
-    /**
-     * Creates a new instance using the given accumulator function
-     * and identity element.
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @param identity identity (initial value) for the accumulator function
-     */
-    public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
-                             double identity) {
-        this.function = accumulatorFunction;
-        base = this.identity = Double.doubleToRawLongBits(identity);
-    }
-
-    /**
-     * Updates with the given value.
-     *
-     * @param x the value
-     */
-    public void accumulate(double x) {
-        Cell[] as; long b, v, r; int m; Cell a;
-        if ((as = cells) != null ||
-            (r = Double.doubleToRawLongBits
-             (function.applyAsDouble
-              (Double.longBitsToDouble(b = base), x))) != b  && !casBase(b, r)) {
-            boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended =
-                  (r = Double.doubleToRawLongBits
-                   (function.applyAsDouble
-                    (Double.longBitsToDouble(v = a.value), x))) == v ||
-                  a.cas(v, r)))
-                doubleAccumulate(x, function, uncontended);
-        }
-    }
-
-    /**
-     * Returns the current value.  The returned value is <em>NOT</em>
-     * an atomic snapshot; invocation in the absence of concurrent
-     * updates returns an accurate result, but concurrent updates that
-     * occur while the value is being calculated might not be
-     * incorporated.
-     *
-     * @return the current value
-     */
-    public double get() {
-        Cell[] as = cells;
-        double result = Double.longBitsToDouble(base);
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    result = function.applyAsDouble
-                        (result, Double.longBitsToDouble(a.value));
-        }
-        return result;
-    }
-
-    /**
-     * Resets variables maintaining updates to the identity value.
-     * This method may be a useful alternative to creating a new
-     * updater, but is only effective if there are no concurrent
-     * updates.  Because this method is intrinsically racy, it should
-     * only be used when it is known that no threads are concurrently
-     * updating.
-     */
-    public void reset() {
-        Cell[] as = cells;
-        base = identity;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset(identity);
-        }
-    }
-
-    /**
-     * Equivalent in effect to {@link #get} followed by {@link
-     * #reset}. This method may apply for example during quiescent
-     * points between multithreaded computations.  If there are
-     * updates concurrent with this method, the returned value is
-     * <em>not</em> guaranteed to be the final value occurring before
-     * the reset.
-     *
-     * @return the value before reset
-     */
-    public double getThenReset() {
-        Cell[] as = cells;
-        double result = Double.longBitsToDouble(base);
-        base = identity;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    double v = Double.longBitsToDouble(a.value);
-                    a.reset(identity);
-                    result = function.applyAsDouble(result, v);
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the String representation of the current value.
-     * @return the String representation of the current value
-     */
-    public String toString() {
-        return Double.toString(get());
-    }
-
-    /**
-     * Equivalent to {@link #get}.
-     *
-     * @return the current value
-     */
-    public double doubleValue() {
-        return get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as a {@code long}
-     * after a narrowing primitive conversion.
-     */
-    public long longValue() {
-        return (long)get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as an {@code int}
-     * after a narrowing primitive conversion.
-     */
-    public int intValue() {
-        return (int)get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as a {@code float}
-     * after a narrowing primitive conversion.
-     */
-    public float floatValue() {
-        return (float)get();
-    }
-
-    /**
-     * Serialization proxy, used to avoid reference to the non-public
-     * Striped64 superclass in serialized forms.
-     * @serial include
-     */
-    private static class SerializationProxy implements Serializable {
-        private static final long serialVersionUID = 7249069246863182397L;
-
-        /**
-         * The current value returned by get().
-         * @serial
-         */
-        private final double value;
-
-        /**
-         * The function used for updates.
-         * @serial
-         */
-        private final DoubleBinaryOperator function;
-
-        /**
-         * The identity value, represented as a long, as converted by
-         * {@link Double#doubleToRawLongBits}.  The original identity
-         * can be recovered using {@link Double#longBitsToDouble}.
-         * @serial
-         */
-        private final long identity;
-
-        SerializationProxy(double value,
-                           DoubleBinaryOperator function,
-                           long identity) {
-            this.value = value;
-            this.function = function;
-            this.identity = identity;
-        }
-
-        /**
-         * Returns a {@code DoubleAccumulator} object with initial state
-         * held by this proxy.
-         *
-         * @return a {@code DoubleAccumulator} object with initial state
-         * held by this proxy
-         */
-        private Object readResolve() {
-            double d = Double.longBitsToDouble(identity);
-            DoubleAccumulator a = new DoubleAccumulator(function, d);
-            a.base = Double.doubleToRawLongBits(value);
-            return a;
-        }
-    }
-
-    /**
-     * Returns a
-     * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
-     * SerializationProxy</a>
-     * representing the state of this instance.
-     *
-     * @return a {@link SerializationProxy}
-     * representing the state of this instance
-     */
-    private Object writeReplace() {
-        return new SerializationProxy(get(), function, identity);
-    }
-
-    /**
-     * @param s the stream
-     * @throws java.io.InvalidObjectException always
-     */
-    private void readObject(java.io.ObjectInputStream s)
-        throws java.io.InvalidObjectException {
-        throw new java.io.InvalidObjectException("Proxy required");
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java b/luni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java
deleted file mode 100644
index 94844d5..0000000
--- a/luni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * 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.atomic;
-
-import java.io.Serializable;
-
-/**
- * One or more variables that together maintain an initially zero
- * {@code double} sum.  When updates (method {@link #add}) are
- * contended across threads, the set of variables may grow dynamically
- * to reduce contention.  Method {@link #sum} (or, equivalently {@link
- * #doubleValue}) returns the current total combined across the
- * variables maintaining the sum. The order of accumulation within or
- * across threads is not guaranteed. Thus, this class may not be
- * applicable if numerical stability is required, especially when
- * combining values of substantially different orders of magnitude.
- *
- * <p>This class is usually preferable to alternatives when multiple
- * threads update a common value that is used for purposes such as
- * summary statistics that are frequently updated but less frequently
- * read.
- *
- * <p>This class extends {@link Number}, but does <em>not</em> define
- * methods such as {@code equals}, {@code hashCode} and {@code
- * compareTo} because instances are expected to be mutated, and so are
- * not useful as collection keys.
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class DoubleAdder extends Striped64 implements Serializable {
-    private static final long serialVersionUID = 7249069246863182397L;
-
-    /*
-     * Note that we must use "long" for underlying representations,
-     * because there is no compareAndSet for double, due to the fact
-     * that the bitwise equals used in any CAS implementation is not
-     * the same as double-precision equals.  However, we use CAS only
-     * to detect and alleviate contention, for which bitwise equals
-     * works best anyway. In principle, the long/double conversions
-     * used here should be essentially free on most platforms since
-     * they just re-interpret bits.
-     */
-
-    /**
-     * Creates a new adder with initial sum of zero.
-     */
-    public DoubleAdder() {
-    }
-
-    /**
-     * Adds the given value.
-     *
-     * @param x the value to add
-     */
-    public void add(double x) {
-        Cell[] as; long b, v; int m; Cell a;
-        if ((as = cells) != null ||
-            !casBase(b = base,
-                     Double.doubleToRawLongBits
-                     (Double.longBitsToDouble(b) + x))) {
-            boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended = a.cas(v = a.value,
-                                      Double.doubleToRawLongBits
-                                      (Double.longBitsToDouble(v) + x))))
-                doubleAccumulate(x, null, uncontended);
-        }
-    }
-
-    /**
-     * Returns the current sum.  The returned value is <em>NOT</em> an
-     * atomic snapshot; invocation in the absence of concurrent
-     * updates returns an accurate result, but concurrent updates that
-     * occur while the sum is being calculated might not be
-     * incorporated.  Also, because floating-point arithmetic is not
-     * strictly associative, the returned result need not be identical
-     * to the value that would be obtained in a sequential series of
-     * updates to a single variable.
-     *
-     * @return the sum
-     */
-    public double sum() {
-        Cell[] as = cells;
-        double sum = Double.longBitsToDouble(base);
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    sum += Double.longBitsToDouble(a.value);
-        }
-        return sum;
-    }
-
-    /**
-     * Resets variables maintaining the sum to zero.  This method may
-     * be a useful alternative to creating a new adder, but is only
-     * effective if there are no concurrent updates.  Because this
-     * method is intrinsically racy, it should only be used when it is
-     * known that no threads are concurrently updating.
-     */
-    public void reset() {
-        Cell[] as = cells;
-        base = 0L; // relies on fact that double 0 must have same rep as long
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset();
-        }
-    }
-
-    /**
-     * Equivalent in effect to {@link #sum} followed by {@link
-     * #reset}. This method may apply for example during quiescent
-     * points between multithreaded computations.  If there are
-     * updates concurrent with this method, the returned value is
-     * <em>not</em> guaranteed to be the final value occurring before
-     * the reset.
-     *
-     * @return the sum
-     */
-    public double sumThenReset() {
-        Cell[] as = cells;
-        double sum = Double.longBitsToDouble(base);
-        base = 0L;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    long v = a.value;
-                    a.reset();
-                    sum += Double.longBitsToDouble(v);
-                }
-            }
-        }
-        return sum;
-    }
-
-    /**
-     * Returns the String representation of the {@link #sum}.
-     * @return the String representation of the {@link #sum}
-     */
-    public String toString() {
-        return Double.toString(sum());
-    }
-
-    /**
-     * Equivalent to {@link #sum}.
-     *
-     * @return the sum
-     */
-    public double doubleValue() {
-        return sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as a {@code long} after a
-     * narrowing primitive conversion.
-     */
-    public long longValue() {
-        return (long)sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as an {@code int} after a
-     * narrowing primitive conversion.
-     */
-    public int intValue() {
-        return (int)sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as a {@code float}
-     * after a narrowing primitive conversion.
-     */
-    public float floatValue() {
-        return (float)sum();
-    }
-
-    /**
-     * Serialization proxy, used to avoid reference to the non-public
-     * Striped64 superclass in serialized forms.
-     * @serial include
-     */
-    private static class SerializationProxy implements Serializable {
-        private static final long serialVersionUID = 7249069246863182397L;
-
-        /**
-         * The current value returned by sum().
-         * @serial
-         */
-        private final double value;
-
-        SerializationProxy(DoubleAdder a) {
-            value = a.sum();
-        }
-
-        /**
-         * Returns a {@code DoubleAdder} object with initial state
-         * held by this proxy.
-         *
-         * @return a {@code DoubleAdder} object with initial state
-         * held by this proxy
-         */
-        private Object readResolve() {
-            DoubleAdder a = new DoubleAdder();
-            a.base = Double.doubleToRawLongBits(value);
-            return a;
-        }
-    }
-
-    /**
-     * Returns a
-     * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAdder.SerializationProxy">
-     * SerializationProxy</a>
-     * representing the state of this instance.
-     *
-     * @return a {@link SerializationProxy}
-     * representing the state of this instance
-     */
-    private Object writeReplace() {
-        return new SerializationProxy(this);
-    }
-
-    /**
-     * @param s the stream
-     * @throws java.io.InvalidObjectException always
-     */
-    private void readObject(java.io.ObjectInputStream s)
-        throws java.io.InvalidObjectException {
-        throw new java.io.InvalidObjectException("Proxy required");
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/Fences.java b/luni/src/main/java/java/util/concurrent/atomic/Fences.java
new file mode 100644
index 0000000..d907faf
--- /dev/null
+++ b/luni/src/main/java/java/util/concurrent/atomic/Fences.java
@@ -0,0 +1,538 @@
+/*
+ * 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.atomic;
+
+/**
+ * A set of methods providing fine-grained control over happens-before
+ * and synchronization order relations among reads and/or writes.  The
+ * methods of this class are designed for use in uncommon situations
+ * where declaring variables {@code volatile} or {@code final}, using
+ * instances of atomic classes, using {@code synchronized} blocks or
+ * methods, or using other synchronization facilities are not possible
+ * or do not provide the desired control.
+ *
+ * <p><b>Memory Ordering.</b> There are three methods for controlling
+ * ordering relations among memory accesses (i.e., reads and
+ * writes). Method {@code orderWrites} is typically used to enforce
+ * order between two writes, and {@code orderAccesses} between a write
+ * and a read.  Method {@code orderReads} is used to enforce order
+ * between two reads with respect to other {@code orderWrites} and/or
+ * {@code orderAccesses} invocations.  The formally specified
+ * properties of these methods described below provide
+ * platform-independent guarantees that are honored by all levels of a
+ * platform (compilers, systems, processors).  The use of these
+ * methods may result in the suppression of otherwise valid compiler
+ * transformations and optimizations that could visibly violate the
+ * specified orderings, and may or may not entail the use of
+ * processor-level "memory barrier" instructions.
+ *
+ * <p>Each ordering method accepts a {@code ref} argument, and
+ * controls ordering among accesses with respect to this reference.
+ * Invocations must be placed <em>between</em> accesses performed in
+ * expression evaluations and assignment statements to control the
+ * orderings of prior versus subsequent accesses appearing in program
+ * order. These methods also return their arguments to simplify
+ * correct usage in these contexts.
+ *
+ * <p>Usages of ordering methods almost always take one of the forms
+ * illustrated in the examples below.  These idioms arrange some of
+ * the ordering properties associated with {@code volatile} and
+ * related language-based constructions, but without other
+ * compile-time and runtime benefits that make language-based
+ * constructions far better choices when they are applicable.  Usages
+ * should be restricted to the control of strictly internal
+ * implementation matters inside a class or package, and must either
+ * avoid or document any consequent violations of ordering or safety
+ * properties expected by users of a class employing them.
+ *
+ * <p><b>Reachability.</b> Method {@code reachabilityFence}
+ * establishes an ordering for strong reachability (as defined in the
+ * {@link java.lang.ref} package specification) with respect to
+ * garbage collection.  Method {@code reachabilityFence} differs from
+ * the others in that it controls relations that are otherwise only
+ * implicit in a program -- the reachability conditions triggering
+ * garbage collection.  As illustrated in the sample usages below,
+ * this method is applicable only when reclamation may have visible
+ * effects, which is possible for objects with finalizers (see Section
+ * 12.6 of the Java Language Specification) that are implemented in
+ * ways that rely on ordering control for correctness.
+ *
+ * <p><b>Sample Usages</b>
+ *
+ * <p><b>Safe publication.</b> With care, method {@code orderWrites}
+ * may be used to obtain the memory safety effects of {@code final}
+ * for a field that cannot be declared as {@code final}, because its
+ * primary initialization cannot be performed in a constructor, in
+ * turn because it is used in a framework requiring that all classes
+ * have a no-argument constructor; as in:
+ *
+ * <pre> {@code
+ * class WidgetHolder {
+ *   private Widget widget;
+ *   public WidgetHolder() {}
+ *   public static WidgetHolder newWidgetHolder(Params params) {
+ *     WidgetHolder h = new WidgetHolder();
+ *     h.widget = new Widget(params);
+ *     return Fences.orderWrites(h);
+ *   }
+ * }}</pre>
+ *
+ * Here, the invocation of {@code orderWrites} ensures that the
+ * effects of the widget assignment are ordered before those of any
+ * (unknown) subsequent stores of {@code h} in other variables that
+ * make {@code h} available for use by other objects.  Initialization
+ * sequences using {@code orderWrites} require more care than those
+ * involving {@code final} fields.  When {@code final} is not used,
+ * compilers cannot help you to ensure that the field is set correctly
+ * across all usages.  You must fully initialize objects
+ * <em>before</em> the {@code orderWrites} invocation that makes
+ * references to them safe to assign to accessible variables. Further,
+ * initialization sequences must not internally "leak" the reference
+ * by using it as an argument to a callback method or adding it to a
+ * static data structure.  If less constrained usages were required,
+ * it may be possible to cope using more extensive sets of fences, or
+ * as a normally better choice, using synchronization (locking).
+ * Conversely, if it were possible to do so, the best option would be
+ * to rewrite class {@code WidgetHolder} to use {@code final}.
+ *
+ * <p>An alternative approach is to place similar mechanics in the
+ * (sole) method that makes such objects available for use by others.
+ * Here is a stripped-down example illustrating the essentials. In
+ * practice, among other changes, you would use access methods instead
+ * of a public field.
+ *
+ * <pre> {@code
+ * class AnotherWidgetHolder {
+ *   public Widget widget;
+ *   void publish(Widget w) {
+ *     this.widget = Fences.orderWrites(w);
+ *   }
+ *   // ...
+ * }}</pre>
+ *
+ * In this case, the {@code orderWrites} invocation occurs before the
+ * store making the object available. Correctness again relies on
+ * ensuring that there are no leaks prior to invoking this method, and
+ * that it really is the <em>only</em> means of accessing the
+ * published object.  This approach is not often applicable --
+ * normally you would publish objects using a thread-safe collection
+ * that itself guarantees the expected ordering relations. However, it
+ * may come into play in the construction of such classes themselves.
+ *
+ * <p><b>Safely updating fields.</b> Outside of the initialization
+ * idioms illustrated above, Fence methods ordering writes must be
+ * paired with those ordering reads. To illustrate, suppose class
+ * {@code c} contains an accessible variable {@code data} that should
+ * have been declared as {@code volatile} but wasn't:
+ *
+ * <pre> {@code
+ * class C {
+ *   Object data;  // need volatile access but not volatile
+ *   // ...
+ * }
+ *
+ * class App {
+ *   Object getData(C c) {
+ *     return Fences.orderReads(c).data;
+ *   }
+ *
+ *   void setData(C c) {
+ *     Object newValue = ...;
+ *     c.data = Fences.orderWrites(newValue);
+ *     Fences.orderAccesses(c);
+ *   }
+ *   // ...
+ * }}</pre>
+ *
+ * Method {@code getData} provides an emulation of {@code volatile}
+ * reads of (non-long/double) fields by ensuring that the read of
+ * {@code c} obtained as an argument is ordered before subsequent
+ * reads using this reference, and then performs the read of its
+ * field. Method {@code setData} provides an emulation of volatile
+ * writes, ensuring that all other relevant writes have completed,
+ * then performing the assignment, and then ensuring that the write is
+ * ordered before any other access.  These techniques may apply even
+ * when fields are not directly accessible, in which case calls to
+ * fence methods would surround calls to methods such as {@code
+ * c.getData()}.  However, these techniques cannot be applied to
+ * {@code long} or {@code double} fields because reads and writes of
+ * fields of these types are not guaranteed to be
+ * atomic. Additionally, correctness may require that all accesses of
+ * such data use these kinds of wrapper methods, which you would need
+ * to manually ensure.
+ *
+ * <p>More generally, Fence methods can be used in this way to achieve
+ * the safety properties of {@code volatile}. However their use does
+ * not necessarily guarantee the full sequential consistency
+ * properties specified in the Java Language Specification chapter 17
+ * for programs using {@code volatile}. In particular, emulation using
+ * Fence methods is not guaranteed to maintain the property that
+ * {@code volatile} operations performed by different threads are
+ * observed in the same order by all observer threads.
+ *
+ * <p><b>Acquire/Release management of threadsafe objects</b>. It may
+ * be possible to use weaker conventions for volatile-like variables
+ * when they are used to keep track of objects that fully manage their
+ * own thread-safety and synchronization.  Here, an acquiring read
+ * operation remains the same as a volatile-read, but a releasing
+ * write differs by virtue of not itself ensuring an ordering of its
+ * write with subsequent reads, because the required effects are
+ * already ensured by the referenced objects.
+ * For example:
+ *
+ * <pre> {@code
+ * class Item {
+ *   synchronized f(); // ALL methods are synchronized
+ *   // ...
+ * }
+ *
+ * class ItemHolder {
+ *   private Item item;
+ *   Item acquireItem() {
+ *     return Fences.orderReads(item);
+ *   }
+ *
+ *   void releaseItem(Item x) {
+ *     item = Fences.orderWrites(x);
+ *   }
+ *
+ *   // ...
+ * }}</pre>
+ *
+ * Because this construction avoids use of {@code orderAccesses},
+ * which is typically more costly than the other fence methods, it may
+ * result in better performance than using {@code volatile} or its
+ * emulation. However, as is the case with most applications of fence
+ * methods, correctness relies on the usage context -- here, the
+ * thread safety of {@code Item}, as well as the lack of need for full
+ * volatile semantics inside this class itself. However, the second
+ * concern means that it can be difficult to extend the {@code
+ * ItemHolder} class in this example to be more useful.
+ *
+ * <p><b>Avoiding premature finalization.</b> Finalization may occur
+ * whenever a Java Virtual Machine detects that no reference to an
+ * object will ever be stored in the heap: A garbage collector may
+ * reclaim an object even if the fields of that object are still in
+ * use, so long as the object has otherwise become unreachable. This
+ * may have surprising and undesirable effects in cases such as the
+ * following example in which the bookkeeping associated with a class
+ * is managed through array indices. Here, method {@code action}
+ * uses a {@code reachabilityFence} to ensure that the Resource
+ * object is not reclaimed before bookkeeping on an associated
+ * ExternalResource has been performed; in particular here, to ensure
+ * that the array slot holding the ExternalResource is not nulled out
+ * in method {@link Object#finalize}, which may otherwise run
+ * concurrently.
+ *
+ * <pre> {@code
+ * class Resource {
+ *   private static ExternalResource[] externalResourceArray = ...
+ *
+ *   int myIndex;
+ *   Resource(...) {
+ *     myIndex = ...
+ *     externalResourceArray[myIndex] = ...;
+ *     ...
+ *   }
+ *   protected void finalize() {
+ *     externalResourceArray[myIndex] = null;
+ *     ...
+ *   }
+ *   public void action() {
+ *     try {
+ *       // ...
+ *       int i = myIndex;
+ *       Resource.update(externalResourceArray[i]);
+ *     } finally {
+ *       Fences.reachabilityFence(this);
+ *     }
+ *   }
+ *   private static void update(ExternalResource ext) {
+ *     ext.status = ...;
+ *   }
+ * }}</pre>
+ *
+ * Here, the call to {@code reachabilityFence} is nonintuitively
+ * placed <em>after</em> the call to {@code update}, to ensure that
+ * the array slot is not nulled out by {@link Object#finalize} before
+ * the update, even if the call to {@code action} was the last use of
+ * this object. This might be the case if for example a usage in a
+ * user program had the form {@code new Resource().action();} which
+ * retains no other reference to this Resource.  While probably
+ * overkill here, {@code reachabilityFence} is placed in a {@code
+ * finally} block to ensure that it is invoked across all paths in the
+ * method.  In a method with more complex control paths, you might
+ * need further precautions to ensure that {@code reachabilityFence}
+ * is encountered along all of them.
+ *
+ * <p>It is sometimes possible to better encapsulate use of
+ * {@code reachabilityFence}. Continuing the above example, if it
+ * were OK for the call to method update to proceed even if the
+ * finalizer had already executed (nulling out slot), then you could
+ * localize use of {@code reachabilityFence}:
+ *
+ * <pre> {@code
+ * public void action2() {
+ *   // ...
+ *   Resource.update(getExternalResource());
+ * }
+ * private ExternalResource getExternalResource() {
+ *   ExternalResource ext = externalResourceArray[myIndex];
+ *   Fences.reachabilityFence(this);
+ *   return ext;
+ * }}</pre>
+ *
+ * <p>Method {@code reachabilityFence} is not required in
+ * constructions that themselves ensure reachability. For example,
+ * because objects that are locked cannot in general be reclaimed, it
+ * would suffice if all accesses of the object, in all methods of
+ * class Resource (including {@code finalize}) were enclosed in {@code
+ * synchronized (this)} blocks. (Further, such blocks must not include
+ * infinite loops, or themselves be unreachable, which fall into the
+ * corner case exceptions to the "in general" disclaimer.) However,
+ * method {@code reachabilityFence} remains a better option in cases
+ * where this approach is not as efficient, desirable, or possible;
+ * for example because it would encounter deadlock.
+ *
+ * <p><b>Formal Properties.</b>
+ *
+ * <p>Using the terminology of The Java Language Specification chapter
+ * 17, the rules governing the semantics of the methods of this class
+ * are as follows:
+ *
+ * <p>The following is still under construction.
+ *
+ * <dl>
+ *
+ *   <dt><b>[Definitions]</b>
+ *   <dd>
+ *   <ul>
+ *
+ *     <li>Define <em>sequenced(a, b)</em> to be true if <em>a</em>
+ *     occurs before <em>b</em> in <em>program order</em>.
+ *
+ *     <li>Define <em>accesses(a, p)</em> to be true if
+ *     <em>a</em> is a read or write of a field (or if an array, an
+ *     element) of the object referenced by <em>p</em>.
+ *
+ *     <li>Define <em>deeplyAccesses(a, p)</em> to be true if either
+ *     <em>accesses(a, p)</em> or <em>deeplyAccesses(a, q)</em> where
+ *     <em>q</em> is the value seen by some read <em>r</em>
+ *     such that <em>accesses(r, p)</em>.
+ *
+ *   </ul>
+ *   <dt><b>[Matching]</b>
+ *   <dd>Given:
+ *
+ *   <ul>
+ *
+ *     <li><em>p</em>, a reference to an object
+ *
+ *     <li><em>wf</em>, an invocation of {@code orderWrites(p)} or
+ *       {@code orderAccesses(p)}
+ *
+ *     <li><em>w</em>, a write of value <em>p</em>
+ *
+ *     <li> <em>rf</em>, an invocation of {@code orderReads(p)} or
+ *     {@code orderAccesses(p)}
+ *
+ *     <li> <em>r</em>, a read returning value <em>p</em>
+ *
+ *   </ul>
+ *   If:
+ *   <ul>
+ *     <li>sequenced(wf, w)
+ *     <li>read <em>r</em> sees write <em>w</em>
+ *     <li>sequenced(r, rf)
+ *   </ul>
+ *   Then:
+ *   <ul>
+ *
+ *     <li> <em>wf happens-before rf</em>
+ *
+ *     <li> <em>wf</em> precedes <em>rf</em> in the
+ *          <em>synchronization order</em>
+ *
+ *     <li> If (<em>r1</em>, <em>w1</em>) and (<em>r2</em>,
+ *     <em>w2</em>) are two pairs of reads and writes, both
+ *     respectively satisfying the above conditions for <em>p</em>,
+ *     and sequenced(r1, r2) then it is not the case that <em>w2
+ *     happens-before w1</em>.
+ *
+ *   </ul>
+ *   <dt><b>[Initial Reads]</b>
+ *   <dd>Given:
+ *
+ *   <ul>
+ *
+ *     <li><em>p</em>, a reference to an object
+ *
+ *     <li> <em>a</em>, an access where deeplyAccesses(a, p)
+ *
+ *     <li><em>wf</em>, an invocation of {@code orderWrites(p)} or
+ *       {@code orderAccesses(p)}
+ *
+ *     <li><em>w</em>, a write of value <em>p</em>
+ *
+ *     <li> <em>r</em>, a read returning value <em>p</em>
+ *
+ *     <li> <em>b</em>, an access where accesses(b, p)
+ *
+ *   </ul>
+ *   If:
+ *   <ul>
+ *     <li>sequenced(a, wf);
+ *     <li>sequenced(wf, w)
+ *     <li>read <em>r</em> sees write <em>w</em>, and
+ *         <em>r</em> is the first read by some thread
+ *         <em>t</em> that sees value <em>p</em>
+ *     <li>sequenced(r, b)
+ *   </ul>
+ *   Then:
+ *   <ul>
+ *     <li> the effects of <em>b</em> are constrained
+ *          by the relation <em>a happens-before b</em>.
+ *   </ul>
+ *  <dt><b>[orderAccesses]</b>
+ *  <dd>Given:
+ *
+ *   <ul>
+ *     <li><em>p</em>, a reference to an object
+ *     <li><em>f</em>, an invocation of {@code orderAccesses(p)}
+ *   </ul>
+ *   If:
+ *   <ul>
+ *     <li>sequenced(f, w)
+ *   </ul>
+ *
+ *    Then:
+ *
+ *   <ul>
+ *
+ *     <li> <em>f</em> is an element of the <em>synchronization order</em>.
+ *
+ *   </ul>
+ *   <dt><b>[Reachability]</b>
+ *   <dd>Given:
+ *
+ *   <ul>
+ *
+ *     <li><em>p</em>, a reference to an object
+ *
+ *     <li><em>f</em>, an invocation of {@code reachabilityFence(p)}
+ *
+ *     <li><em>a</em>, an access where accesses(a, p)
+ *
+ *     <li><em>b</em>, an action (by a garbage collector) taking
+ *     the form of an invocation of {@code
+ *     p.finalize()} or of enqueuing any {@link
+ *     java.lang.ref.Reference} constructed with argument <em>p</em>
+ *
+ *   </ul>
+ *
+ *   If:
+ *   <ul>
+ *     <li>sequenced(a, f)
+ *   </ul>
+ *
+ *    Then:
+ *
+ *   <ul>
+ *
+ *     <li> <em>a happens-before b</em>.
+ *
+ *   </ul>
+ *
+ * </dl>
+ *
+ * @hide
+ * @author Doug Lea
+ */
+public class Fences {
+    private Fences() {} // Non-instantiable
+
+    /**
+     * The methods of this class are intended to be intrinisified by a
+     * JVM. However, we provide correct but inefficient Java-level
+     * code that simply reads and writes a static volatile
+     * variable. Without JVM support, the consistency effects are
+     * stronger than necessary, and the memory contention effects can
+     * be a serious performance issue.
+     */
+    private static volatile int theVolatile;
+
+    /**
+     * Informally: Ensures that a read of the given reference prior to
+     * the invocation of this method occurs before a subsequent use of
+     * the given reference with the effect of reading or writing a
+     * field (or if an array, element) of the referenced object.  The
+     * use of this method is sensible only when paired with other
+     * invocations of {@link #orderWrites} and/or {@link
+     * #orderAccesses} for the given reference. For details, see the
+     * class documentation for this class.
+     *
+     * @param ref the reference. If null, this method has no effect.
+     * @param <T> the type of the reference
+     * @return the given ref, to simplify usage
+     */
+    public static <T> T orderReads(T ref) {
+        int ignore = theVolatile;
+        return ref;
+    }
+
+    /**
+     * Informally: Ensures that a use of the given reference with the
+     * effect of reading or writing a field (or if an array, element)
+     * of the referenced object, prior to the invocation of this
+     * method occur before a subsequent write of the reference. For
+     * details, see the class documentation for this class.
+     *
+     * @param ref the reference. If null, this method has no effect.
+     * @param <T> the type of the reference
+     * @return the given ref, to simplify usage
+     */
+    public static <T> T orderWrites(T ref) {
+        theVolatile = 0;
+        return ref;
+    }
+
+    /**
+     * Informally: Ensures that accesses (reads or writes) using the
+     * given reference prior to the invocation of this method occur
+     * before subsequent accesses.  For details, see the class
+     * documentation for this class.
+     *
+     * @param ref the reference. If null, this method has no effect.
+     * @param <T> the type of the reference
+     * @return the given ref, to simplify usage
+     */
+    public static <T> T orderAccesses(T ref) {
+        theVolatile = 0;
+        return ref;
+    }
+
+    /**
+     * Ensures that the object referenced by the given reference
+     * remains <em>strongly reachable</em> (as defined in the {@link
+     * java.lang.ref} package documentation), regardless of any prior
+     * actions of the program that might otherwise cause the object to
+     * become unreachable; thus, the referenced object is not
+     * reclaimable by garbage collection at least until after the
+     * invocation of this method. Invocation of this method does not
+     * itself initiate garbage collection or finalization.
+     *
+     * <p>See the class-level documentation for further explanation
+     * and usage examples.
+     *
+     * @param ref the reference. If null, this method has no effect.
+     */
+    public static void reachabilityFence(Object ref) {
+        if (ref != null) {
+            synchronized (ref) {}
+        }
+    }
+}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java b/luni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java
deleted file mode 100644
index 85e3241..0000000
--- a/luni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * 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.atomic;
-
-import java.io.Serializable;
-import java.util.function.LongBinaryOperator;
-
-/**
- * One or more variables that together maintain a running {@code long}
- * value updated using a supplied function.  When updates (method
- * {@link #accumulate}) are contended across threads, the set of variables
- * may grow dynamically to reduce contention.  Method {@link #get}
- * (or, equivalently, {@link #longValue}) returns the current value
- * across the variables maintaining updates.
- *
- * <p>This class is usually preferable to {@link AtomicLong} when
- * multiple threads update a common value that is used for purposes such
- * as collecting statistics, not for fine-grained synchronization
- * control.  Under low update contention, the two classes have similar
- * characteristics. But under high contention, expected throughput of
- * this class is significantly higher, at the expense of higher space
- * consumption.
- *
- * <p>The order of accumulation within or across threads is not
- * guaranteed and cannot be depended upon, so this class is only
- * applicable to functions for which the order of accumulation does
- * not matter. The supplied accumulator function should be
- * side-effect-free, since it may be re-applied when attempted updates
- * fail due to contention among threads. The function is applied with
- * the current value as its first argument, and the given update as
- * the second argument.  For example, to maintain a running maximum
- * value, you could supply {@code Long::max} along with {@code
- * Long.MIN_VALUE} as the identity.
- *
- * <p>Class {@link LongAdder} provides analogs of the functionality of
- * this class for the common special case of maintaining counts and
- * sums.  The call {@code new LongAdder()} is equivalent to {@code new
- * LongAccumulator((x, y) -> x + y, 0L}.
- *
- * <p>This class extends {@link Number}, but does <em>not</em> define
- * methods such as {@code equals}, {@code hashCode} and {@code
- * compareTo} because instances are expected to be mutated, and so are
- * not useful as collection keys.
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class LongAccumulator extends Striped64 implements Serializable {
-    private static final long serialVersionUID = 7249069246863182397L;
-
-    private final LongBinaryOperator function;
-    private final long identity;
-
-    /**
-     * Creates a new instance using the given accumulator function
-     * and identity element.
-     * @param accumulatorFunction a side-effect-free function of two arguments
-     * @param identity identity (initial value) for the accumulator function
-     */
-    public LongAccumulator(LongBinaryOperator accumulatorFunction,
-                           long identity) {
-        this.function = accumulatorFunction;
-        base = this.identity = identity;
-    }
-
-    /**
-     * Updates with the given value.
-     *
-     * @param x the value
-     */
-    public void accumulate(long x) {
-        Cell[] as; long b, v, r; int m; Cell a;
-        if ((as = cells) != null ||
-            (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
-            boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended =
-                  (r = function.applyAsLong(v = a.value, x)) == v ||
-                  a.cas(v, r)))
-                longAccumulate(x, function, uncontended);
-        }
-    }
-
-    /**
-     * Returns the current value.  The returned value is <em>NOT</em>
-     * an atomic snapshot; invocation in the absence of concurrent
-     * updates returns an accurate result, but concurrent updates that
-     * occur while the value is being calculated might not be
-     * incorporated.
-     *
-     * @return the current value
-     */
-    public long get() {
-        Cell[] as = cells;
-        long result = base;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    result = function.applyAsLong(result, a.value);
-        }
-        return result;
-    }
-
-    /**
-     * Resets variables maintaining updates to the identity value.
-     * This method may be a useful alternative to creating a new
-     * updater, but is only effective if there are no concurrent
-     * updates.  Because this method is intrinsically racy, it should
-     * only be used when it is known that no threads are concurrently
-     * updating.
-     */
-    public void reset() {
-        Cell[] as = cells;
-        base = identity;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset(identity);
-        }
-    }
-
-    /**
-     * Equivalent in effect to {@link #get} followed by {@link
-     * #reset}. This method may apply for example during quiescent
-     * points between multithreaded computations.  If there are
-     * updates concurrent with this method, the returned value is
-     * <em>not</em> guaranteed to be the final value occurring before
-     * the reset.
-     *
-     * @return the value before reset
-     */
-    public long getThenReset() {
-        Cell[] as = cells;
-        long result = base;
-        base = identity;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    long v = a.value;
-                    a.reset(identity);
-                    result = function.applyAsLong(result, v);
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the String representation of the current value.
-     * @return the String representation of the current value
-     */
-    public String toString() {
-        return Long.toString(get());
-    }
-
-    /**
-     * Equivalent to {@link #get}.
-     *
-     * @return the current value
-     */
-    public long longValue() {
-        return get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as an {@code int}
-     * after a narrowing primitive conversion.
-     */
-    public int intValue() {
-        return (int)get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as a {@code float}
-     * after a widening primitive conversion.
-     */
-    public float floatValue() {
-        return (float)get();
-    }
-
-    /**
-     * Returns the {@linkplain #get current value} as a {@code double}
-     * after a widening primitive conversion.
-     */
-    public double doubleValue() {
-        return (double)get();
-    }
-
-    /**
-     * Serialization proxy, used to avoid reference to the non-public
-     * Striped64 superclass in serialized forms.
-     * @serial include
-     */
-    private static class SerializationProxy implements Serializable {
-        private static final long serialVersionUID = 7249069246863182397L;
-
-        /**
-         * The current value returned by get().
-         * @serial
-         */
-        private final long value;
-
-        /**
-         * The function used for updates.
-         * @serial
-         */
-        private final LongBinaryOperator function;
-
-        /**
-         * The identity value.
-         * @serial
-         */
-        private final long identity;
-
-        SerializationProxy(long value,
-                           LongBinaryOperator function,
-                           long identity) {
-            this.value = value;
-            this.function = function;
-            this.identity = identity;
-        }
-
-        /**
-         * Returns a {@code LongAccumulator} object with initial state
-         * held by this proxy.
-         *
-         * @return a {@code LongAccumulator} object with initial state
-         * held by this proxy
-         */
-        private Object readResolve() {
-            LongAccumulator a = new LongAccumulator(function, identity);
-            a.base = value;
-            return a;
-        }
-    }
-
-    /**
-     * Returns a
-     * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAccumulator.SerializationProxy">
-     * SerializationProxy</a>
-     * representing the state of this instance.
-     *
-     * @return a {@link SerializationProxy}
-     * representing the state of this instance
-     */
-    private Object writeReplace() {
-        return new SerializationProxy(get(), function, identity);
-    }
-
-    /**
-     * @param s the stream
-     * @throws java.io.InvalidObjectException always
-     */
-    private void readObject(java.io.ObjectInputStream s)
-        throws java.io.InvalidObjectException {
-        throw new java.io.InvalidObjectException("Proxy required");
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/LongAdder.java b/luni/src/main/java/java/util/concurrent/atomic/LongAdder.java
deleted file mode 100644
index a17d52a..0000000
--- a/luni/src/main/java/java/util/concurrent/atomic/LongAdder.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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.atomic;
-
-import java.io.Serializable;
-
-/**
- * One or more variables that together maintain an initially zero
- * {@code long} sum.  When updates (method {@link #add}) are contended
- * across threads, the set of variables may grow dynamically to reduce
- * contention. Method {@link #sum} (or, equivalently, {@link
- * #longValue}) returns the current total combined across the
- * variables maintaining the sum.
- *
- * <p>This class is usually preferable to {@link AtomicLong} when
- * multiple threads update a common sum that is used for purposes such
- * as collecting statistics, not for fine-grained synchronization
- * control.  Under low update contention, the two classes have similar
- * characteristics. But under high contention, expected throughput of
- * this class is significantly higher, at the expense of higher space
- * consumption.
- *
- * <p>LongAdders can be used with a {@link
- * java.util.concurrent.ConcurrentHashMap} to maintain a scalable
- * frequency map (a form of histogram or multiset). For example, to
- * add a count to a {@code ConcurrentHashMap<String,LongAdder> freqs},
- * initializing if not already present, you can use {@code
- * freqs.computeIfAbsent(key, k -> new LongAdder()).increment();}
- *
- * <p>This class extends {@link Number}, but does <em>not</em> define
- * methods such as {@code equals}, {@code hashCode} and {@code
- * compareTo} because instances are expected to be mutated, and so are
- * not useful as collection keys.
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class LongAdder extends Striped64 implements Serializable {
-    private static final long serialVersionUID = 7249069246863182397L;
-
-    /**
-     * Creates a new adder with initial sum of zero.
-     */
-    public LongAdder() {
-    }
-
-    /**
-     * Adds the given value.
-     *
-     * @param x the value to add
-     */
-    public void add(long x) {
-        Cell[] as; long b, v; int m; Cell a;
-        if ((as = cells) != null || !casBase(b = base, b + x)) {
-            boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended = a.cas(v = a.value, v + x)))
-                longAccumulate(x, null, uncontended);
-        }
-    }
-
-    /**
-     * Equivalent to {@code add(1)}.
-     */
-    public void increment() {
-        add(1L);
-    }
-
-    /**
-     * Equivalent to {@code add(-1)}.
-     */
-    public void decrement() {
-        add(-1L);
-    }
-
-    /**
-     * Returns the current sum.  The returned value is <em>NOT</em> an
-     * atomic snapshot; invocation in the absence of concurrent
-     * updates returns an accurate result, but concurrent updates that
-     * occur while the sum is being calculated might not be
-     * incorporated.
-     *
-     * @return the sum
-     */
-    public long sum() {
-        Cell[] as = cells;
-        long sum = base;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    sum += a.value;
-        }
-        return sum;
-    }
-
-    /**
-     * Resets variables maintaining the sum to zero.  This method may
-     * be a useful alternative to creating a new adder, but is only
-     * effective if there are no concurrent updates.  Because this
-     * method is intrinsically racy, it should only be used when it is
-     * known that no threads are concurrently updating.
-     */
-    public void reset() {
-        Cell[] as = cells;
-        base = 0L;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset();
-        }
-    }
-
-    /**
-     * Equivalent in effect to {@link #sum} followed by {@link
-     * #reset}. This method may apply for example during quiescent
-     * points between multithreaded computations.  If there are
-     * updates concurrent with this method, the returned value is
-     * <em>not</em> guaranteed to be the final value occurring before
-     * the reset.
-     *
-     * @return the sum
-     */
-    public long sumThenReset() {
-        Cell[] as = cells;
-        long sum = base;
-        base = 0L;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    sum += a.value;
-                    a.reset();
-                }
-            }
-        }
-        return sum;
-    }
-
-    /**
-     * Returns the String representation of the {@link #sum}.
-     * @return the String representation of the {@link #sum}
-     */
-    public String toString() {
-        return Long.toString(sum());
-    }
-
-    /**
-     * Equivalent to {@link #sum}.
-     *
-     * @return the sum
-     */
-    public long longValue() {
-        return sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as an {@code int} after a narrowing
-     * primitive conversion.
-     */
-    public int intValue() {
-        return (int)sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as a {@code float}
-     * after a widening primitive conversion.
-     */
-    public float floatValue() {
-        return (float)sum();
-    }
-
-    /**
-     * Returns the {@link #sum} as a {@code double} after a widening
-     * primitive conversion.
-     */
-    public double doubleValue() {
-        return (double)sum();
-    }
-
-    /**
-     * Serialization proxy, used to avoid reference to the non-public
-     * Striped64 superclass in serialized forms.
-     * @serial include
-     */
-    private static class SerializationProxy implements Serializable {
-        private static final long serialVersionUID = 7249069246863182397L;
-
-        /**
-         * The current value returned by sum().
-         * @serial
-         */
-        private final long value;
-
-        SerializationProxy(LongAdder a) {
-            value = a.sum();
-        }
-
-        /**
-         * Returns a {@code LongAdder} object with initial state
-         * held by this proxy.
-         *
-         * @return a {@code LongAdder} object with initial state
-         * held by this proxy
-         */
-        private Object readResolve() {
-            LongAdder a = new LongAdder();
-            a.base = value;
-            return a;
-        }
-    }
-
-    /**
-     * Returns a
-     * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAdder.SerializationProxy">
-     * SerializationProxy</a>
-     * representing the state of this instance.
-     *
-     * @return a {@link SerializationProxy}
-     * representing the state of this instance
-     */
-    private Object writeReplace() {
-        return new SerializationProxy(this);
-    }
-
-    /**
-     * @param s the stream
-     * @throws java.io.InvalidObjectException always
-     */
-    private void readObject(java.io.ObjectInputStream s)
-        throws java.io.InvalidObjectException {
-        throw new java.io.InvalidObjectException("Proxy required");
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/Striped64.java b/luni/src/main/java/java/util/concurrent/atomic/Striped64.java
deleted file mode 100644
index fc88849..0000000
--- a/luni/src/main/java/java/util/concurrent/atomic/Striped64.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * 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.atomic;
-
-import java.util.Arrays;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.function.DoubleBinaryOperator;
-import java.util.function.LongBinaryOperator;
-
-/**
- * A package-local class holding common representation and mechanics
- * for classes supporting dynamic striping on 64bit values. The class
- * extends Number so that concrete subclasses must publicly do so.
- */
-@SuppressWarnings("serial")
-abstract class Striped64 extends Number {
-    /*
-     * This class maintains a lazily-initialized table of atomically
-     * updated variables, plus an extra "base" field. The table size
-     * is a power of two. Indexing uses masked per-thread hash codes.
-     * Nearly all declarations in this class are package-private,
-     * accessed directly by subclasses.
-     *
-     * Table entries are of class Cell; a variant of AtomicLong padded
-     * (via @Contended) to reduce cache contention. Padding is
-     * overkill for most Atomics because they are usually irregularly
-     * scattered in memory and thus don't interfere much with each
-     * other. But Atomic objects residing in arrays will tend to be
-     * placed adjacent to each other, and so will most often share
-     * cache lines (with a huge negative performance impact) without
-     * this precaution.
-     *
-     * In part because Cells are relatively large, we avoid creating
-     * them until they are needed.  When there is no contention, all
-     * updates are made to the base field.  Upon first contention (a
-     * failed CAS on base update), the table is initialized to size 2.
-     * The table size is doubled upon further contention until
-     * reaching the nearest power of two greater than or equal to the
-     * number of CPUS. Table slots remain empty (null) until they are
-     * needed.
-     *
-     * A single spinlock ("cellsBusy") is used for initializing and
-     * resizing the table, as well as populating slots with new Cells.
-     * There is no need for a blocking lock; when the lock is not
-     * available, threads try other slots (or the base).  During these
-     * retries, there is increased contention and reduced locality,
-     * which is still better than alternatives.
-     *
-     * The Thread probe fields maintained via ThreadLocalRandom serve
-     * as per-thread hash codes. We let them remain uninitialized as
-     * zero (if they come in this way) until they contend at slot
-     * 0. They are then initialized to values that typically do not
-     * often conflict with others.  Contention and/or table collisions
-     * are indicated by failed CASes when performing an update
-     * operation. Upon a collision, if the table size is less than
-     * the capacity, it is doubled in size unless some other thread
-     * holds the lock. If a hashed slot is empty, and lock is
-     * available, a new Cell is created. Otherwise, if the slot
-     * exists, a CAS is tried.  Retries proceed by "double hashing",
-     * using a secondary hash (Marsaglia XorShift) to try to find a
-     * free slot.
-     *
-     * The table size is capped because, when there are more threads
-     * than CPUs, supposing that each thread were bound to a CPU,
-     * there would exist a perfect hash function mapping threads to
-     * slots that eliminates collisions. When we reach capacity, we
-     * search for this mapping by randomly varying the hash codes of
-     * colliding threads.  Because search is random, and collisions
-     * only become known via CAS failures, convergence can be slow,
-     * and because threads are typically not bound to CPUS forever,
-     * may not occur at all. However, despite these limitations,
-     * observed contention rates are typically low in these cases.
-     *
-     * It is possible for a Cell to become unused when threads that
-     * once hashed to it terminate, as well as in the case where
-     * doubling the table causes no thread to hash to it under
-     * expanded mask.  We do not try to detect or remove such cells,
-     * under the assumption that for long-running instances, observed
-     * contention levels will recur, so the cells will eventually be
-     * needed again; and for short-lived ones, it does not matter.
-     */
-
-    /**
-     * Padded variant of AtomicLong supporting only raw accesses plus CAS.
-     *
-     * JVM intrinsics note: It would be possible to use a release-only
-     * form of CAS here, if it were provided.
-     */
-    // @jdk.internal.vm.annotation.Contended // android-removed
-    static final class Cell {
-        volatile long value;
-        Cell(long x) { value = x; }
-        final boolean cas(long cmp, long val) {
-            return U.compareAndSwapLong(this, VALUE, cmp, val);
-        }
-        final void reset() {
-            U.putLongVolatile(this, VALUE, 0L);
-        }
-        final void reset(long identity) {
-            U.putLongVolatile(this, VALUE, identity);
-        }
-
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
-        static {
-            try {
-                VALUE = U.objectFieldOffset
-                    (Cell.class.getDeclaredField("value"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
-    }
-
-    /** Number of CPUS, to place bound on table size */
-    static final int NCPU = Runtime.getRuntime().availableProcessors();
-
-    /**
-     * Table of cells. When non-null, size is a power of 2.
-     */
-    transient volatile Cell[] cells;
-
-    /**
-     * Base value, used mainly when there is no contention, but also as
-     * a fallback during table initialization races. Updated via CAS.
-     */
-    transient volatile long base;
-
-    /**
-     * Spinlock (locked via CAS) used when resizing and/or creating Cells.
-     */
-    transient volatile int cellsBusy;
-
-    /**
-     * Package-private default constructor.
-     */
-    Striped64() {
-    }
-
-    /**
-     * CASes the base field.
-     */
-    final boolean casBase(long cmp, long val) {
-        return U.compareAndSwapLong(this, BASE, cmp, val);
-    }
-
-    /**
-     * CASes the cellsBusy field from 0 to 1 to acquire lock.
-     */
-    final boolean casCellsBusy() {
-        return U.compareAndSwapInt(this, CELLSBUSY, 0, 1);
-    }
-
-    /**
-     * Returns the probe value for the current thread.
-     * Duplicated from ThreadLocalRandom because of packaging restrictions.
-     */
-    static final int getProbe() {
-        return U.getInt(Thread.currentThread(), PROBE);
-    }
-
-    /**
-     * Pseudo-randomly advances and records the given probe value for the
-     * given thread.
-     * Duplicated from ThreadLocalRandom because of packaging restrictions.
-     */
-    static final int advanceProbe(int probe) {
-        probe ^= probe << 13;   // xorshift
-        probe ^= probe >>> 17;
-        probe ^= probe << 5;
-        U.putInt(Thread.currentThread(), PROBE, probe);
-        return probe;
-    }
-
-    /**
-     * Handles cases of updates involving initialization, resizing,
-     * creating new Cells, and/or contention. See above for
-     * explanation. This method suffers the usual non-modularity
-     * problems of optimistic retry code, relying on rechecked sets of
-     * reads.
-     *
-     * @param x the value
-     * @param fn the update function, or null for add (this convention
-     * avoids the need for an extra field or function in LongAdder).
-     * @param wasUncontended false if CAS failed before call
-     */
-    final void longAccumulate(long x, LongBinaryOperator fn,
-                              boolean wasUncontended) {
-        int h;
-        if ((h = getProbe()) == 0) {
-            ThreadLocalRandom.current(); // force initialization
-            h = getProbe();
-            wasUncontended = true;
-        }
-        boolean collide = false;                // True if last slot nonempty
-        done: for (;;) {
-            Cell[] as; Cell a; int n; long v;
-            if ((as = cells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
-                    if (cellsBusy == 0) {       // Try to attach new Cell
-                        Cell r = new Cell(x);   // Optimistically create
-                        if (cellsBusy == 0 && casCellsBusy()) {
-                            try {               // Recheck under lock
-                                Cell[] rs; int m, j;
-                                if ((rs = cells) != null &&
-                                    (m = rs.length) > 0 &&
-                                    rs[j = (m - 1) & h] == null) {
-                                    rs[j] = r;
-                                    break done;
-                                }
-                            } finally {
-                                cellsBusy = 0;
-                            }
-                            continue;           // Slot is now non-empty
-                        }
-                    }
-                    collide = false;
-                }
-                else if (!wasUncontended)       // CAS already known to fail
-                    wasUncontended = true;      // Continue after rehash
-                else if (a.cas(v = a.value,
-                               (fn == null) ? v + x : fn.applyAsLong(v, x)))
-                    break;
-                else if (n >= NCPU || cells != as)
-                    collide = false;            // At max size or stale
-                else if (!collide)
-                    collide = true;
-                else if (cellsBusy == 0 && casCellsBusy()) {
-                    try {
-                        if (cells == as)        // Expand table unless stale
-                            cells = Arrays.copyOf(as, n << 1);
-                    } finally {
-                        cellsBusy = 0;
-                    }
-                    collide = false;
-                    continue;                   // Retry with expanded table
-                }
-                h = advanceProbe(h);
-            }
-            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
-                try {                           // Initialize table
-                    if (cells == as) {
-                        Cell[] rs = new Cell[2];
-                        rs[h & 1] = new Cell(x);
-                        cells = rs;
-                        break done;
-                    }
-                } finally {
-                    cellsBusy = 0;
-                }
-            }
-            // Fall back on using base
-            else if (casBase(v = base,
-                             (fn == null) ? v + x : fn.applyAsLong(v, x)))
-                break done;
-        }
-    }
-
-    private static long apply(DoubleBinaryOperator fn, long v, double x) {
-        double d = Double.longBitsToDouble(v);
-        d = (fn == null) ? d + x : fn.applyAsDouble(d, x);
-        return Double.doubleToRawLongBits(d);
-    }
-
-    /**
-     * Same as longAccumulate, but injecting long/double conversions
-     * in too many places to sensibly merge with long version, given
-     * the low-overhead requirements of this class. So must instead be
-     * maintained by copy/paste/adapt.
-     */
-    final void doubleAccumulate(double x, DoubleBinaryOperator fn,
-                                boolean wasUncontended) {
-        int h;
-        if ((h = getProbe()) == 0) {
-            ThreadLocalRandom.current(); // force initialization
-            h = getProbe();
-            wasUncontended = true;
-        }
-        boolean collide = false;                // True if last slot nonempty
-        done: for (;;) {
-            Cell[] as; Cell a; int n; long v;
-            if ((as = cells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
-                    if (cellsBusy == 0) {       // Try to attach new Cell
-                        Cell r = new Cell(Double.doubleToRawLongBits(x));
-                        if (cellsBusy == 0 && casCellsBusy()) {
-                            try {               // Recheck under lock
-                                Cell[] rs; int m, j;
-                                if ((rs = cells) != null &&
-                                    (m = rs.length) > 0 &&
-                                    rs[j = (m - 1) & h] == null) {
-                                    rs[j] = r;
-                                    break done;
-                                }
-                            } finally {
-                                cellsBusy = 0;
-                            }
-                            continue;           // Slot is now non-empty
-                        }
-                    }
-                    collide = false;
-                }
-                else if (!wasUncontended)       // CAS already known to fail
-                    wasUncontended = true;      // Continue after rehash
-                else if (a.cas(v = a.value, apply(fn, v, x)))
-                    break;
-                else if (n >= NCPU || cells != as)
-                    collide = false;            // At max size or stale
-                else if (!collide)
-                    collide = true;
-                else if (cellsBusy == 0 && casCellsBusy()) {
-                    try {
-                        if (cells == as)        // Expand table unless stale
-                            cells = Arrays.copyOf(as, n << 1);
-                    } finally {
-                        cellsBusy = 0;
-                    }
-                    collide = false;
-                    continue;                   // Retry with expanded table
-                }
-                h = advanceProbe(h);
-            }
-            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
-                try {                           // Initialize table
-                    if (cells == as) {
-                        Cell[] rs = new Cell[2];
-                        rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
-                        cells = rs;
-                        break done;
-                    }
-                } finally {
-                    cellsBusy = 0;
-                }
-            }
-            // Fall back on using base
-            else if (casBase(v = base, apply(fn, v, x)))
-                break done;
-        }
-    }
-
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long BASE;
-    private static final long CELLSBUSY;
-    private static final long PROBE;
-    static {
-        try {
-            BASE = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("base"));
-            CELLSBUSY = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("cellsBusy"));
-
-            PROBE = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomProbe"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
-}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/package-info.java b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
index b19dd49..568d2c6 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -11,7 +11,7 @@
  * array elements to those that also provide an atomic conditional update
  * operation of the form:
  *
- * <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
+ *  <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
  *
  * <p>This method (which varies in argument types across different
  * classes) atomically sets a variable to the {@code updateValue} if it
@@ -38,7 +38,7 @@
  * {@code AtomicInteger} provide atomic increment methods.  One
  * application is to generate sequence numbers, as in:
  *
- * <pre> {@code
+ *  <pre> {@code
  * class Sequencer {
  *   private final AtomicLong sequenceNumber
  *     = new AtomicLong(0);
@@ -53,31 +53,31 @@
  * <pre> {@code long transform(long input)}</pre>
  *
  * write your utility method as follows:
- * <pre> {@code
+ *  <pre> {@code
  * long getAndTransform(AtomicLong var) {
- *   long prev, next;
- *   do {
- *     prev = var.get();
- *     next = transform(prev);
- *   } while (!var.compareAndSet(prev, next));
- *   return prev; // return next; for transformAndGet
+ *   while (true) {
+ *     long current = var.get();
+ *     long next = transform(current);
+ *     if (var.compareAndSet(current, next))
+ *         return current;
+ *         // return next; for transformAndGet
+ *   }
  * }}</pre>
  *
  * <p>The memory effects for accesses and updates of atomics generally
  * follow the rules for volatiles, as stated in
- * <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>:
+ * <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>:
  *
  * <ul>
  *
- *   <li>{@code get} has the memory effects of reading a
+ *   <li> {@code get} has the memory effects of reading a
  * {@code volatile} variable.
  *
- *   <li>{@code set} has the memory effects of writing (assigning) a
+ *   <li> {@code set} has the memory effects of writing (assigning) a
  * {@code volatile} variable.
  *
- *   <li>{@code lazySet} has the memory effects of writing (assigning)
+ *   <li> {@code lazySet} has the memory effects of writing (assigning)
  *   a {@code volatile} variable except that it permits reorderings with
  *   subsequent (but not previous) memory actions that do not themselves
  *   impose reordering constraints with ordinary non-{@code volatile}
@@ -91,7 +91,7 @@
  *   with respect to previous or subsequent reads and writes of any
  *   variables other than the target of the {@code weakCompareAndSet}.
  *
- *   <li>{@code compareAndSet}
+ *   <li> {@code compareAndSet}
  *   and all other read-and-update operations such as {@code getAndIncrement}
  *   have the memory effects of both reading and
  *   writing {@code volatile} variables.
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index 3c10805..a74fb24 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -6,11 +6,11 @@
 
 package java.util.concurrent.locks;
 
+import java.util.concurrent.TimeUnit;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.AbstractQueuedSynchronizer.Node;
+import sun.misc.Unsafe;
 
 /**
  * A version of {@link AbstractQueuedSynchronizer} in
@@ -49,6 +49,221 @@
     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
@@ -82,9 +297,7 @@
      * @param newState the new state value
      */
     protected final void setState(long newState) {
-        // Use putLongVolatile instead of ordinary volatile store when
-        // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, STATE, newState);
+        state = newState;
     }
 
     /**
@@ -95,11 +308,12 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that the actual
+     * @return true if successful. False return indicates that the actual
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(long expect, long update) {
-        return U.compareAndSwapLong(this, STATE, expect, update);
+        // See below for intrinsics setup to support this
+        return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
     }
 
     // Queuing utilities
@@ -109,24 +323,25 @@
      * rather than to use timed park. A rough estimate suffices
      * to improve responsiveness with very short timeouts.
      */
-    static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
+    static final long spinForTimeoutThreshold = 1000L;
 
     /**
      * Inserts node into queue, initializing if necessary. See picture above.
      * @param node the node to insert
      * @return node's predecessor
      */
-    private Node enq(Node node) {
+    private Node enq(final Node node) {
         for (;;) {
-            Node oldTail = tail;
-            if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
-                if (compareAndSetTail(oldTail, node)) {
-                    oldTail.next = node;
-                    return oldTail;
-                }
+            Node t = tail;
+            if (t == null) { // Must initialize
+                if (compareAndSetHead(new Node()))
+                    tail = head;
             } else {
-                initializeSyncQueue();
+                node.prev = t;
+                if (compareAndSetTail(t, node)) {
+                    t.next = node;
+                    return t;
+                }
             }
         }
     }
@@ -138,20 +353,18 @@
      * @return the new node
      */
     private Node addWaiter(Node mode) {
-        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();
+        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;
             }
         }
+        enq(node);
+        return node;
     }
 
     /**
@@ -180,7 +393,7 @@
          */
         int ws = node.waitStatus;
         if (ws < 0)
-            node.compareAndSetWaitStatus(ws, 0);
+            compareAndSetWaitStatus(node, ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -191,7 +404,7 @@
         Node s = node.next;
         if (s == null || s.waitStatus > 0) {
             s = null;
-            for (Node p = tail; p != node && p != null; p = p.prev)
+            for (Node p = tail; p != null && p != node; p = p.prev)
                 if (p.waitStatus <= 0)
                     s = p;
         }
@@ -221,12 +434,12 @@
             if (h != null && h != tail) {
                 int ws = h.waitStatus;
                 if (ws == Node.SIGNAL) {
-                    if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
+                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                         continue;            // loop to recheck cases
                     unparkSuccessor(h);
                 }
                 else if (ws == 0 &&
-                         !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
+                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                     continue;                // loop on failed CAS
             }
             if (h == head)                   // loop if head changed
@@ -248,8 +461,7 @@
         /*
          * Try to signal next queued node if:
          *   Propagation was indicated by caller,
-         *     or was recorded (as h.waitStatus either before
-         *     or after setHead) by a previous operation
+         *     or was recorded (as h.waitStatus) by a previous operation
          *     (note: this uses sign-check of waitStatus because
          *      PROPAGATE status may transition to SIGNAL.)
          * and
@@ -261,8 +473,7 @@
          * racing acquires/releases, so most need signals now or soon
          * anyway.
          */
-        if (propagate > 0 || h == null || h.waitStatus < 0 ||
-            (h = head) == null || h.waitStatus < 0) {
+        if (propagate > 0 || h == null || h.waitStatus < 0) {
             Node s = node.next;
             if (s == null || s.isShared())
                 doReleaseShared();
@@ -300,18 +511,18 @@
 
         // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
-            pred.compareAndSetNext(predNext, null);
+            compareAndSetNext(pred, 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 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
+                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                 pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
-                    pred.compareAndSetNext(predNext, next);
+                    compareAndSetNext(pred, predNext, next);
             } else {
                 unparkSuccessor(node);
             }
@@ -352,7 +563,7 @@
              * need a signal, but don't park yet.  Caller will need to
              * retry to make sure it cannot acquire before parking.
              */
-            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
+            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
         }
         return false;
     }
@@ -365,7 +576,7 @@
     }
 
     /**
-     * Convenience method to park and then check if interrupted.
+     * Convenience method to park and then check if interrupted
      *
      * @return {@code true} if interrupted
      */
@@ -392,6 +603,7 @@
      * @return {@code true} if interrupted while waiting
      */
     final boolean acquireQueued(final Node node, long arg) {
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -399,15 +611,16 @@
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
+                    failed = false;
                     return interrupted;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -418,21 +631,23 @@
     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();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -449,28 +664,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) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0L)
                     return false;
-                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -480,6 +695,7 @@
      */
     private void doAcquireShared(long arg) {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -491,6 +707,7 @@
                         p.next = null; // help GC
                         if (interrupted)
                             selfInterrupt();
+                        failed = false;
                         return;
                     }
                 }
@@ -498,9 +715,9 @@
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -511,6 +728,7 @@
     private void doAcquireSharedInterruptibly(long arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -519,6 +737,7 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return;
                     }
                 }
@@ -526,9 +745,9 @@
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -545,6 +764,7 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -553,23 +773,22 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return true;
                     }
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0L)
                     return false;
-                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -893,7 +1112,7 @@
 
     /**
      * Queries whether any threads have ever contended to acquire this
-     * synchronizer; that is, if an acquire method has ever blocked.
+     * synchronizer; that is if an acquire method has ever blocked.
      *
      * <p>In this implementation, this operation returns in
      * constant time.
@@ -921,7 +1140,7 @@
     }
 
     /**
-     * Version of getFirstQueuedThread called when fastpath fails.
+     * Version of getFirstQueuedThread called when fastpath fails
      */
     private Thread fullGetFirstQueuedThread() {
         /*
@@ -948,11 +1167,13 @@
          * guaranteeing termination.
          */
 
+        Node t = tail;
         Thread firstThread = null;
-        for (Node p = tail; p != null && p != head; p = p.prev) {
-            Thread t = p.thread;
-            if (t != null)
-                firstThread = t;
+        while (t != null && t != head) {
+            Thread tt = t.thread;
+            if (tt != null)
+                firstThread = tt;
+            t = t.prev;
         }
         return firstThread;
     }
@@ -999,9 +1220,9 @@
      *
      * <p>An invocation of this method is equivalent to (but may be
      * more efficient than):
-     * <pre> {@code
-     * getFirstQueuedThread() != Thread.currentThread()
-     *   && hasQueuedThreads()}</pre>
+     *  <pre> {@code
+     * getFirstQueuedThread() != Thread.currentThread() &&
+     * hasQueuedThreads()}</pre>
      *
      * <p>Note that because cancellations due to interrupts and
      * timeouts may occur at any time, a {@code true} return does not
@@ -1019,7 +1240,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
@@ -1055,7 +1276,8 @@
      * 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
      */
@@ -1080,7 +1302,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             Thread t = p.thread;
             if (t != null)
@@ -1098,7 +1320,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             if (!p.isShared()) {
                 Thread t = p.thread;
@@ -1118,7 +1340,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getSharedQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             if (p.isShared()) {
                 Thread t = p.thread;
@@ -1139,9 +1361,10 @@
      * @return a string identifying this synchronizer, as well as its state
      */
     public String toString() {
-        return super.toString()
-            + "[State = " + getState() + ", "
-            + (hasQueuedThreads() ? "non" : "") + "empty queue]";
+        long s = getState();
+        String q  = hasQueuedThreads() ? "non" : "";
+        return super.toString() +
+            "[State = " + s + ", " + q + "empty queue]";
     }
 
 
@@ -1175,10 +1398,8 @@
      * @return true if present
      */
     private boolean findNodeFromTail(Node 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;;) {
+        Node p = tail;
+        for (;;) {
             if (p == node)
                 return true;
             if (p == null)
@@ -1198,7 +1419,7 @@
         /*
          * If cannot change waitStatus, the node has been cancelled.
          */
-        if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
+        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
             return false;
 
         /*
@@ -1209,7 +1430,7 @@
          */
         Node p = enq(node);
         int ws = p.waitStatus;
-        if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
+        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
@@ -1222,7 +1443,7 @@
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
-        if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
+        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
             enq(node);
             return true;
         }
@@ -1244,14 +1465,18 @@
      * @return previous sync state
      */
     final long fullyRelease(Node node) {
+        boolean failed = true;
         try {
             long savedState = getState();
-            if (release(savedState))
+            if (release(savedState)) {
+                failed = false;
                 return savedState;
-            throw new IllegalMonitorStateException();
-        } catch (Throwable t) {
-            node.waitStatus = Node.CANCELLED;
-            throw t;
+            } else {
+                throw new IllegalMonitorStateException();
+            }
+        } finally {
+            if (failed)
+                node.waitStatus = Node.CANCELLED;
         }
     }
 
@@ -1296,8 +1521,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 system
-     * state, not for synchronization control.
+     * waiters.  This method is designed for use in monitoring of the
+     * system state, not for synchronization control.
      *
      * @param condition the condition
      * @return the estimated number of waiting threads
@@ -1377,9 +1602,7 @@
                 unlinkCancelledWaiters();
                 t = lastWaiter;
             }
-
-            Node node = new Node(Node.CONDITION);
-
+            Node node = new Node(Thread.currentThread(), Node.CONDITION);
             if (t == null)
                 firstWaiter = node;
             else
@@ -1487,12 +1710,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() {
@@ -1546,14 +1769,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 {
@@ -1578,33 +1801,31 @@
         /**
          * 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 > SPIN_FOR_TIMEOUT_THRESHOLD)
+                if (nanosTimeout >= spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -1617,21 +1838,24 @@
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
             long remaining = deadline - System.nanoTime(); // avoid overflow
+            // BEGIN android-note Changed from < to <= http://b/24284239
+            // return (remaining < initialNanos) ? remaining : Long.MIN_VALUE;
             return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
+            // END android-note
         }
 
         /**
          * 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)
@@ -1644,7 +1868,7 @@
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
-                if (System.currentTimeMillis() >= abstime) {
+                if (System.currentTimeMillis() > abstime) {
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
@@ -1664,15 +1888,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)
@@ -1680,11 +1904,9 @@
             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)) {
@@ -1692,7 +1914,7 @@
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                if (nanosTimeout >= spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -1721,7 +1943,7 @@
 
         /**
          * Queries whether any threads are waiting on this condition.
-         * Implements {@link AbstractQueuedLongSynchronizer#hasWaiters(ConditionObject)}.
+         * Implements {@link AbstractQueuedLongSynchronizer#hasWaiters}.
          *
          * @return {@code true} if there are any waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -1740,7 +1962,7 @@
         /**
          * Returns an estimate of the number of threads waiting on
          * this condition.
-         * Implements {@link AbstractQueuedLongSynchronizer#getWaitQueueLength(ConditionObject)}.
+         * Implements {@link AbstractQueuedLongSynchronizer#getWaitQueueLength}.
          *
          * @return the estimated number of waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -1760,7 +1982,7 @@
         /**
          * Returns a collection containing those threads that may be
          * waiting on this Condition.
-         * Implements {@link AbstractQueuedLongSynchronizer#getWaitingThreads(ConditionObject)}.
+         * Implements {@link AbstractQueuedLongSynchronizer#getWaitingThreads}.
          *
          * @return the collection of threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -1769,7 +1991,7 @@
         protected final Collection<Thread> getWaitingThreads() {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
-            ArrayList<Thread> list = new ArrayList<>();
+            ArrayList<Thread> list = new ArrayList<Thread>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION) {
                     Thread t = w.thread;
@@ -1790,22 +2012,27 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    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;
+    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;
 
     static {
         try {
-            STATE = U.objectFieldOffset
+            stateOffset = unsafe.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
+            headOffset = unsafe.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
+            tailOffset = unsafe.objectFieldOffset
                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+            waitStatusOffset = unsafe.objectFieldOffset
+                (Node.class.getDeclaredField("waitStatus"));
+            nextOffset = unsafe.objectFieldOffset
+                (Node.class.getDeclaredField("next"));
+
+        } 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
@@ -1813,18 +2040,35 @@
     }
 
     /**
-     * Initializes head and tail fields on first contention.
+     * CAS head field. Used only by enq.
      */
-    private final void initializeSyncQueue() {
-        Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
-            tail = h;
+    private final boolean compareAndSetHead(Node update) {
+        return unsafe.compareAndSwapObject(this, headOffset, null, update);
     }
 
     /**
-     * CASes tail field.
+     * CAS tail field. Used only by enq.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+    }
+
+    /**
+     * CAS waitStatus field of a node.
+     */
+    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);
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 2c41000..8823b6f 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -6,11 +6,15 @@
 
 package java.util.concurrent.locks;
 
+import java.util.concurrent.TimeUnit;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
-import java.util.concurrent.TimeUnit;
-/// OPENJDK-9 import jdk.internal.vm.annotation.ReservedStackAccess;
+import sun.misc.Unsafe;
+
+// BEGIN android-note
+// Use older class level documentation to not @link to hasQueuedPredecessors
+// END android-changed
 
 /**
  * Provides a framework for implementing blocking locks and related
@@ -82,11 +86,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
@@ -127,7 +131,7 @@
  * disable barging by internally invoking one or more of the inspection
  * methods, thereby providing a <em>fair</em> FIFO acquisition order.
  * In particular, most fair synchronizers can define {@code tryAcquire}
- * to return {@code false} if {@link #hasQueuedPredecessors} (a method
+ * to return {@code false} if {@code hasQueuedPredecessors} (a method
  * specifically designed to be used by fair synchronizers) returns
  * {@code true}.  Other variations are possible.
  *
@@ -167,7 +171,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
@@ -231,7 +235,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 {
@@ -355,15 +359,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;
 
@@ -471,49 +475,17 @@
                 return p;
         }
 
-        /** Establishes initial head or SHARED marker. */
-        Node() {}
-
-        /** Constructor used by addWaiter. */
-        Node(Node nextWaiter) {
-            this.nextWaiter = nextWaiter;
-            U.putObject(this, THREAD, Thread.currentThread());
+        Node() {    // Used to establish initial head or SHARED marker
         }
 
-        /** Constructor used by addConditionWaiter. */
-        Node(int waitStatus) {
-            U.putInt(this, WAITSTATUS, waitStatus);
-            U.putObject(this, THREAD, Thread.currentThread());
+        Node(Thread thread, Node mode) {     // Used by addWaiter
+            this.nextWaiter = mode;
+            this.thread = thread;
         }
 
-        /** CASes waitStatus field. */
-        final boolean compareAndSetWaitStatus(int expect, int update) {
-            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
-        }
-
-        /** CASes next field. */
-        final boolean compareAndSetNext(Node expect, Node update) {
-            return U.compareAndSwapObject(this, NEXT, expect, update);
-        }
-
-        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);
-            }
+        Node(Thread thread, int waitStatus) { // Used by Condition
+            this.waitStatus = waitStatus;
+            this.thread = thread;
         }
     }
 
@@ -562,11 +534,12 @@
      *
      * @param expect the expected value
      * @param update the new value
-     * @return {@code true} if successful. False return indicates that the actual
+     * @return true if successful. False return indicates that the actual
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
-        return U.compareAndSwapInt(this, STATE, expect, update);
+        // See below for intrinsics setup to support this
+        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
     }
 
     // Queuing utilities
@@ -576,24 +549,25 @@
      * rather than to use timed park. A rough estimate suffices
      * to improve responsiveness with very short timeouts.
      */
-    static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
+    static final long spinForTimeoutThreshold = 1000L;
 
     /**
      * Inserts node into queue, initializing if necessary. See picture above.
      * @param node the node to insert
      * @return node's predecessor
      */
-    private Node enq(Node node) {
+    private Node enq(final Node node) {
         for (;;) {
-            Node oldTail = tail;
-            if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
-                if (compareAndSetTail(oldTail, node)) {
-                    oldTail.next = node;
-                    return oldTail;
-                }
+            Node t = tail;
+            if (t == null) { // Must initialize
+                if (compareAndSetHead(new Node()))
+                    tail = head;
             } else {
-                initializeSyncQueue();
+                node.prev = t;
+                if (compareAndSetTail(t, node)) {
+                    t.next = node;
+                    return t;
+                }
             }
         }
     }
@@ -605,20 +579,18 @@
      * @return the new node
      */
     private Node addWaiter(Node mode) {
-        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();
+        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;
             }
         }
+        enq(node);
+        return node;
     }
 
     /**
@@ -647,7 +619,7 @@
          */
         int ws = node.waitStatus;
         if (ws < 0)
-            node.compareAndSetWaitStatus(ws, 0);
+            compareAndSetWaitStatus(node, ws, 0);
 
         /*
          * Thread to unpark is held in successor, which is normally
@@ -658,9 +630,9 @@
         Node s = node.next;
         if (s == null || s.waitStatus > 0) {
             s = null;
-            for (Node p = tail; p != node && p != null; p = p.prev)
-                if (p.waitStatus <= 0)
-                    s = p;
+            for (Node t = tail; t != null && t != node; t = t.prev)
+                if (t.waitStatus <= 0)
+                    s = t;
         }
         if (s != null)
             LockSupport.unpark(s.thread);
@@ -688,12 +660,12 @@
             if (h != null && h != tail) {
                 int ws = h.waitStatus;
                 if (ws == Node.SIGNAL) {
-                    if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
+                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                         continue;            // loop to recheck cases
                     unparkSuccessor(h);
                 }
                 else if (ws == 0 &&
-                         !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
+                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                     continue;                // loop on failed CAS
             }
             if (h == head)                   // loop if head changed
@@ -715,8 +687,7 @@
         /*
          * Try to signal next queued node if:
          *   Propagation was indicated by caller,
-         *     or was recorded (as h.waitStatus either before
-         *     or after setHead) by a previous operation
+         *     or was recorded (as h.waitStatus) by a previous operation
          *     (note: this uses sign-check of waitStatus because
          *      PROPAGATE status may transition to SIGNAL.)
          * and
@@ -728,8 +699,7 @@
          * racing acquires/releases, so most need signals now or soon
          * anyway.
          */
-        if (propagate > 0 || h == null || h.waitStatus < 0 ||
-            (h = head) == null || h.waitStatus < 0) {
+        if (propagate > 0 || h == null || h.waitStatus < 0) {
             Node s = node.next;
             if (s == null || s.isShared())
                 doReleaseShared();
@@ -767,18 +737,18 @@
 
         // If we are the tail, remove ourselves.
         if (node == tail && compareAndSetTail(node, pred)) {
-            pred.compareAndSetNext(predNext, null);
+            compareAndSetNext(pred, 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 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
+                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                 pred.thread != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
-                    pred.compareAndSetNext(predNext, next);
+                    compareAndSetNext(pred, predNext, next);
             } else {
                 unparkSuccessor(node);
             }
@@ -819,7 +789,7 @@
              * need a signal, but don't park yet.  Caller will need to
              * retry to make sure it cannot acquire before parking.
              */
-            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
+            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
         }
         return false;
     }
@@ -832,7 +802,7 @@
     }
 
     /**
-     * Convenience method to park and then check if interrupted.
+     * Convenience method to park and then check if interrupted
      *
      * @return {@code true} if interrupted
      */
@@ -858,8 +828,8 @@
      * @param arg the acquire argument
      * @return {@code true} if interrupted while waiting
      */
-/// OPENJDK-9     @ReservedStackAccess
     final boolean acquireQueued(final Node node, int arg) {
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -867,15 +837,16 @@
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
+                    failed = false;
                     return interrupted;
                 }
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -886,21 +857,23 @@
     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();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -917,28 +890,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) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0L)
                     return false;
-                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -948,6 +921,7 @@
      */
     private void doAcquireShared(int arg) {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -959,6 +933,7 @@
                         p.next = null; // help GC
                         if (interrupted)
                             selfInterrupt();
+                        failed = false;
                         return;
                     }
                 }
@@ -966,9 +941,9 @@
                     parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -979,6 +954,7 @@
     private void doAcquireSharedInterruptibly(int arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -987,6 +963,7 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return;
                     }
                 }
@@ -994,9 +971,9 @@
                     parkAndCheckInterrupt())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -1013,6 +990,7 @@
             return false;
         final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -1021,23 +999,22 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return true;
                     }
                 }
                 nanosTimeout = deadline - System.nanoTime();
-                if (nanosTimeout <= 0L) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0L)
                     return false;
-                }
                 if (shouldParkAfterFailedAcquire(p, node) &&
-                    nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
-        } catch (Throwable t) {
-            cancelAcquire(node);
-            throw t;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
@@ -1191,7 +1168,6 @@
      *        {@link #tryAcquire} but is otherwise uninterpreted and
      *        can represent anything you like.
      */
-/// OPENJDK-9     @ReservedStackAccess
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1255,7 +1231,6 @@
      *        can represent anything you like.
      * @return the value returned from {@link #tryRelease}
      */
-/// OPENJDK-9     @ReservedStackAccess
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
@@ -1336,7 +1311,6 @@
      *        and can represent anything you like.
      * @return the value returned from {@link #tryReleaseShared}
      */
-/// OPENJDK-9     @ReservedStackAccess
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
             doReleaseShared();
@@ -1364,7 +1338,7 @@
 
     /**
      * Queries whether any threads have ever contended to acquire this
-     * synchronizer; that is, if an acquire method has ever blocked.
+     * synchronizer; that is if an acquire method has ever blocked.
      *
      * <p>In this implementation, this operation returns in
      * constant time.
@@ -1392,7 +1366,7 @@
     }
 
     /**
-     * Version of getFirstQueuedThread called when fastpath fails.
+     * Version of getFirstQueuedThread called when fastpath fails
      */
     private Thread fullGetFirstQueuedThread() {
         /*
@@ -1419,11 +1393,13 @@
          * guaranteeing termination.
          */
 
+        Node t = tail;
         Thread firstThread = null;
-        for (Node p = tail; p != null && p != head; p = p.prev) {
-            Thread t = p.thread;
-            if (t != null)
-                firstThread = t;
+        while (t != null && t != head) {
+            Thread tt = t.thread;
+            if (tt != null)
+                firstThread = tt;
+            t = t.prev;
         }
         return firstThread;
     }
@@ -1470,9 +1446,9 @@
      *
      * <p>An invocation of this method is equivalent to (but may be
      * more efficient than):
-     * <pre> {@code
-     * getFirstQueuedThread() != Thread.currentThread()
-     *   && hasQueuedThreads()}</pre>
+     *  <pre> {@code
+     * getFirstQueuedThread() != Thread.currentThread() &&
+     * hasQueuedThreads()}</pre>
      *
      * <p>Note that because cancellations due to interrupts and
      * timeouts may occur at any time, a {@code true} return does not
@@ -1490,7 +1466,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
@@ -1526,7 +1502,8 @@
      * 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
      */
@@ -1551,7 +1528,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             Thread t = p.thread;
             if (t != null)
@@ -1569,7 +1546,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             if (!p.isShared()) {
                 Thread t = p.thread;
@@ -1589,7 +1566,7 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getSharedQueuedThreads() {
-        ArrayList<Thread> list = new ArrayList<>();
+        ArrayList<Thread> list = new ArrayList<Thread>();
         for (Node p = tail; p != null; p = p.prev) {
             if (p.isShared()) {
                 Thread t = p.thread;
@@ -1610,9 +1587,10 @@
      * @return a string identifying this synchronizer, as well as its state
      */
     public String toString() {
-        return super.toString()
-            + "[State = " + getState() + ", "
-            + (hasQueuedThreads() ? "non" : "") + "empty queue]";
+        int s = getState();
+        String q  = hasQueuedThreads() ? "non" : "";
+        return super.toString() +
+            "[State = " + s + ", " + q + "empty queue]";
     }
 
 
@@ -1646,15 +1624,13 @@
      * @return true if present
      */
     private boolean findNodeFromTail(Node 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)
+        Node t = tail;
+        for (;;) {
+            if (t == node)
                 return true;
-            if (p == null)
+            if (t == null)
                 return false;
-            p = p.prev;
+            t = t.prev;
         }
     }
 
@@ -1669,7 +1645,7 @@
         /*
          * If cannot change waitStatus, the node has been cancelled.
          */
-        if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
+        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
             return false;
 
         /*
@@ -1680,7 +1656,7 @@
          */
         Node p = enq(node);
         int ws = p.waitStatus;
-        if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
+        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
@@ -1693,7 +1669,7 @@
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
-        if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
+        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
             enq(node);
             return true;
         }
@@ -1715,14 +1691,18 @@
      * @return previous sync state
      */
     final int fullyRelease(Node node) {
+        boolean failed = true;
         try {
             int savedState = getState();
-            if (release(savedState))
+            if (release(savedState)) {
+                failed = false;
                 return savedState;
-            throw new IllegalMonitorStateException();
-        } catch (Throwable t) {
-            node.waitStatus = Node.CANCELLED;
-            throw t;
+            } else {
+                throw new IllegalMonitorStateException();
+            }
+        } finally {
+            if (failed)
+                node.waitStatus = Node.CANCELLED;
         }
     }
 
@@ -1767,8 +1747,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 system
-     * state, not for synchronization control.
+     * waiters.  This method is designed for use in monitoring of the
+     * system state, not for synchronization control.
      *
      * @param condition the condition
      * @return the estimated number of waiting threads
@@ -1846,9 +1826,7 @@
                 unlinkCancelledWaiters();
                 t = lastWaiter;
             }
-
-            Node node = new Node(Node.CONDITION);
-
+            Node node = new Node(Thread.currentThread(), Node.CONDITION);
             if (t == null)
                 firstWaiter = node;
             else
@@ -1956,12 +1934,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() {
@@ -2015,14 +1993,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 {
@@ -2047,33 +2025,31 @@
         /**
          * 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 > SPIN_FOR_TIMEOUT_THRESHOLD)
+                if (nanosTimeout >= spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -2086,21 +2062,24 @@
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
             long remaining = deadline - System.nanoTime(); // avoid overflow
+            // BEGIN android-note Changed from < to <= http://b/24284239
+            // return (remaining < initialNanos) ? remaining : Long.MIN_VALUE;
             return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
+            // END android-note
         }
 
         /**
          * 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 +2092,7 @@
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
-                if (System.currentTimeMillis() >= abstime) {
+                if (System.currentTimeMillis() > abstime) {
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
@@ -2133,15 +2112,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,11 +2128,9 @@
             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)) {
@@ -2161,7 +2138,7 @@
                     timedout = transferAfterCancelledWait(node);
                     break;
                 }
-                if (nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
+                if (nanosTimeout >= spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
@@ -2190,7 +2167,7 @@
 
         /**
          * Queries whether any threads are waiting on this condition.
-         * Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.
+         * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.
          *
          * @return {@code true} if there are any waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -2209,7 +2186,7 @@
         /**
          * Returns an estimate of the number of threads waiting on
          * this condition.
-         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.
+         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.
          *
          * @return the estimated number of waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -2229,7 +2206,7 @@
         /**
          * Returns a collection containing those threads that may be
          * waiting on this Condition.
-         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.
+         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.
          *
          * @return the collection of threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
@@ -2238,7 +2215,7 @@
         protected final Collection<Thread> getWaitingThreads() {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
-            ArrayList<Thread> list = new ArrayList<>();
+            ArrayList<Thread> list = new ArrayList<Thread>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION) {
                     Thread t = w.thread;
@@ -2259,22 +2236,27 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    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;
+    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;
 
     static {
         try {
-            STATE = U.objectFieldOffset
+            stateOffset = unsafe.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
+            headOffset = unsafe.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
+            tailOffset = unsafe.objectFieldOffset
                 (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+            waitStatusOffset = unsafe.objectFieldOffset
+                (Node.class.getDeclaredField("waitStatus"));
+            nextOffset = unsafe.objectFieldOffset
+                (Node.class.getDeclaredField("next"));
+
+        } 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
@@ -2282,18 +2264,35 @@
     }
 
     /**
-     * Initializes head and tail fields on first contention.
+     * CAS head field. Used only by enq.
      */
-    private final void initializeSyncQueue() {
-        Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
-            tail = h;
+    private final boolean compareAndSetHead(Node update) {
+        return unsafe.compareAndSwapObject(this, headOffset, null, update);
     }
 
     /**
-     * CASes tail field.
+     * CAS tail field. Used only by enq.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+    }
+
+    /**
+     * CAS waitStatus field of a node.
+     */
+    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);
     }
 }
diff --git a/luni/src/main/java/java/util/concurrent/locks/Condition.java b/luni/src/main/java/java/util/concurrent/locks/Condition.java
index b3132e7..11a7090 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Condition.java
@@ -6,8 +6,8 @@
 
 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
@@ -98,7 +98,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 notify} methods invoked.
+ * {@link Object#notify notification} 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
@@ -280,7 +280,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();
@@ -333,7 +333,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
@@ -382,7 +382,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();
diff --git a/luni/src/main/java/java/util/concurrent/locks/Lock.java b/luni/src/main/java/java/util/concurrent/locks/Lock.java
index a2d7b48..a7ca001 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Lock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Lock.java
@@ -49,7 +49,7 @@
  * methods and statements. In most cases, the following idiom
  * should be used:
  *
- * <pre> {@code
+ *  <pre> {@code
  * Lock l = ...;
  * l.lock();
  * try {
@@ -93,9 +93,8 @@
  * <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="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>:
+ * <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>:
  * <ul>
  * <li>A successful {@code lock} operation has the same memory
  * synchronization effects as a successful <em>Lock</em> action.
@@ -213,7 +212,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 {
diff --git a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
index 694f4ca..089d818 100644
--- a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -6,6 +6,8 @@
 
 package java.util.concurrent.locks;
 
+import sun.misc.Unsafe;
+
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
@@ -17,10 +19,6 @@
  * 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
@@ -41,74 +39,73 @@
  * {@code blocker} object parameter. This object is recorded while
  * the thread is blocked to permit monitoring and diagnostic tools to
  * identify the reasons that threads are blocked. (Such tools may
- * access blockers using method {@link #getBlocker(Thread)}.)
- * The use of these forms rather than the original forms without this
- * parameter is strongly encouraged. The normal argument to supply as
- * a {@code blocker} within a lock implementation is {@code this}.
+ * access blockers using method {@link #getBlocker}.) The use of these
+ * forms rather than the original forms without this parameter is
+ * strongly encouraged. The normal argument to supply as a
+ * {@code blocker} within a lock implementation is {@code this}.
  *
  * <p>These methods are designed to be used as tools for creating
  * higher-level synchronization utilities, and are not in themselves
  * useful for most concurrency control applications.  The {@code park}
  * method is designed for use only in constructions of the form:
  *
- * <pre> {@code
- * while (!canProceed()) {
- *   // ensure request to unpark is visible to other threads
- *   ...
- *   LockSupport.park(this);
- * }}</pre>
+ *  <pre> {@code
+ * while (!canProceed()) { ... LockSupport.park(this); }}</pre>
  *
- * where no actions by the thread publishing a request to unpark,
- * prior to the call to {@code park}, entail locking or blocking.
- * Because only one permit is associated with each thread, any
- * intermediary uses of {@code park}, including implicitly via class
- * loading, could lead to an unresponsive thread (a "lost unpark").
+ * where neither {@code canProceed} nor any other actions prior to the
+ * call to {@code park} entail locking or blocking.  Because only one
+ * permit is associated with each thread, any intermediary uses of
+ * {@code park} could interfere with its intended effects.
  *
  * <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<>();
+ *     = new ConcurrentLinkedQueue<Thread>();
  *
  *   public void lock() {
  *     boolean wasInterrupted = false;
- *     // publish current thread for unparkers
- *     waiters.add(Thread.currentThread());
+ *     Thread current = Thread.currentThread();
+ *     waiters.add(current);
  *
  *     // Block while not first in queue or cannot acquire lock
- *     while (waiters.peek() != Thread.currentThread() ||
+ *     while (waiters.peek() != current ||
  *            !locked.compareAndSet(false, true)) {
  *       LockSupport.park(this);
- *       // ignore interrupts while waiting
- *       if (Thread.interrupted())
+ *       if (Thread.interrupted()) // ignore interrupts while waiting
  *         wasInterrupted = true;
  *     }
  *
  *     waiters.remove();
- *     // ensure correct interrupt status on return
- *     if (wasInterrupted)
- *       Thread.currentThread().interrupt();
+ *     if (wasInterrupted)          // reassert interrupt status on exit
+ *       current.interrupt();
  *   }
  *
  *   public void unlock() {
  *     locked.set(false);
  *     LockSupport.unpark(waiters.peek());
  *   }
- *
- *   static {
- *     // Reduce the risk of "lost unpark" due to classloading
- *     Class<?> ensureLoaded = LockSupport.class;
- *   }
  * }}</pre>
  */
 public class LockSupport {
     private LockSupport() {} // Cannot be instantiated.
 
+    // Hotspot implementation via intrinsics API
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long parkBlockerOffset;
+
+    static {
+        try {
+            parkBlockerOffset = unsafe.objectFieldOffset
+                (java.lang.Thread.class.getDeclaredField("parkBlocker"));
+        } catch (Exception ex) { throw new Error(ex); }
+    }
+
     private static void setBlocker(Thread t, Object arg) {
         // Even though volatile, hotspot doesn't need a write barrier here.
-        U.putObject(t, PARKBLOCKER, arg);
+        unsafe.putObject(t, parkBlockerOffset, arg);
     }
 
     /**
@@ -124,7 +121,7 @@
      */
     public static void unpark(Thread thread) {
         if (thread != null)
-            U.unpark(thread);
+            unsafe.unpark(thread);
     }
 
     /**
@@ -158,7 +155,7 @@
     public static void park(Object blocker) {
         Thread t = Thread.currentThread();
         setBlocker(t, blocker);
-        U.park(false, 0L);
+        unsafe.park(false, 0L);
         setBlocker(t, null);
     }
 
@@ -198,7 +195,7 @@
         if (nanos > 0) {
             Thread t = Thread.currentThread();
             setBlocker(t, blocker);
-            U.park(false, nanos);
+            unsafe.park(false, nanos);
             setBlocker(t, null);
         }
     }
@@ -239,7 +236,7 @@
     public static void parkUntil(Object blocker, long deadline) {
         Thread t = Thread.currentThread();
         setBlocker(t, blocker);
-        U.park(true, deadline);
+        unsafe.park(true, deadline);
         setBlocker(t, null);
     }
 
@@ -258,7 +255,7 @@
     public static Object getBlocker(Thread t) {
         if (t == null)
             throw new NullPointerException();
-        return U.getObjectVolatile(t, PARKBLOCKER);
+        return unsafe.getObjectVolatile(t, parkBlockerOffset);
     }
 
     /**
@@ -287,7 +284,7 @@
      * for example, the interrupt status of the thread upon return.
      */
     public static void park() {
-        U.park(false, 0L);
+        unsafe.park(false, 0L);
     }
 
     /**
@@ -321,7 +318,7 @@
      */
     public static void parkNanos(long nanos) {
         if (nanos > 0)
-            U.park(false, nanos);
+            unsafe.park(false, nanos);
     }
 
     /**
@@ -355,40 +352,6 @@
      *        to wait until
      */
     public static void parkUntil(long deadline) {
-        U.park(true, deadline);
+        unsafe.park(true, deadline);
     }
-
-    /**
-     * Returns the pseudo-randomly initialized or updated secondary seed.
-     * Copied from ThreadLocalRandom due to package access restrictions.
-     */
-    static final int nextSecondarySeed() {
-        int r;
-        Thread t = Thread.currentThread();
-        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
-        U.putInt(t, SECONDARY, r);
-        return r;
-    }
-
-    // Hotspot implementation via intrinsics API
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PARKBLOCKER;
-    private static final long SECONDARY;
-    static {
-        try {
-            PARKBLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-            SECONDARY = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
index a1a211a..8690355 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
@@ -9,9 +9,9 @@
 /**
  * A {@code ReadWriteLock} maintains a pair of associated {@link
  * Lock locks}, one for read-only operations and one for writing.
- * 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.
+ * 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.
  *
  * <p>All {@code ReadWriteLock} implementations must guarantee that
  * the memory synchronization effects of {@code writeLock} operations
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index 5fedcaa..3654248 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -6,9 +6,8 @@
 
 package java.util.concurrent.locks;
 
-import java.util.Collection;
 import java.util.concurrent.TimeUnit;
-/// OPENJDK-9 import jdk.internal.vm.annotation.ReservedStackAccess;
+import java.util.Collection;
 
 /**
  * A reentrant mutual exclusion {@link Lock} with the same basic
@@ -45,7 +44,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();
  *   // ...
@@ -99,7 +98,6 @@
          * Performs non-fair tryLock.  tryAcquire is implemented in
          * subclasses, but both need nonfair try for trylock method.
          */
-/// OPENJDK-9         @ReservedStackAccess
         final boolean nonfairTryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
@@ -119,7 +117,6 @@
             return false;
         }
 
-/// OPENJDK-9         @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             int c = getState() - releases;
             if (Thread.currentThread() != getExclusiveOwnerThread())
@@ -177,7 +174,6 @@
          * Performs lock.  Try immediate barge, backing up to normal
          * acquire on failure.
          */
-/// OPENJDK-9         @ReservedStackAccess
         final void lock() {
             if (compareAndSetState(0, 1))
                 setExclusiveOwnerThread(Thread.currentThread());
@@ -204,7 +200,6 @@
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
          */
-/// OPENJDK-9         @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
@@ -355,7 +350,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)) {
      *   ...
@@ -461,7 +456,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
@@ -488,7 +483,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();
      *   // ...
@@ -513,12 +508,12 @@
     /**
      * Queries if this lock is held by the current thread.
      *
-     * <p>Analogous to the {@link Thread#holdsLock(Object)} method for
-     * built-in monitor locks, this method is typically used for
-     * debugging and testing. For example, a method that should only be
-     * called while a lock is held can assert that this is the case:
+     * <p>Analogous to the {@link Thread#holdsLock} method for built-in
+     * monitor locks, this method is typically used for 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();
      *   // ...
@@ -532,7 +527,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();
      *   // ...
@@ -623,11 +618,12 @@
     }
 
     /**
-     * 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 system state, not for synchronization control.
+     * monitoring of the system state, not for synchronization
+     * control.
      *
      * @return the estimated number of threads waiting for this lock
      */
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 8969a54..cc7ba4c 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -6,8 +6,8 @@
 
 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
@@ -23,16 +23,15 @@
  *
  * <dl>
  * <dt><b><i>Non-fair mode (default)</i></b>
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * When constructed as non-fair (the default), the order of entry
+ * <dd>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.
+ * <p>
  *
  * <dt><b><i>Fair mode</i></b>
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * When constructed as fair, threads contend for entry using an
+ * <dd>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
@@ -54,6 +53,7 @@
  * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
  * do not honor this fair setting and will immediately acquire the lock
  * if it is possible, regardless of waiting threads.)
+ * <p>
  * </dl>
  *
  * <li><b>Reentrancy</b>
@@ -147,9 +147,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<>();
+ *   private final Map<String, Data> m = new TreeMap<String, Data>();
  *   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  *   private final Lock r = rwl.readLock();
  *   private final Lock w = rwl.writeLock();
@@ -159,9 +159,9 @@
  *     try { return m.get(key); }
  *     finally { r.unlock(); }
  *   }
- *   public List<String> allKeys() {
+ *   public String[] allKeys() {
  *     r.lock();
- *     try { return new ArrayList<>(m.keySet()); }
+ *     try { return m.keySet().toArray(); }
  *     finally { r.unlock(); }
  *   }
  *   public Data put(String key, Data value) {
@@ -247,9 +247,9 @@
          * Maintained as a ThreadLocal; cached in cachedHoldCounter.
          */
         static final class HoldCounter {
-            int count;          // initially 0
+            int count = 0;
             // Use id, not reference, to avoid garbage retention
-            final long tid = getThreadId(Thread.currentThread());
+            final long tid = Thread.currentThread().getId();
         }
 
         /**
@@ -392,7 +392,7 @@
                     firstReaderHoldCount--;
             } else {
                 HoldCounter rh = cachedHoldCounter;
-                if (rh == null || rh.tid != getThreadId(current))
+                if (rh == null || rh.tid != current.getId())
                     rh = readHolds.get();
                 int count = rh.count;
                 if (count <= 1) {
@@ -450,7 +450,7 @@
                     firstReaderHoldCount++;
                 } else {
                     HoldCounter rh = cachedHoldCounter;
-                    if (rh == null || rh.tid != getThreadId(current))
+                    if (rh == null || rh.tid != current.getId())
                         cachedHoldCounter = rh = readHolds.get();
                     else if (rh.count == 0)
                         readHolds.set(rh);
@@ -487,7 +487,7 @@
                     } else {
                         if (rh == null) {
                             rh = cachedHoldCounter;
-                            if (rh == null || rh.tid != getThreadId(current)) {
+                            if (rh == null || rh.tid != current.getId()) {
                                 rh = readHolds.get();
                                 if (rh.count == 0)
                                     readHolds.remove();
@@ -508,7 +508,7 @@
                     } else {
                         if (rh == null)
                             rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null || rh.tid != current.getId())
                             rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -564,7 +564,7 @@
                         firstReaderHoldCount++;
                     } else {
                         HoldCounter rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null || rh.tid != current.getId())
                             cachedHoldCounter = rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -615,7 +615,7 @@
                 return firstReaderHoldCount;
 
             HoldCounter rh = cachedHoldCounter;
-            if (rh != null && rh.tid == getThreadId(current))
+            if (rh != null && rh.tid == current.getId())
                 return rh.count;
 
             int count = readHolds.get().count;
@@ -677,7 +677,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
@@ -788,7 +788,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)) {
          *   ...
@@ -848,12 +848,7 @@
          * Attempts to release this lock.
          *
          * <p>If the number of readers is now zero then the lock
-         * 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
+         * is made available for write lock attempts.
          */
         public void unlock() {
             sync.releaseShared(1);
@@ -891,7 +886,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
@@ -1005,7 +1000,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();
         }
 
@@ -1025,7 +1020,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)) {
          *   ...
@@ -1140,7 +1135,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
@@ -1348,7 +1343,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 system state, not for
+     * designed for use in monitoring of the system state, not for
      * synchronization control.
      *
      * @return the estimated number of threads waiting for this lock
@@ -1461,26 +1456,4 @@
             "[Write locks = " + w + ", Read locks = " + r + "]";
     }
 
-    /**
-     * Returns the thread id for the given thread.  We must access
-     * this directly rather than via method Thread.getId() because
-     * getId() is not final, and has been known to be overridden in
-     * ways that do not preserve unique mappings.
-     */
-    static final long getThreadId(Thread thread) {
-        return U.getLongVolatile(thread, TID);
-    }
-
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long TID;
-    static {
-        try {
-            TID = U.objectFieldOffset
-                (Thread.class.getDeclaredField("tid"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/locks/StampedLock.java b/luni/src/main/java/java/util/concurrent/locks/StampedLock.java
deleted file mode 100644
index 1f4d54f..0000000
--- a/luni/src/main/java/java/util/concurrent/locks/StampedLock.java
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
- * 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.locks;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * A capability-based lock with three modes for controlling read/write
- * access.  The state of a StampedLock consists of a version and mode.
- * Lock acquisition methods return a stamp that represents and
- * controls access with respect to a lock state; "try" versions of
- * these methods may instead return the special value zero to
- * represent failure to acquire access. Lock release and conversion
- * methods require stamps as arguments, and fail if they do not match
- * the state of the lock. The three modes are:
- *
- * <ul>
- *
- *  <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
- *   waiting for exclusive access, returning a stamp that can be used
- *   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><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><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
- *   returns a non-zero stamp only if the lock is not currently held
- *   in write mode. Method {@link #validate} returns true if the lock
- *   has not been acquired in write mode since obtaining a given
- *   stamp.  This mode can be thought of as an extremely weak version
- *   of a read-lock, that can be broken by a writer at any time.  The
- *   use of optimistic mode for short read-only code segments often
- *   reduces contention and improves throughput.  However, its use is
- *   inherently fragile.  Optimistic read sections should only read
- *   fields and hold them in local variables for later use after
- *   validation. Fields read while in optimistic mode may be wildly
- *   inconsistent, so usage applies only when you are familiar enough
- *   with data representations to check consistency and/or repeatedly
- *   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.
- *
- * </ul>
- *
- * <p>This class also supports methods that conditionally provide
- * conversions across the three modes. For example, method {@link
- * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
- * a valid write stamp if (1) already in writing mode (2) in reading
- * mode and there are no other readers or (3) in optimistic mode and
- * the lock is available. The forms of these methods are designed to
- * help reduce some of the code bloat that otherwise occurs in
- * retry-based designs.
- *
- * <p>StampedLocks are designed for use as internal utilities in the
- * development of thread-safe components. Their use relies on
- * knowledge of the internal properties of the data, objects, and
- * methods they are protecting.  They are not reentrant, so locked
- * bodies should not call other unknown methods that may try to
- * re-acquire locks (although you may pass a stamp to other methods
- * that can use or convert it).  The use of read lock modes relies on
- * the associated code sections being side-effect-free.  Unvalidated
- * optimistic read sections cannot call methods that are not known to
- * tolerate potential inconsistencies.  Stamps use finite
- * representations, and are not cryptographically secure (i.e., a
- * valid stamp may be guessable). Stamp values may recycle after (no
- * sooner than) one year of continuous operation. A stamp held without
- * use or validation for longer than this period may fail to validate
- * correctly.  StampedLocks are serializable, but always deserialize
- * into initial unlocked state, so they are not useful for remote
- * locking.
- *
- * <p>The scheduling policy of StampedLock does not consistently
- * prefer readers over writers or vice versa.  All "try" methods are
- * best-effort and do not necessarily conform to any scheduling or
- * fairness policy. A zero return from any "try" method for acquiring
- * or converting locks does not carry any information about the state
- * of the lock; a subsequent invocation may succeed.
- *
- * <p>Because it supports coordinated usage across multiple lock
- * modes, this class does not directly implement the {@link Lock} or
- * {@link ReadWriteLock} interfaces. However, a StampedLock may be
- * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link
- * #asReadWriteLock()} in applications requiring only the associated
- * set of functionality.
- *
- * <p><b>Sample Usage.</b> The following illustrates some usage idioms
- * in a class that maintains simple two-dimensional points. The sample
- * code illustrates some try/catch conventions even though they are
- * not strictly needed here because no exceptions can occur in their
- * bodies.<br>
- *
- * <pre> {@code
- * class Point {
- *   private double x, y;
- *   private final StampedLock sl = new StampedLock();
- *
- *   void move(double deltaX, double deltaY) { // an exclusively locked method
- *     long stamp = sl.writeLock();
- *     try {
- *       x += deltaX;
- *       y += deltaY;
- *     } finally {
- *       sl.unlockWrite(stamp);
- *     }
- *   }
- *
- *   double distanceFromOrigin() { // A read-only method
- *     long stamp = sl.tryOptimisticRead();
- *     double currentX = x, currentY = y;
- *     if (!sl.validate(stamp)) {
- *        stamp = sl.readLock();
- *        try {
- *          currentX = x;
- *          currentY = y;
- *        } finally {
- *           sl.unlockRead(stamp);
- *        }
- *     }
- *     return Math.sqrt(currentX * currentX + currentY * currentY);
- *   }
- *
- *   void moveIfAtOrigin(double newX, double newY) { // upgrade
- *     // Could instead start with optimistic, not read mode
- *     long stamp = sl.readLock();
- *     try {
- *       while (x == 0.0 && y == 0.0) {
- *         long ws = sl.tryConvertToWriteLock(stamp);
- *         if (ws != 0L) {
- *           stamp = ws;
- *           x = newX;
- *           y = newY;
- *           break;
- *         }
- *         else {
- *           sl.unlockRead(stamp);
- *           stamp = sl.writeLock();
- *         }
- *       }
- *     } finally {
- *       sl.unlock(stamp);
- *     }
- *   }
- * }}</pre>
- *
- * @since 1.8
- * @author Doug Lea
- */
-public class StampedLock implements java.io.Serializable {
-    /*
-     * Algorithmic notes:
-     *
-     * The design employs elements of Sequence locks
-     * (as used in linux kernels; see Lameter's
-     * http://www.lameter.com/gelato2005.pdf
-     * and elsewhere; see
-     * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html)
-     * and Ordered RW locks (see Shirako et al
-     * http://dl.acm.org/citation.cfm?id=2312015)
-     *
-     * Conceptually, the primary state of the lock includes a sequence
-     * number that is odd when write-locked and even otherwise.
-     * However, this is offset by a reader count that is non-zero when
-     * read-locked.  The read count is ignored when validating
-     * "optimistic" seqlock-reader-style stamps.  Because we must use
-     * a small finite number of bits (currently 7) for readers, a
-     * supplementary reader overflow word is used when the number of
-     * readers exceeds the count field. We do this by treating the max
-     * reader count value (RBITS) as a spinlock protecting overflow
-     * updates.
-     *
-     * Waiters use a modified form of CLH lock used in
-     * AbstractQueuedSynchronizer (see its internal documentation for
-     * a fuller account), where each node is tagged (field mode) as
-     * either a reader or writer. Sets of waiting readers are grouped
-     * (linked) under a common node (field cowait) so act as a single
-     * node with respect to most CLH mechanics.  By virtue of the
-     * queue structure, wait nodes need not actually carry sequence
-     * numbers; we know each is greater than its predecessor.  This
-     * simplifies the scheduling policy to a mainly-FIFO scheme that
-     * incorporates elements of Phase-Fair locks (see Brandenburg &
-     * Anderson, especially http://www.cs.unc.edu/~bbb/diss/).  In
-     * particular, we use the phase-fair anti-barging rule: If an
-     * incoming reader arrives while read lock is held but there is a
-     * queued writer, this incoming reader is queued.  (This rule is
-     * responsible for some of the complexity of method acquireRead,
-     * but without it, the lock becomes highly unfair.) Method release
-     * does not (and sometimes cannot) itself wake up cowaiters. This
-     * is done by the primary thread, but helped by any other threads
-     * with nothing better to do in methods acquireRead and
-     * acquireWrite.
-     *
-     * These rules apply to threads actually queued. All tryLock forms
-     * opportunistically try to acquire locks regardless of preference
-     * rules, and so may "barge" their way in.  Randomized spinning is
-     * used in the acquire methods to reduce (increasingly expensive)
-     * context switching while also avoiding sustained memory
-     * thrashing among many threads.  We limit spins to the head of
-     * queue. A thread spin-waits up to SPINS times (where each
-     * iteration decreases spin count with 50% probability) before
-     * blocking. If, upon wakening it fails to obtain lock, and is
-     * still (or becomes) the first waiting thread (which indicates
-     * that some other thread barged and obtained lock), it escalates
-     * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
-     * continually losing to barging threads.
-     *
-     * Nearly all of these mechanics are carried out in methods
-     * acquireWrite and acquireRead, that, as typical of such code,
-     * sprawl out because actions and retries rely on consistent sets
-     * of locally cached reads.
-     *
-     * As noted in Boehm's paper (above), sequence validation (mainly
-     * method validate()) requires stricter ordering rules than apply
-     * to normal volatile reads (of "state").  To force orderings of
-     * reads before a validation and the validation itself in those
-     * cases where this is not already forced, we use
-     * Unsafe.loadFence.
-     *
-     * The memory layout keeps lock state and queue pointers together
-     * (normally on the same cache line). This usually works well for
-     * read-mostly loads. In most other cases, the natural tendency of
-     * adaptive-spin CLH locks to reduce memory contention lessens
-     * motivation to further spread out contended locations, but might
-     * be subject to future improvements.
-     */
-
-    private static final long serialVersionUID = -6001602636862214147L;
-
-    /** Number of processors, for spin control */
-    private static final int NCPU = Runtime.getRuntime().availableProcessors();
-
-    /** Maximum number of retries before enqueuing on acquisition */
-    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
-
-    /** Maximum number of retries before blocking at head on acquisition */
-    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
-
-    /** Maximum number of retries before re-blocking */
-    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
-
-    /** The period for yielding when waiting for overflow spinlock */
-    private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
-
-    /** The number of bits to use for reader count before overflowing */
-    private static final int LG_READERS = 7;
-
-    // Values for lock state and stamp operations
-    private static final long RUNIT = 1L;
-    private static final long WBIT  = 1L << LG_READERS;
-    private static final long RBITS = WBIT - 1L;
-    private static final long RFULL = RBITS - 1L;
-    private static final long ABITS = RBITS | WBIT;
-    private static final long SBITS = ~RBITS; // note overlap with ABITS
-
-    // Initial value for lock state; avoid failure value zero
-    private static final long ORIGIN = WBIT << 1;
-
-    // Special value from cancelled acquire methods so caller can throw IE
-    private static final long INTERRUPTED = 1L;
-
-    // Values for node status; order matters
-    private static final int WAITING   = -1;
-    private static final int CANCELLED =  1;
-
-    // Modes for nodes (int not boolean to allow arithmetic)
-    private static final int RMODE = 0;
-    private static final int WMODE = 1;
-
-    /** Wait nodes */
-    static final class WNode {
-        volatile WNode prev;
-        volatile WNode next;
-        volatile WNode cowait;    // list of linked readers
-        volatile Thread thread;   // non-null while possibly parked
-        volatile int status;      // 0, WAITING, or CANCELLED
-        final int mode;           // RMODE or WMODE
-        WNode(int m, WNode p) { mode = m; prev = p; }
-    }
-
-    /** Head of CLH queue */
-    private transient volatile WNode whead;
-    /** Tail (last) of CLH queue */
-    private transient volatile WNode wtail;
-
-    // views
-    transient ReadLockView readLockView;
-    transient WriteLockView writeLockView;
-    transient ReadWriteLockView readWriteLockView;
-
-    /** Lock sequence/state */
-    private transient volatile long state;
-    /** extra reader count when state read count saturated */
-    private transient int readerOverflow;
-
-    /**
-     * Creates a new lock, initially in unlocked state.
-     */
-    public StampedLock() {
-        state = ORIGIN;
-    }
-
-    /**
-     * Exclusively acquires the lock, blocking if necessary
-     * until available.
-     *
-     * @return a stamp that can be used to unlock or convert mode
-     */
-    public long writeLock() {
-        long s, next;  // bypass acquireWrite in fully unlocked case only
-        return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
-                next : acquireWrite(false, 0L));
-    }
-
-    /**
-     * Exclusively acquires the lock if it is immediately available.
-     *
-     * @return a stamp that can be used to unlock or convert mode,
-     * or zero if the lock is not available
-     */
-    public long tryWriteLock() {
-        long s, next;
-        return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
-                next : 0L);
-    }
-
-    /**
-     * Exclusively acquires the lock if it is available within the
-     * given time and the current thread has not been interrupted.
-     * Behavior under timeout and interruption matches that specified
-     * for method {@link Lock#tryLock(long,TimeUnit)}.
-     *
-     * @param time the maximum time to wait for the lock
-     * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
-     * or zero if the lock is not available
-     * @throws InterruptedException if the current thread is interrupted
-     * before acquiring the lock
-     */
-    public long tryWriteLock(long time, TimeUnit unit)
-        throws InterruptedException {
-        long nanos = unit.toNanos(time);
-        if (!Thread.interrupted()) {
-            long next, deadline;
-            if ((next = tryWriteLock()) != 0L)
-                return next;
-            if (nanos <= 0L)
-                return 0L;
-            if ((deadline = System.nanoTime() + nanos) == 0L)
-                deadline = 1L;
-            if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
-                return next;
-        }
-        throw new InterruptedException();
-    }
-
-    /**
-     * Exclusively acquires the lock, blocking if necessary
-     * until available or the current thread is interrupted.
-     * Behavior under interruption matches that specified
-     * for method {@link Lock#lockInterruptibly()}.
-     *
-     * @return a stamp that can be used to unlock or convert mode
-     * @throws InterruptedException if the current thread is interrupted
-     * before acquiring the lock
-     */
-    public long writeLockInterruptibly() throws InterruptedException {
-        long next;
-        if (!Thread.interrupted() &&
-            (next = acquireWrite(true, 0L)) != INTERRUPTED)
-            return next;
-        throw new InterruptedException();
-    }
-
-    /**
-     * Non-exclusively acquires the lock, blocking if necessary
-     * until available.
-     *
-     * @return a stamp that can be used to unlock or convert mode
-     */
-    public long readLock() {
-        long s = state, next;  // bypass acquireRead on common uncontended case
-        return ((whead == wtail && (s & ABITS) < RFULL &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
-                next : acquireRead(false, 0L));
-    }
-
-    /**
-     * Non-exclusively acquires the lock if it is immediately available.
-     *
-     * @return a stamp that can be used to unlock or convert mode,
-     * or zero if the lock is not available
-     */
-    public long tryReadLock() {
-        for (;;) {
-            long s, m, next;
-            if ((m = (s = state) & ABITS) == WBIT)
-                return 0L;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
-                    return next;
-            }
-            else if ((next = tryIncReaderOverflow(s)) != 0L)
-                return next;
-        }
-    }
-
-    /**
-     * Non-exclusively acquires the lock if it is available within the
-     * given time and the current thread has not been interrupted.
-     * Behavior under timeout and interruption matches that specified
-     * for method {@link Lock#tryLock(long,TimeUnit)}.
-     *
-     * @param time the maximum time to wait for the lock
-     * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
-     * or zero if the lock is not available
-     * @throws InterruptedException if the current thread is interrupted
-     * before acquiring the lock
-     */
-    public long tryReadLock(long time, TimeUnit unit)
-        throws InterruptedException {
-        long s, m, next, deadline;
-        long nanos = unit.toNanos(time);
-        if (!Thread.interrupted()) {
-            if ((m = (s = state) & ABITS) != WBIT) {
-                if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
-                        return next;
-                }
-                else if ((next = tryIncReaderOverflow(s)) != 0L)
-                    return next;
-            }
-            if (nanos <= 0L)
-                return 0L;
-            if ((deadline = System.nanoTime() + nanos) == 0L)
-                deadline = 1L;
-            if ((next = acquireRead(true, deadline)) != INTERRUPTED)
-                return next;
-        }
-        throw new InterruptedException();
-    }
-
-    /**
-     * Non-exclusively acquires the lock, blocking if necessary
-     * until available or the current thread is interrupted.
-     * Behavior under interruption matches that specified
-     * for method {@link Lock#lockInterruptibly()}.
-     *
-     * @return a stamp that can be used to unlock or convert mode
-     * @throws InterruptedException if the current thread is interrupted
-     * before acquiring the lock
-     */
-    public long readLockInterruptibly() throws InterruptedException {
-        long next;
-        if (!Thread.interrupted() &&
-            (next = acquireRead(true, 0L)) != INTERRUPTED)
-            return next;
-        throw new InterruptedException();
-    }
-
-    /**
-     * Returns a stamp that can later be validated, or zero
-     * if exclusively locked.
-     *
-     * @return a stamp, or zero if exclusively locked
-     */
-    public long tryOptimisticRead() {
-        long s;
-        return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
-    }
-
-    /**
-     * Returns true if the lock has not been exclusively acquired
-     * since issuance of the given stamp. Always returns false if the
-     * stamp is zero. Always returns true if the stamp represents a
-     * currently held lock. Invoking this method with a value not
-     * obtained from {@link #tryOptimisticRead} or a locking method
-     * for this lock has no defined effect or result.
-     *
-     * @param stamp a stamp
-     * @return {@code true} if the lock has not been exclusively acquired
-     * since issuance of the given stamp; else false
-     */
-    public boolean validate(long stamp) {
-        U.loadFence();
-        return (stamp & SBITS) == (state & SBITS);
-    }
-
-    /**
-     * If the lock state matches the given stamp, releases the
-     * exclusive lock.
-     *
-     * @param stamp a stamp returned by a write-lock operation
-     * @throws IllegalMonitorStateException if the stamp does
-     * not match the current state of this lock
-     */
-    public void unlockWrite(long stamp) {
-        WNode h;
-        if (state != stamp || (stamp & WBIT) == 0L)
-            throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (stamp += WBIT) == 0L ? ORIGIN : stamp);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
-    }
-
-    /**
-     * If the lock state matches the given stamp, releases the
-     * non-exclusive lock.
-     *
-     * @param stamp a stamp returned by a read-lock operation
-     * @throws IllegalMonitorStateException if the stamp does
-     * not match the current state of this lock
-     */
-    public void unlockRead(long stamp) {
-        long s, m; WNode h;
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS) ||
-                (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
-                throw new IllegalMonitorStateException();
-            if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    break;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                break;
-        }
-    }
-
-    /**
-     * If the lock state matches the given stamp, releases the
-     * corresponding mode of the lock.
-     *
-     * @param stamp a stamp returned by a lock operation
-     * @throws IllegalMonitorStateException if the stamp does
-     * not match the current state of this lock
-     */
-    public void unlock(long stamp) {
-        long a = stamp & ABITS, m, s; WNode h;
-        while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L)
-                break;
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return;
-            }
-            else if (a == 0L || a >= WBIT)
-                break;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    return;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                return;
-        }
-        throw new IllegalMonitorStateException();
-    }
-
-    /**
-     * 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.
-     * Or, if an optimistic read, returns a write stamp only if
-     * immediately available. This method returns zero in all other
-     * cases.
-     *
-     * @param stamp a stamp
-     * @return a valid write stamp, or zero on failure
-     */
-    public long tryConvertToWriteLock(long stamp) {
-        long a = stamp & ABITS, m, s, next;
-        while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
-                    break;
-                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
-                    return next;
-            }
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                return stamp;
-            }
-            else if (m == RUNIT && a != 0L) {
-                if (U.compareAndSwapLong(this, STATE, s,
-                                         next = s - RUNIT + WBIT))
-                    return next;
-            }
-            else
-                break;
-        }
-        return 0L;
-    }
-
-    /**
-     * 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
-     * returns a read stamp only if immediately available. This method
-     * returns zero in all other cases.
-     *
-     * @param stamp a stamp
-     * @return a valid read stamp, or zero on failure
-     */
-    public long tryConvertToReadLock(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
-        while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
-                    break;
-                else if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
-                        return next;
-                }
-                else if ((next = tryIncReaderOverflow(s)) != 0L)
-                    return next;
-            }
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE, next = s + (WBIT + RUNIT));
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
-            }
-            else if (a != 0L && a < WBIT)
-                return stamp;
-            else
-                break;
-        }
-        return 0L;
-    }
-
-    /**
-     * 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
-     * may be useful as a form of "tryUnlock".
-     *
-     * @param stamp a stamp
-     * @return a valid optimistic read stamp, or zero on failure
-     */
-    public long tryConvertToOptimisticRead(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
-        U.loadFence();
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS))
-                break;
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
-                    break;
-                return s;
-            }
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE,
-                                  next = (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
-            }
-            else if (a == 0L || a >= WBIT)
-                break;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    return next & SBITS;
-                }
-            }
-            else if ((next = tryDecReaderOverflow(s)) != 0L)
-                return next & SBITS;
-        }
-        return 0L;
-    }
-
-    /**
-     * Releases the write lock if it is held, without requiring a
-     * stamp value. This method may be useful for recovery after
-     * errors.
-     *
-     * @return {@code true} if the lock was held, else false
-     */
-    public boolean tryUnlockWrite() {
-        long s; WNode h;
-        if (((s = state) & WBIT) != 0L) {
-            U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-            if ((h = whead) != null && h.status != 0)
-                release(h);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Releases one hold of the read lock if it is held, without
-     * requiring a stamp value. This method may be useful for recovery
-     * after errors.
-     *
-     * @return {@code true} if the read lock was held, else false
-     */
-    public boolean tryUnlockRead() {
-        long s, m; WNode h;
-        while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
-            if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    return true;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                return true;
-        }
-        return false;
-    }
-
-    // status monitoring methods
-
-    /**
-     * Returns combined state-held and overflow read count for given
-     * state s.
-     */
-    private int getReadLockCount(long s) {
-        long readers;
-        if ((readers = s & RBITS) >= RFULL)
-            readers = RFULL + readerOverflow;
-        return (int) readers;
-    }
-
-    /**
-     * Returns {@code true} if the lock is currently held exclusively.
-     *
-     * @return {@code true} if the lock is currently held exclusively
-     */
-    public boolean isWriteLocked() {
-        return (state & WBIT) != 0L;
-    }
-
-    /**
-     * Returns {@code true} if the lock is currently held non-exclusively.
-     *
-     * @return {@code true} if the lock is currently held non-exclusively
-     */
-    public boolean isReadLocked() {
-        return (state & RBITS) != 0L;
-    }
-
-    /**
-     * Queries the number of read locks held for this lock. This
-     * method is designed for use in monitoring system state, not for
-     * synchronization control.
-     * @return the number of read locks held
-     */
-    public int getReadLockCount() {
-        return getReadLockCount(state);
-    }
-
-    /**
-     * Returns a string identifying this lock, as well as its lock
-     * state.  The state, in brackets, includes the String {@code
-     * "Unlocked"} or the String {@code "Write-locked"} or the String
-     * {@code "Read-locks:"} followed by the current number of
-     * read-locks held.
-     *
-     * @return a string identifying this lock, as well as its lock state
-     */
-    public String toString() {
-        long s = state;
-        return super.toString() +
-            ((s & ABITS) == 0L ? "[Unlocked]" :
-             (s & WBIT) != 0L ? "[Write-locked]" :
-             "[Read-locks:" + getReadLockCount(s) + "]");
-    }
-
-    // views
-
-    /**
-     * Returns a plain {@link Lock} view of this StampedLock in which
-     * the {@link Lock#lock} method is mapped to {@link #readLock},
-     * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
-     *
-     * @return the lock
-     */
-    public Lock asReadLock() {
-        ReadLockView v;
-        return ((v = readLockView) != null ? v :
-                (readLockView = new ReadLockView()));
-    }
-
-    /**
-     * Returns a plain {@link Lock} view of this StampedLock in which
-     * the {@link Lock#lock} method is mapped to {@link #writeLock},
-     * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
-     *
-     * @return the lock
-     */
-    public Lock asWriteLock() {
-        WriteLockView v;
-        return ((v = writeLockView) != null ? v :
-                (writeLockView = new WriteLockView()));
-    }
-
-    /**
-     * Returns a {@link ReadWriteLock} view of this StampedLock in
-     * which the {@link ReadWriteLock#readLock()} method is mapped to
-     * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to
-     * {@link #asWriteLock()}.
-     *
-     * @return the lock
-     */
-    public ReadWriteLock asReadWriteLock() {
-        ReadWriteLockView v;
-        return ((v = readWriteLockView) != null ? v :
-                (readWriteLockView = new ReadWriteLockView()));
-    }
-
-    // view classes
-
-    final class ReadLockView implements Lock {
-        public void lock() { readLock(); }
-        public void lockInterruptibly() throws InterruptedException {
-            readLockInterruptibly();
-        }
-        public boolean tryLock() { return tryReadLock() != 0L; }
-        public boolean tryLock(long time, TimeUnit unit)
-            throws InterruptedException {
-            return tryReadLock(time, unit) != 0L;
-        }
-        public void unlock() { unstampedUnlockRead(); }
-        public Condition newCondition() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    final class WriteLockView implements Lock {
-        public void lock() { writeLock(); }
-        public void lockInterruptibly() throws InterruptedException {
-            writeLockInterruptibly();
-        }
-        public boolean tryLock() { return tryWriteLock() != 0L; }
-        public boolean tryLock(long time, TimeUnit unit)
-            throws InterruptedException {
-            return tryWriteLock(time, unit) != 0L;
-        }
-        public void unlock() { unstampedUnlockWrite(); }
-        public Condition newCondition() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    final class ReadWriteLockView implements ReadWriteLock {
-        public Lock readLock() { return asReadLock(); }
-        public Lock writeLock() { return asWriteLock(); }
-    }
-
-    // Unlock methods without stamp argument checks for view classes.
-    // Needed because view-class lock methods throw away stamps.
-
-    final void unstampedUnlockWrite() {
-        WNode h; long s;
-        if (((s = state) & WBIT) == 0L)
-            throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
-    }
-
-    final void unstampedUnlockRead() {
-        for (;;) {
-            long s, m; WNode h;
-            if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
-                throw new IllegalMonitorStateException();
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    break;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                break;
-        }
-    }
-
-    private void readObject(java.io.ObjectInputStream s)
-        throws java.io.IOException, ClassNotFoundException {
-        s.defaultReadObject();
-        U.putLongVolatile(this, STATE, ORIGIN); // reset to unlocked state
-    }
-
-    // internals
-
-    /**
-     * Tries to increment readerOverflow by first setting state
-     * access bits value to RBITS, indicating hold of spinlock,
-     * then updating, then releasing.
-     *
-     * @param s a reader overflow stamp: (s & ABITS) >= RFULL
-     * @return new stamp on success, else zero
-     */
-    private long tryIncReaderOverflow(long s) {
-        // assert (s & ABITS) >= RFULL;
-        if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
-                ++readerOverflow;
-                U.putLongVolatile(this, STATE, s);
-                return s;
-            }
-        }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
-            Thread.yield();
-        return 0L;
-    }
-
-    /**
-     * Tries to decrement readerOverflow.
-     *
-     * @param s a reader overflow stamp: (s & ABITS) >= RFULL
-     * @return new stamp on success, else zero
-     */
-    private long tryDecReaderOverflow(long s) {
-        // assert (s & ABITS) >= RFULL;
-        if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
-                int r; long next;
-                if ((r = readerOverflow) > 0) {
-                    readerOverflow = r - 1;
-                    next = s;
-                }
-                else
-                    next = s - RUNIT;
-                U.putLongVolatile(this, STATE, next);
-                return next;
-            }
-        }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
-            Thread.yield();
-        return 0L;
-    }
-
-    /**
-     * Wakes up the successor of h (normally whead). This is normally
-     * just h.next, but may require traversal from wtail if next
-     * pointers are lagging. This may fail to wake up an acquiring
-     * thread when one or more have been cancelled, but the cancel
-     * methods themselves provide extra safeguards to ensure liveness.
-     */
-    private void release(WNode h) {
-        if (h != null) {
-            WNode q; Thread w;
-            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
-            if ((q = h.next) == null || q.status == CANCELLED) {
-                for (WNode t = wtail; t != null && t != h; t = t.prev)
-                    if (t.status <= 0)
-                        q = t;
-            }
-            if (q != null && (w = q.thread) != null)
-                U.unpark(w);
-        }
-    }
-
-    /**
-     * See above for explanation.
-     *
-     * @param interruptible true if should check interrupts and if so
-     * return INTERRUPTED
-     * @param deadline if nonzero, the System.nanoTime value to timeout
-     * at (and return zero)
-     * @return next state, or INTERRUPTED
-     */
-    private long acquireWrite(boolean interruptible, long deadline) {
-        WNode node = null, p;
-        for (int spins = -1;;) { // spin while enqueuing
-            long m, s, ns;
-            if ((m = (s = state) & ABITS) == 0L) {
-                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
-                    return ns;
-            }
-            else if (spins < 0)
-                spins = (m == WBIT && wtail == whead) ? SPINS : 0;
-            else if (spins > 0) {
-                if (LockSupport.nextSecondarySeed() >= 0)
-                    --spins;
-            }
-            else if ((p = wtail) == null) { // initialize queue
-                WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
-                    wtail = hd;
-            }
-            else if (node == null)
-                node = new WNode(WMODE, p);
-            else if (node.prev != p)
-                node.prev = p;
-            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
-                p.next = node;
-                break;
-            }
-        }
-
-        boolean wasInterrupted = false;
-        for (int spins = -1;;) {
-            WNode h, np, pp; int ps;
-            if ((h = whead) == p) {
-                if (spins < 0)
-                    spins = HEAD_SPINS;
-                else if (spins < MAX_HEAD_SPINS)
-                    spins <<= 1;
-                for (int k = spins;;) { // spin at head
-                    long s, ns;
-                    if (((s = state) & ABITS) == 0L) {
-                        if (U.compareAndSwapLong(this, STATE, s,
-                                                 ns = s + WBIT)) {
-                            whead = node;
-                            node.prev = null;
-                            if (wasInterrupted)
-                                Thread.currentThread().interrupt();
-                            return ns;
-                        }
-                    }
-                    else if (LockSupport.nextSecondarySeed() >= 0 &&
-                             --k <= 0)
-                        break;
-                }
-            }
-            else if (h != null) { // help release stale waiters
-                WNode c; Thread w;
-                while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
-                        (w = c.thread) != null)
-                        U.unpark(w);
-                }
-            }
-            if (whead == h) {
-                if ((np = node.prev) != p) {
-                    if (np != null)
-                        (p = np).next = node;   // stale
-                }
-                else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
-                else if (ps == CANCELLED) {
-                    if ((pp = p.prev) != null) {
-                        node.prev = pp;
-                        pp.next = node;
-                    }
-                }
-                else {
-                    long time; // 0 argument to park means no timeout
-                    if (deadline == 0L)
-                        time = 0L;
-                    else if ((time = deadline - System.nanoTime()) <= 0L)
-                        return cancelWaiter(node, node, false);
-                    Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
-                    node.thread = wt;
-                    if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);  // emulate LockSupport.park
-                    node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
-                    if (Thread.interrupted()) {
-                        if (interruptible)
-                            return cancelWaiter(node, node, true);
-                        wasInterrupted = true;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * See above for explanation.
-     *
-     * @param interruptible true if should check interrupts and if so
-     * return INTERRUPTED
-     * @param deadline if nonzero, the System.nanoTime value to timeout
-     * at (and return zero)
-     * @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;
-            if ((h = whead) == (p = wtail)) {
-                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)) {
-                        if (wasInterrupted)
-                            Thread.currentThread().interrupt();
-                        return ns;
-                    }
-                    else if (m >= WBIT) {
-                        if (spins > 0) {
-                            if (LockSupport.nextSecondarySeed() >= 0)
-                                --spins;
-                        }
-                        else {
-                            if (spins == 0) {
-                                WNode nh = whead, np = wtail;
-                                if ((nh == h && np == p) || (h = nh) != (p = np))
-                                    break;
-                            }
-                            spins = SPINS;
-                        }
-                    }
-                }
-            }
-            if (p == null) { // initialize queue
-                WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
-                    wtail = hd;
-            }
-            else if (node == null)
-                node = new WNode(RMODE, p);
-            else if (h == p || p.mode != RMODE) {
-                if (node.prev != p)
-                    node.prev = p;
-                else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
-                    p.next = node;
-                    break;
-                }
-            }
-            else if (!U.compareAndSwapObject(p, WCOWAIT,
-                                             node.cowait = p.cowait, node))
-                node.cowait = null;
-            else {
-                for (;;) {
-                    WNode pp, c; Thread w;
-                    if ((h = whead) != null && (c = h.cowait) != null &&
-                        U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
-                        (w = c.thread) != null) // help release
-                        U.unpark(w);
-                    if (h == (pp = p.prev) || h == p || pp == null) {
-                        long m, s, ns;
-                        do {
-                            if ((m = (s = state) & ABITS) < RFULL ?
-                                U.compareAndSwapLong(this, STATE, s,
-                                                     ns = s + RUNIT) :
-                                (m < WBIT &&
-                                 (ns = tryIncReaderOverflow(s)) != 0L)) {
-                                if (wasInterrupted)
-                                    Thread.currentThread().interrupt();
-                                return ns;
-                            }
-                        } while (m < WBIT);
-                    }
-                    if (whead == h && p.prev == pp) {
-                        long time;
-                        if (pp == null || h == p || p.status > 0) {
-                            node = null; // throw away
-                            break;
-                        }
-                        if (deadline == 0L)
-                            time = 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;
-                        if ((h != pp || (state & ABITS) == WBIT) &&
-                            whead == h && p.prev == pp)
-                            U.park(false, time);
-                        node.thread = null;
-                        U.putObject(wt, PARKBLOCKER, null);
-                        if (Thread.interrupted()) {
-                            if (interruptible)
-                                return cancelWaiter(node, p, true);
-                            wasInterrupted = true;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (int spins = -1;;) {
-            WNode h, np, pp; int ps;
-            if ((h = whead) == p) {
-                if (spins < 0)
-                    spins = HEAD_SPINS;
-                else if (spins < MAX_HEAD_SPINS)
-                    spins <<= 1;
-                for (int k = spins;;) { // spin at head
-                    long m, s, ns;
-                    if ((m = (s = state) & ABITS) < RFULL ?
-                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
-                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
-                        WNode c; Thread w;
-                        whead = node;
-                        node.prev = null;
-                        while ((c = node.cowait) != null) {
-                            if (U.compareAndSwapObject(node, WCOWAIT,
-                                                       c, c.cowait) &&
-                                (w = c.thread) != null)
-                                U.unpark(w);
-                        }
-                        if (wasInterrupted)
-                            Thread.currentThread().interrupt();
-                        return ns;
-                    }
-                    else if (m >= WBIT &&
-                             LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
-                        break;
-                }
-            }
-            else if (h != null) {
-                WNode c; Thread w;
-                while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
-                        (w = c.thread) != null)
-                        U.unpark(w);
-                }
-            }
-            if (whead == h) {
-                if ((np = node.prev) != p) {
-                    if (np != null)
-                        (p = np).next = node;   // stale
-                }
-                else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
-                else if (ps == CANCELLED) {
-                    if ((pp = p.prev) != null) {
-                        node.prev = pp;
-                        pp.next = node;
-                    }
-                }
-                else {
-                    long time;
-                    if (deadline == 0L)
-                        time = 0L;
-                    else if ((time = deadline - System.nanoTime()) <= 0L)
-                        return cancelWaiter(node, node, false);
-                    Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
-                    node.thread = wt;
-                    if (p.status < 0 &&
-                        (p != h || (state & ABITS) == WBIT) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);
-                    node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
-                    if (Thread.interrupted()) {
-                        if (interruptible)
-                            return cancelWaiter(node, node, true);
-                        wasInterrupted = true;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * If node non-null, forces cancel status and unsplices it from
-     * queue if possible and wakes up any cowaiters (of the node, or
-     * group, as applicable), and in any case helps release current
-     * first waiter if lock is free. (Calling with null arguments
-     * serves as a conditional form of release, which is not currently
-     * needed but may be needed under possible future cancellation
-     * policies). This is a variant of cancellation methods in
-     * AbstractQueuedSynchronizer (see its detailed explanation in AQS
-     * internal documentation).
-     *
-     * @param node if nonnull, the waiter
-     * @param group either node or the group node is cowaiting with
-     * @param interrupted if already interrupted
-     * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
-     */
-    private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
-        if (node != null && group != null) {
-            Thread w;
-            node.status = CANCELLED;
-            // unsplice cancelled nodes from group
-            for (WNode p = group, q; (q = p.cowait) != null;) {
-                if (q.status == CANCELLED) {
-                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
-                    p = group; // restart
-                }
-                else
-                    p = q;
-            }
-            if (group == node) {
-                for (WNode r = group.cowait; r != null; r = r.cowait) {
-                    if ((w = r.thread) != null)
-                        U.unpark(w);       // wake up uncancelled co-waiters
-                }
-                for (WNode pred = node.prev; pred != null; ) { // unsplice
-                    WNode succ, pp;        // find valid successor
-                    while ((succ = node.next) == null ||
-                           succ.status == CANCELLED) {
-                        WNode q = null;    // find successor the slow way
-                        for (WNode t = wtail; t != null && t != node; t = t.prev)
-                            if (t.status != CANCELLED)
-                                q = t;     // don't link if succ cancelled
-                        if (succ == q ||   // ensure accurate successor
-                            U.compareAndSwapObject(node, WNEXT,
-                                                   succ, succ = q)) {
-                            if (succ == null && node == wtail)
-                                U.compareAndSwapObject(this, WTAIL, node, pred);
-                            break;
-                        }
-                    }
-                    if (pred.next == node) // unsplice pred link
-                        U.compareAndSwapObject(pred, WNEXT, node, succ);
-                    if (succ != null && (w = succ.thread) != null) {
-                        succ.thread = null;
-                        U.unpark(w);       // wake up succ to observe new pred
-                    }
-                    if (pred.status != CANCELLED || (pp = pred.prev) == null)
-                        break;
-                    node.prev = pp;        // repeat if new pred wrong/cancelled
-                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
-                    pred = pp;
-                }
-            }
-        }
-        WNode h; // Possibly release first waiter
-        while ((h = whead) != null) {
-            long s; WNode q; // similar to release() but check eligibility
-            if ((q = h.next) == null || q.status == CANCELLED) {
-                for (WNode t = wtail; t != null && t != h; t = t.prev)
-                    if (t.status <= 0)
-                        q = t;
-            }
-            if (h == whead) {
-                if (q != null && h.status == 0 &&
-                    ((s = state) & ABITS) != WBIT && // waiter is eligible
-                    (s == 0L || q.mode == RMODE))
-                    release(h);
-                break;
-            }
-        }
-        return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
-    }
-
-    // Unsafe mechanics
-    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;
-    private static final long WNEXT;
-    private static final long WSTATUS;
-    private static final long WCOWAIT;
-    private static final long PARKBLOCKER;
-
-    static {
-        try {
-            STATE = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("state"));
-            WHEAD = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("whead"));
-            WTAIL = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("wtail"));
-
-            WSTATUS = U.objectFieldOffset
-                (WNode.class.getDeclaredField("status"));
-            WNEXT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("next"));
-            WCOWAIT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("cowait"));
-
-            PARKBLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-}
diff --git a/luni/src/main/java/java/util/concurrent/package-info.java b/luni/src/main/java/java/util/concurrent/package-info.java
index 5dc1228..afc8ca4 100644
--- a/luni/src/main/java/java/util/concurrent/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/package-info.java
@@ -181,25 +181,18 @@
  * collections are unshared, or are accessible only when
  * holding other locks.
  *
- * <p id="Weakly">Most concurrent Collection implementations
- * (including most Queues) also differ from the usual {@code java.util}
- * conventions in that their {@linkplain java.util.Iterator Iterators}
- * and {@linkplain java.util.Spliterator Spliterators} provide
- * <em>weakly consistent</em> rather than fast-fail traversal:
- * <ul>
- * <li>they may proceed concurrently with other operations
- * <li>they will never throw {@link java.util.ConcurrentModificationException
- * ConcurrentModificationException}
- * <li>they are guaranteed to traverse elements as they existed upon
- * construction exactly once, and may (but are not guaranteed to)
- * reflect any modifications subsequent to construction.
- * </ul>
+ * <p>Most concurrent Collection implementations (including most
+ * Queues) also differ from the usual java.util conventions in that
+ * their Iterators provide <em>weakly consistent</em> rather than
+ * fast-fail traversal.  A weakly consistent iterator is thread-safe,
+ * but does not necessarily freeze the collection while iterating, so
+ * it may (or may not) reflect any updates since the iterator was
+ * created.
  *
  * <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
  *
- * <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
+ * <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
  * <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
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index 104a6f3..0c5502b 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -88,10 +88,7 @@
   luni/src/main/java/java/util/concurrent/BrokenBarrierException.java \
   luni/src/main/java/java/util/concurrent/Callable.java \
   luni/src/main/java/java/util/concurrent/CancellationException.java \
-  luni/src/main/java/java/util/concurrent/CompletableFuture.java \
-  luni/src/main/java/java/util/concurrent/CompletionException.java \
   luni/src/main/java/java/util/concurrent/CompletionService.java \
-  luni/src/main/java/java/util/concurrent/CompletionStage.java \
   luni/src/main/java/java/util/concurrent/ConcurrentHashMap.java \
   luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java \
   luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java \
@@ -117,7 +114,6 @@
   luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java \
   luni/src/main/java/java/util/concurrent/Future.java \
   luni/src/main/java/java/util/concurrent/FutureTask.java \
-  luni/src/main/java/java/util/concurrent/Helpers.java \
   luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java \
   luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java \
   luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java \
@@ -152,11 +148,7 @@
   luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java \
   luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java \
   luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java \
-  luni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java \
-  luni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java \
-  luni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java \
-  luni/src/main/java/java/util/concurrent/atomic/LongAdder.java \
-  luni/src/main/java/java/util/concurrent/atomic/Striped64.java \
+  luni/src/main/java/java/util/concurrent/atomic/Fences.java \
   luni/src/main/java/java/util/concurrent/atomic/package-info.java \
   luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java \
   luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \
@@ -167,7 +159,6 @@
   luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java \
   luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java \
   luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java \
-  luni/src/main/java/java/util/concurrent/locks/StampedLock.java \
   luni/src/main/java/java/util/concurrent/locks/package-info.java \
   luni/src/main/java/java/util/concurrent/package-info.java \
   luni/src/main/java/javax/xml/XMLConstants.java \
diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java
index c14022b..2afeccf 100755
--- a/ojluni/src/main/java/java/lang/Thread.java
+++ b/ojluni/src/main/java/java/lang/Thread.java
@@ -2050,25 +2050,6 @@
         }
     }
 
-
-    // The following three initially uninitialized fields are exclusively
-    // managed by class java.util.concurrent.ThreadLocalRandom. These
-    // fields are used to build the high-performance PRNGs in the
-    // concurrent code, and we can not risk accidental false sharing.
-    // Hence, the fields are isolated with @Contended.
-
-    /** The current seed for a ThreadLocalRandom */
-    // @sun.misc.Contended("tlr")
-    long threadLocalRandomSeed;
-
-    /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
-    // @sun.misc.Contended("tlr")
-    int threadLocalRandomProbe;
-
-    /** Secondary seed isolated from public ThreadLocalRandom sequence */
-    //  @sun.misc.Contended("tlr")
-    int threadLocalRandomSecondarySeed;
-
     /* Some private helper methods */
     private native void nativeSetName(String newName);
 
diff --git a/ojluni/src/main/java/java/util/AbstractQueue.java b/ojluni/src/main/java/java/util/AbstractQueue.java
index 44e11f7..ebe2700 100644
--- a/ojluni/src/main/java/java/util/AbstractQueue.java
+++ b/ojluni/src/main/java/java/util/AbstractQueue.java
@@ -58,7 +58,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public abstract class AbstractQueue<E>
     extends AbstractCollection<E>
diff --git a/ojluni/src/main/java/java/util/ArrayDeque.java b/ojluni/src/main/java/java/util/ArrayDeque.java
index 83ae076..eb31bcc 100644
--- a/ojluni/src/main/java/java/util/ArrayDeque.java
+++ b/ojluni/src/main/java/java/util/ArrayDeque.java
@@ -33,7 +33,7 @@
 
 package java.util;
 
-import java.io.Serializable;
+import java.io.*;
 import java.util.function.Consumer;
 
 // BEGIN android-note
@@ -81,10 +81,10 @@
  *
  * @author  Josh Bloch and Doug Lea
  * @since   1.6
- * @param <E> the type of elements held in this deque
+ * @param <E> the type of elements held in this collection
  */
 public class ArrayDeque<E> extends AbstractCollection<E>
-                           implements Deque<E>, Cloneable, Serializable
+                           implements Deque<E>, Cloneable, java.io.Serializable
 {
     /**
      * The array in which the elements of the deque are stored.
@@ -96,20 +96,20 @@
      * other.  We also guarantee that all array cells not holding
      * deque elements are always null.
      */
-    transient Object[] elements; // non-private to simplify nested class access
+    private transient Object[] elements;
 
     /**
      * The index of the element at the head of the deque (which is the
      * element that would be removed by remove() or pop()); or an
      * arbitrary number equal to tail if the deque is empty.
      */
-    transient int head;
+    private transient int head;
 
     /**
      * The index at which the next element would be added to the tail
      * of the deque (via addLast(E), add(E), or push(E)).
      */
-    transient int tail;
+    private transient int tail;
 
     /**
      * The minimum capacity that we'll use for a newly created deque.
@@ -137,8 +137,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];
     }
@@ -275,27 +275,25 @@
     }
 
     public E pollFirst() {
-        final Object[] elements = this.elements;
-        final int h = head;
+        int h = head;
         @SuppressWarnings("unchecked")
         E result = (E) elements[h];
         // Element is null if deque empty
-        if (result != null) {
-            elements[h] = null; // Must null out slot
-            head = (h + 1) & (elements.length - 1);
-        }
+        if (result == null)
+            return null;
+        elements[h] = null;     // Must null out slot
+        head = (h + 1) & (elements.length - 1);
         return result;
     }
 
     public E pollLast() {
-        final Object[] elements = this.elements;
-        final int t = (tail - 1) & (elements.length - 1);
+        int t = (tail - 1) & (elements.length - 1);
         @SuppressWarnings("unchecked")
         E result = (E) elements[t];
-        if (result != null) {
-            elements[t] = null;
-            tail = t;
-        }
+        if (result == null)
+            return null;
+        elements[t] = null;
+        tail = t;
         return result;
     }
 
@@ -345,15 +343,17 @@
      * @return {@code true} if the deque contained the specified element
      */
     public boolean removeFirstOccurrence(Object o) {
-        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;
-                }
+        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;
             }
+            i = (i + 1) & mask;
         }
         return false;
     }
@@ -371,15 +371,17 @@
      * @return {@code true} if the deque contained the specified element
      */
     public boolean removeLastOccurrence(Object o) {
-        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;
-                }
+        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;
             }
+            i = (i - 1) & mask;
         }
         return false;
     }
@@ -499,11 +501,11 @@
     }
 
     private void checkInvariants() {
-        assert elements[tail] == null;
-        assert head == tail ? elements[head] == null :
-            (elements[head] != null &&
-             elements[(tail - 1) & (elements.length - 1)] != null);
-        assert elements[(head - 1) & (elements.length - 1)] == null;
+        // assert elements[tail] == null;
+        // assert head == tail ? elements[head] == null :
+        //     (elements[head] != null &&
+        //      elements[(tail - 1) & (elements.length - 1)] != null);
+        // assert elements[(head - 1) & (elements.length - 1)] == null;
     }
 
     /**
@@ -516,8 +518,8 @@
      *
      * @return true if elements moved backwards
      */
-    boolean delete(int i) {
-        checkInvariants();
+    private boolean delete(int i) {
+        //checkInvariants();
         final Object[] elements = this.elements;
         final int mask = elements.length - 1;
         final int h = head;
@@ -702,13 +704,15 @@
      * @return {@code true} if this deque contains the specified element
      */
     public boolean contains(Object o) {
-        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;
-            }
+        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;
         }
         return false;
     }
@@ -721,7 +725,7 @@
      * 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)}.
+     * <p>This method is equivalent to {@link #removeFirstOccurrence}.
      *
      * @param o element to be removed from this deque, if present
      * @return {@code true} if this deque contained the specified element
@@ -794,7 +798,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()}.
@@ -852,8 +856,6 @@
     /**
      * 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.
@@ -873,10 +875,6 @@
 
     /**
      * 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 {
@@ -915,7 +913,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;
@@ -937,7 +935,7 @@
                 if (h > t)
                     t += n;
                 int m = ((h + t) >>> 1) & (n - 1);
-                return new DeqSpliterator<E>(deq, h, index = m);
+                return new DeqSpliterator<>(deq, h, index = m);
             }
             return null;
         }
@@ -962,7 +960,7 @@
                 throw new NullPointerException();
             Object[] a = deq.elements;
             int m = a.length - 1, f = getFence(), i = index;
-            if (i != f) {
+            if (i != fence) {
                 @SuppressWarnings("unchecked") E e = (E)a[i];
                 index = (i + 1) & m;
                 if (e == null)
diff --git a/ojluni/src/main/java/java/util/ArrayPrefixHelpers.java b/ojluni/src/main/java/java/util/ArrayPrefixHelpers.java
deleted file mode 100644
index d3b5614..0000000
--- a/ojluni/src/main/java/java/util/ArrayPrefixHelpers.java
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * 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;
-
-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;
-
-/**
- * ForkJoin tasks to perform Arrays.parallelPrefix operations.
- *
- * @author Doug Lea
- * @since 1.8
- */
-class ArrayPrefixHelpers {
-    private ArrayPrefixHelpers() {} // non-instantiable
-
-    /*
-     * Parallel prefix (aka cumulate, scan) task classes
-     * are based loosely on Guy Blelloch's original
-     * algorithm (http://www.cs.cmu.edu/~scandal/alg/scan.html):
-     *  Keep dividing by two to threshold segment size, and then:
-     *   Pass 1: Create tree of partial sums for each segment
-     *   Pass 2: For each segment, cumulate with offset of left sibling
-     *
-     * This version improves performance within FJ framework mainly by
-     * allowing the second pass of ready left-hand sides to proceed
-     * even if some right-hand side first passes are still executing.
-     * It also combines first and second pass for leftmost segment,
-     * and skips the first pass for rightmost segment (whose result is
-     * not needed for second pass).  It similarly manages to avoid
-     * requiring that users supply an identity basis for accumulations
-     * by tracking those segments/subtasks for which the first
-     * existing element is used as base.
-     *
-     * Managing this relies on ORing some bits in the pendingCount for
-     * phases/states: CUMULATE, SUMMED, and FINISHED. CUMULATE is the
-     * main phase bit. When false, segments compute only their sum.
-     * When true, they cumulate array elements. CUMULATE is set at
-     * root at beginning of second pass and then propagated down. But
-     * it may also be set earlier for subtrees with lo==0 (the left
-     * spine of tree). SUMMED is a one bit join count. For leafs, it
-     * is set when summed. For internal nodes, it becomes true when
-     * one child is summed.  When the second child finishes summing,
-     * we then moves up tree to trigger the cumulate phase. FINISHED
-     * is also a one bit join count. For leafs, it is set when
-     * cumulated. For internal nodes, it becomes true when one child
-     * is cumulated.  When the second child finishes cumulating, it
-     * then moves up tree, completing at the root.
-     *
-     * To better exploit locality and reduce overhead, the compute
-     * method loops starting with the current task, moving if possible
-     * to one of its subtasks rather than forking.
-     *
-     * As usual for this sort of utility, there are 4 versions, that
-     * are simple copy/paste/adapt variants of each other.  (The
-     * double and int versions differ from long version solely by
-     * replacing "long" (with case-matching)).
-     */
-
-    // see above
-    static final int CUMULATE = 1;
-    static final int SUMMED   = 2;
-    static final int FINISHED = 4;
-
-    /** The smallest subtask array partition size to use as threshold */
-    static final int MIN_PARTITION = 16;
-
-    static final class CumulateTask<T> extends CountedCompleter<Void> {
-        final T[] array;
-        final BinaryOperator<T> function;
-        CumulateTask<T> left, right;
-        T in, out;
-        final int lo, hi, origin, fence, threshold;
-
-        /** Root task constructor */
-        public CumulateTask(CumulateTask<T> parent,
-                            BinaryOperator<T> function,
-                            T[] array, int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            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;
-        }
-
-        /** Subtask constructor */
-        CumulateTask(CumulateTask<T> parent, BinaryOperator<T> function,
-                     T[] array, int origin, int fence, int threshold,
-                     int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            this.origin = origin; this.fence = fence;
-            this.threshold = threshold;
-            this.lo = lo; this.hi = hi;
-        }
-
-        public final void compute() {
-            final BinaryOperator<T> fn;
-            final T[] a;
-            if ((fn = this.function) == null || (a = this.array) == null)
-                throw new NullPointerException();    // hoist checks
-            int th = threshold, org = origin, fnc = fence, l, h;
-            CumulateTask<T> t = this;
-            outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
-                if (h - l > th) {
-                    CumulateTask<T> lt = t.left, rt = t.right, f;
-                    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);
-                    }
-                    else {                           // possibly refork
-                        T pin = t.in;
-                        lt.in = pin;
-                        f = t = null;
-                        if (rt != null) {
-                            T lout = lt.out;
-                            rt.in = (l == org ? lout :
-                                     fn.apply(pin, lout));
-                            for (int c;;) {
-                                if (((c = rt.getPendingCount()) & CUMULATE) != 0)
-                                    break;
-                                if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
-                                    t = rt;
-                                    break;
-                                }
-                            }
-                        }
-                        for (int c;;) {
-                            if (((c = lt.getPendingCount()) & CUMULATE) != 0)
-                                break;
-                            if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
-                                if (t != null)
-                                    f = t;
-                                t = lt;
-                                break;
-                            }
-                        }
-                        if (t == null)
-                            break;
-                    }
-                    if (f != null)
-                        f.fork();
-                }
-                else {
-                    int state; // Transition to sum, cumulate, or both
-                    for (int b;;) {
-                        if (((b = t.getPendingCount()) & FINISHED) != 0)
-                            break outer;                      // already done
-                        state = ((b & CUMULATE) != 0 ? FINISHED :
-                                 (l > org) ? SUMMED : (SUMMED|FINISHED));
-                        if (t.compareAndSetPendingCount(b, b|state))
-                            break;
-                    }
-
-                    T sum;
-                    if (state != SUMMED) {
-                        int first;
-                        if (l == org) {                       // leftmost; no in
-                            sum = a[org];
-                            first = org + 1;
-                        }
-                        else {
-                            sum = t.in;
-                            first = l;
-                        }
-                        for (int i = first; i < h; ++i)       // cumulate
-                            a[i] = sum = fn.apply(sum, a[i]);
-                    }
-                    else if (h < fnc) {                       // skip rightmost
-                        sum = a[l];
-                        for (int i = l + 1; i < h; ++i)       // sum only
-                            sum = fn.apply(sum, a[i]);
-                    }
-                    else
-                        sum = t.in;
-                    t.out = sum;
-                    for (CumulateTask<T> par;;) {             // propagate
-                        @SuppressWarnings("unchecked") CumulateTask<T> partmp
-                            = (CumulateTask<T>)t.getCompleter();
-                        if ((par = partmp) == null) {
-                            if ((state & FINISHED) != 0)      // enable join
-                                t.quietlyComplete();
-                            break outer;
-                        }
-                        int b = par.getPendingCount();
-                        if ((b & state & FINISHED) != 0)
-                            t = par;                          // both done
-                        else if ((b & state & SUMMED) != 0) { // both summed
-                            int nextState; CumulateTask<T> lt, rt;
-                            if ((lt = par.left) != null &&
-                                (rt = par.right) != null) {
-                                T lout = lt.out;
-                                par.out = (rt.hi == fnc ? lout :
-                                           fn.apply(lout, rt.out));
-                            }
-                            int refork = (((b & CUMULATE) == 0 &&
-                                           par.lo == org) ? CUMULATE : 0);
-                            if ((nextState = b|state|refork) == b ||
-                                par.compareAndSetPendingCount(b, nextState)) {
-                                state = SUMMED;               // drop finished
-                                t = par;
-                                if (refork != 0)
-                                    par.fork();
-                            }
-                        }
-                        else if (par.compareAndSetPendingCount(b, b|state))
-                            break outer;                      // sib not ready
-                    }
-                }
-            }
-        }
-        private static final long serialVersionUID = 5293554502939613543L;
-    }
-
-    static final class LongCumulateTask extends CountedCompleter<Void> {
-        final long[] array;
-        final LongBinaryOperator function;
-        LongCumulateTask left, right;
-        long in, out;
-        final int lo, hi, origin, fence, threshold;
-
-        /** Root task constructor */
-        public LongCumulateTask(LongCumulateTask parent,
-                                LongBinaryOperator function,
-                                long[] array, int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            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;
-        }
-
-        /** Subtask constructor */
-        LongCumulateTask(LongCumulateTask parent, LongBinaryOperator function,
-                         long[] array, int origin, int fence, int threshold,
-                         int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            this.origin = origin; this.fence = fence;
-            this.threshold = threshold;
-            this.lo = lo; this.hi = hi;
-        }
-
-        public final void compute() {
-            final LongBinaryOperator fn;
-            final long[] a;
-            if ((fn = this.function) == null || (a = this.array) == null)
-                throw new NullPointerException();    // hoist checks
-            int th = threshold, org = origin, fnc = fence, l, h;
-            LongCumulateTask t = this;
-            outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
-                if (h - l > th) {
-                    LongCumulateTask lt = t.left, rt = t.right, f;
-                    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);
-                    }
-                    else {                           // possibly refork
-                        long pin = t.in;
-                        lt.in = pin;
-                        f = t = null;
-                        if (rt != null) {
-                            long lout = lt.out;
-                            rt.in = (l == org ? lout :
-                                     fn.applyAsLong(pin, lout));
-                            for (int c;;) {
-                                if (((c = rt.getPendingCount()) & CUMULATE) != 0)
-                                    break;
-                                if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
-                                    t = rt;
-                                    break;
-                                }
-                            }
-                        }
-                        for (int c;;) {
-                            if (((c = lt.getPendingCount()) & CUMULATE) != 0)
-                                break;
-                            if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
-                                if (t != null)
-                                    f = t;
-                                t = lt;
-                                break;
-                            }
-                        }
-                        if (t == null)
-                            break;
-                    }
-                    if (f != null)
-                        f.fork();
-                }
-                else {
-                    int state; // Transition to sum, cumulate, or both
-                    for (int b;;) {
-                        if (((b = t.getPendingCount()) & FINISHED) != 0)
-                            break outer;                      // already done
-                        state = ((b & CUMULATE) != 0 ? FINISHED :
-                                 (l > org) ? SUMMED : (SUMMED|FINISHED));
-                        if (t.compareAndSetPendingCount(b, b|state))
-                            break;
-                    }
-
-                    long sum;
-                    if (state != SUMMED) {
-                        int first;
-                        if (l == org) {                       // leftmost; no in
-                            sum = a[org];
-                            first = org + 1;
-                        }
-                        else {
-                            sum = t.in;
-                            first = l;
-                        }
-                        for (int i = first; i < h; ++i)       // cumulate
-                            a[i] = sum = fn.applyAsLong(sum, a[i]);
-                    }
-                    else if (h < fnc) {                       // skip rightmost
-                        sum = a[l];
-                        for (int i = l + 1; i < h; ++i)       // sum only
-                            sum = fn.applyAsLong(sum, a[i]);
-                    }
-                    else
-                        sum = t.in;
-                    t.out = sum;
-                    for (LongCumulateTask par;;) {            // propagate
-                        if ((par = (LongCumulateTask)t.getCompleter()) == null) {
-                            if ((state & FINISHED) != 0)      // enable join
-                                t.quietlyComplete();
-                            break outer;
-                        }
-                        int b = par.getPendingCount();
-                        if ((b & state & FINISHED) != 0)
-                            t = par;                          // both done
-                        else if ((b & state & SUMMED) != 0) { // both summed
-                            int nextState; LongCumulateTask lt, rt;
-                            if ((lt = par.left) != null &&
-                                (rt = par.right) != null) {
-                                long lout = lt.out;
-                                par.out = (rt.hi == fnc ? lout :
-                                           fn.applyAsLong(lout, rt.out));
-                            }
-                            int refork = (((b & CUMULATE) == 0 &&
-                                           par.lo == org) ? CUMULATE : 0);
-                            if ((nextState = b|state|refork) == b ||
-                                par.compareAndSetPendingCount(b, nextState)) {
-                                state = SUMMED;               // drop finished
-                                t = par;
-                                if (refork != 0)
-                                    par.fork();
-                            }
-                        }
-                        else if (par.compareAndSetPendingCount(b, b|state))
-                            break outer;                      // sib not ready
-                    }
-                }
-            }
-        }
-        private static final long serialVersionUID = -5074099945909284273L;
-    }
-
-    static final class DoubleCumulateTask extends CountedCompleter<Void> {
-        final double[] array;
-        final DoubleBinaryOperator function;
-        DoubleCumulateTask left, right;
-        double in, out;
-        final int lo, hi, origin, fence, threshold;
-
-        /** Root task constructor */
-        public DoubleCumulateTask(DoubleCumulateTask parent,
-                                  DoubleBinaryOperator function,
-                                  double[] array, int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            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;
-        }
-
-        /** Subtask constructor */
-        DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function,
-                           double[] array, int origin, int fence, int threshold,
-                           int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            this.origin = origin; this.fence = fence;
-            this.threshold = threshold;
-            this.lo = lo; this.hi = hi;
-        }
-
-        public final void compute() {
-            final DoubleBinaryOperator fn;
-            final double[] a;
-            if ((fn = this.function) == null || (a = this.array) == null)
-                throw new NullPointerException();    // hoist checks
-            int th = threshold, org = origin, fnc = fence, l, h;
-            DoubleCumulateTask t = this;
-            outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
-                if (h - l > th) {
-                    DoubleCumulateTask lt = t.left, rt = t.right, f;
-                    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);
-                    }
-                    else {                           // possibly refork
-                        double pin = t.in;
-                        lt.in = pin;
-                        f = t = null;
-                        if (rt != null) {
-                            double lout = lt.out;
-                            rt.in = (l == org ? lout :
-                                     fn.applyAsDouble(pin, lout));
-                            for (int c;;) {
-                                if (((c = rt.getPendingCount()) & CUMULATE) != 0)
-                                    break;
-                                if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
-                                    t = rt;
-                                    break;
-                                }
-                            }
-                        }
-                        for (int c;;) {
-                            if (((c = lt.getPendingCount()) & CUMULATE) != 0)
-                                break;
-                            if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
-                                if (t != null)
-                                    f = t;
-                                t = lt;
-                                break;
-                            }
-                        }
-                        if (t == null)
-                            break;
-                    }
-                    if (f != null)
-                        f.fork();
-                }
-                else {
-                    int state; // Transition to sum, cumulate, or both
-                    for (int b;;) {
-                        if (((b = t.getPendingCount()) & FINISHED) != 0)
-                            break outer;                      // already done
-                        state = ((b & CUMULATE) != 0 ? FINISHED :
-                                 (l > org) ? SUMMED : (SUMMED|FINISHED));
-                        if (t.compareAndSetPendingCount(b, b|state))
-                            break;
-                    }
-
-                    double sum;
-                    if (state != SUMMED) {
-                        int first;
-                        if (l == org) {                       // leftmost; no in
-                            sum = a[org];
-                            first = org + 1;
-                        }
-                        else {
-                            sum = t.in;
-                            first = l;
-                        }
-                        for (int i = first; i < h; ++i)       // cumulate
-                            a[i] = sum = fn.applyAsDouble(sum, a[i]);
-                    }
-                    else if (h < fnc) {                       // skip rightmost
-                        sum = a[l];
-                        for (int i = l + 1; i < h; ++i)       // sum only
-                            sum = fn.applyAsDouble(sum, a[i]);
-                    }
-                    else
-                        sum = t.in;
-                    t.out = sum;
-                    for (DoubleCumulateTask par;;) {            // propagate
-                        if ((par = (DoubleCumulateTask)t.getCompleter()) == null) {
-                            if ((state & FINISHED) != 0)      // enable join
-                                t.quietlyComplete();
-                            break outer;
-                        }
-                        int b = par.getPendingCount();
-                        if ((b & state & FINISHED) != 0)
-                            t = par;                          // both done
-                        else if ((b & state & SUMMED) != 0) { // both summed
-                            int nextState; DoubleCumulateTask lt, rt;
-                            if ((lt = par.left) != null &&
-                                (rt = par.right) != null) {
-                                double lout = lt.out;
-                                par.out = (rt.hi == fnc ? lout :
-                                           fn.applyAsDouble(lout, rt.out));
-                            }
-                            int refork = (((b & CUMULATE) == 0 &&
-                                           par.lo == org) ? CUMULATE : 0);
-                            if ((nextState = b|state|refork) == b ||
-                                par.compareAndSetPendingCount(b, nextState)) {
-                                state = SUMMED;               // drop finished
-                                t = par;
-                                if (refork != 0)
-                                    par.fork();
-                            }
-                        }
-                        else if (par.compareAndSetPendingCount(b, b|state))
-                            break outer;                      // sib not ready
-                    }
-                }
-            }
-        }
-        private static final long serialVersionUID = -586947823794232033L;
-    }
-
-    static final class IntCumulateTask extends CountedCompleter<Void> {
-        final int[] array;
-        final IntBinaryOperator function;
-        IntCumulateTask left, right;
-        int in, out;
-        final int lo, hi, origin, fence, threshold;
-
-        /** Root task constructor */
-        public IntCumulateTask(IntCumulateTask parent,
-                               IntBinaryOperator function,
-                               int[] array, int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            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;
-        }
-
-        /** Subtask constructor */
-        IntCumulateTask(IntCumulateTask parent, IntBinaryOperator function,
-                        int[] array, int origin, int fence, int threshold,
-                        int lo, int hi) {
-            super(parent);
-            this.function = function; this.array = array;
-            this.origin = origin; this.fence = fence;
-            this.threshold = threshold;
-            this.lo = lo; this.hi = hi;
-        }
-
-        public final void compute() {
-            final IntBinaryOperator fn;
-            final int[] a;
-            if ((fn = this.function) == null || (a = this.array) == null)
-                throw new NullPointerException();    // hoist checks
-            int th = threshold, org = origin, fnc = fence, l, h;
-            IntCumulateTask t = this;
-            outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
-                if (h - l > th) {
-                    IntCumulateTask lt = t.left, rt = t.right, f;
-                    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);
-                    }
-                    else {                           // possibly refork
-                        int pin = t.in;
-                        lt.in = pin;
-                        f = t = null;
-                        if (rt != null) {
-                            int lout = lt.out;
-                            rt.in = (l == org ? lout :
-                                     fn.applyAsInt(pin, lout));
-                            for (int c;;) {
-                                if (((c = rt.getPendingCount()) & CUMULATE) != 0)
-                                    break;
-                                if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
-                                    t = rt;
-                                    break;
-                                }
-                            }
-                        }
-                        for (int c;;) {
-                            if (((c = lt.getPendingCount()) & CUMULATE) != 0)
-                                break;
-                            if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
-                                if (t != null)
-                                    f = t;
-                                t = lt;
-                                break;
-                            }
-                        }
-                        if (t == null)
-                            break;
-                    }
-                    if (f != null)
-                        f.fork();
-                }
-                else {
-                    int state; // Transition to sum, cumulate, or both
-                    for (int b;;) {
-                        if (((b = t.getPendingCount()) & FINISHED) != 0)
-                            break outer;                      // already done
-                        state = ((b & CUMULATE) != 0 ? FINISHED :
-                                 (l > org) ? SUMMED : (SUMMED|FINISHED));
-                        if (t.compareAndSetPendingCount(b, b|state))
-                            break;
-                    }
-
-                    int sum;
-                    if (state != SUMMED) {
-                        int first;
-                        if (l == org) {                       // leftmost; no in
-                            sum = a[org];
-                            first = org + 1;
-                        }
-                        else {
-                            sum = t.in;
-                            first = l;
-                        }
-                        for (int i = first; i < h; ++i)       // cumulate
-                            a[i] = sum = fn.applyAsInt(sum, a[i]);
-                    }
-                    else if (h < fnc) {                       // skip rightmost
-                        sum = a[l];
-                        for (int i = l + 1; i < h; ++i)       // sum only
-                            sum = fn.applyAsInt(sum, a[i]);
-                    }
-                    else
-                        sum = t.in;
-                    t.out = sum;
-                    for (IntCumulateTask par;;) {            // propagate
-                        if ((par = (IntCumulateTask)t.getCompleter()) == null) {
-                            if ((state & FINISHED) != 0)      // enable join
-                                t.quietlyComplete();
-                            break outer;
-                        }
-                        int b = par.getPendingCount();
-                        if ((b & state & FINISHED) != 0)
-                            t = par;                          // both done
-                        else if ((b & state & SUMMED) != 0) { // both summed
-                            int nextState; IntCumulateTask lt, rt;
-                            if ((lt = par.left) != null &&
-                                (rt = par.right) != null) {
-                                int lout = lt.out;
-                                par.out = (rt.hi == fnc ? lout :
-                                           fn.applyAsInt(lout, rt.out));
-                            }
-                            int refork = (((b & CUMULATE) == 0 &&
-                                           par.lo == org) ? CUMULATE : 0);
-                            if ((nextState = b|state|refork) == b ||
-                                par.compareAndSetPendingCount(b, nextState)) {
-                                state = SUMMED;               // drop finished
-                                t = par;
-                                if (refork != 0)
-                                    par.fork();
-                            }
-                        }
-                        else if (par.compareAndSetPendingCount(b, b|state))
-                            break outer;                      // sib not ready
-                    }
-                }
-            }
-        }
-        private static final long serialVersionUID = 3731755594596840961L;
-    }
-}
diff --git a/ojluni/src/main/java/java/util/Deque.java b/ojluni/src/main/java/java/util/Deque.java
index 9fec73b..f230677 100644
--- a/ojluni/src/main/java/java/util/Deque.java
+++ b/ojluni/src/main/java/java/util/Deque.java
@@ -59,6 +59,7 @@
  * <p>The twelve methods described above are summarized in the
  * following table:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Summary of Deque methods</caption>
  *  <tr>
@@ -102,6 +103,7 @@
  * inherited from the {@code Queue} interface are precisely equivalent to
  * {@code Deque} methods as indicated in the following table:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Comparison of Queue and Deque methods</caption>
  *  <tr>
@@ -140,6 +142,7 @@
  * beginning of the deque.  Stack methods are precisely equivalent to
  * {@code Deque} methods as indicated in the table below:
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Comparison of Stack and Deque methods</caption>
  *  <tr>
@@ -187,7 +190,7 @@
  * @author Doug Lea
  * @author Josh Bloch
  * @since  1.6
- * @param <E> the type of elements held in this deque
+ * @param <E> the type of elements held in this collection
  */
 public interface Deque<E> extends Queue<E> {
     /**
@@ -343,18 +346,17 @@
      * 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 Objects.equals(o, e)} (if such an element exists).
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+     * (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 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>)
+     *         is incompatible with this deque (optional)
      * @throws NullPointerException if the specified element is null and this
-     *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     *         deque does not permit null elements (optional)
      */
     boolean removeFirstOccurrence(Object o);
 
@@ -362,18 +364,17 @@
      * 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 Objects.equals(o, e)} (if such an element exists).
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+     * (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 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>)
+     *         is incompatible with this deque (optional)
      * @throws NullPointerException if the specified element is null and this
-     *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     *         deque does not permit null elements (optional)
      */
     boolean removeLastOccurrence(Object o);
 
@@ -518,7 +519,8 @@
      * 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 Objects.equals(o, e)} (if such an element exists).
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+     * (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).
      *
@@ -527,27 +529,24 @@
      * @param o element to be removed from this deque, if present
      * @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>)
+     *         is incompatible with this deque (optional)
      * @throws NullPointerException if the specified element is null and this
-     *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     *         deque does not permit null elements (optional)
      */
     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 {@code Objects.equals(o, e)}.
+     * at least one element {@code e} such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @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 class of the specified element
-     *         is incompatible with this deque
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     * @throws ClassCastException if the type of the specified element
+     *         is incompatible with this deque (optional)
      * @throws NullPointerException if the specified element is null and this
-     *         deque does not permit null elements
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
+     *         deque does not permit null elements (optional)
      */
     boolean contains(Object o);
 
@@ -556,7 +555,7 @@
      *
      * @return the number of elements in this deque
      */
-    int size();
+    public int size();
 
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
diff --git a/ojluni/src/main/java/java/util/Map.java b/ojluni/src/main/java/java/util/Map.java
old mode 100644
new mode 100755
index 74ba701..f59b5a9
--- a/ojluni/src/main/java/java/util/Map.java
+++ b/ojluni/src/main/java/java/util/Map.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2006, 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
@@ -25,43 +25,40 @@
 
 package java.util;
 
+
+import java.io.Serializable;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Function;
-import java.io.Serializable;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// removed java 9 methods
-// END android-note
 
 /**
  * An object that maps keys to values.  A map cannot contain duplicate keys;
  * each key can map to at most one value.
  *
- * <p>This interface takes the place of the {@code Dictionary} class, which
+ * <p>This interface takes the place of the <tt>Dictionary</tt> class, which
  * was a totally abstract class rather than an interface.
  *
- * <p>The {@code Map} interface provides three <i>collection views</i>, which
+ * <p>The <tt>Map</tt> interface provides three <i>collection views</i>, which
  * allow a map's contents to be viewed as a set of keys, collection of values,
  * or set of key-value mappings.  The <i>order</i> of a map is defined as
  * the order in which the iterators on the map's collection views return their
- * elements.  Some map implementations, like the {@code TreeMap} class, make
- * specific guarantees as to their order; others, like the {@code HashMap}
+ * elements.  Some map implementations, like the <tt>TreeMap</tt> class, make
+ * specific guarantees as to their order; others, like the <tt>HashMap</tt>
  * class, do not.
  *
  * <p>Note: great care must be exercised if mutable objects are used as map
  * keys.  The behavior of a map is not specified if the value of an object is
- * changed in a manner that affects {@code equals} comparisons while the
+ * changed in a manner that affects <tt>equals</tt> comparisons while the
  * object is a key in the map.  A special case of this prohibition is that it
  * is not permissible for a map to contain itself as a key.  While it is
  * permissible for a map to contain itself as a value, extreme caution is
- * advised: the {@code equals} and {@code hashCode} methods are no longer
+ * advised: the <tt>equals</tt> and <tt>hashCode</tt> methods are no longer
  * well defined on such a map.
  *
  * <p>All general-purpose map implementation classes should provide two
  * "standard" constructors: a void (no arguments) constructor which creates an
- * empty map, and a constructor with a single argument of type {@code Map},
+ * empty map, and a constructor with a single argument of type <tt>Map</tt>,
  * which creates a new map with the same key-value mappings as its argument.
  * In effect, the latter constructor allows the user to copy any map,
  * producing an equivalent map of the desired class.  There is no way to
@@ -70,9 +67,9 @@
  *
  * <p>The "destructive" methods contained in this interface, that is, the
  * methods that modify the map on which they operate, are specified to throw
- * {@code UnsupportedOperationException} if this map does not support the
+ * <tt>UnsupportedOperationException</tt> if this map does not support the
  * operation.  If this is the case, these methods may, but are not required
- * to, throw an {@code UnsupportedOperationException} if the invocation would
+ * to, throw an <tt>UnsupportedOperationException</tt> if the invocation would
  * have no effect on the map.  For example, invoking the {@link #putAll(Map)}
  * method on an unmodifiable map may, but is not required to, throw the
  * exception if the map whose mappings are to be "superimposed" is empty.
@@ -81,7 +78,7 @@
  * may contain.  For example, some implementations prohibit null keys and
  * values, and some have restrictions on the types of their keys.  Attempting
  * to insert an ineligible key or value throws an unchecked exception,
- * typically {@code NullPointerException} or {@code ClassCastException}.
+ * typically <tt>NullPointerException</tt> or <tt>ClassCastException</tt>.
  * Attempting to query the presence of an ineligible key or value may throw an
  * exception, or it may simply return false; some implementations will exhibit
  * the former behavior and some will exhibit the latter.  More generally,
@@ -91,16 +88,20 @@
  * Such exceptions are marked as "optional" in the specification for this
  * interface.
  *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
  * <p>Many methods in Collections Framework interfaces are defined
  * in terms of the {@link Object#equals(Object) equals} method.  For
  * example, the specification for the {@link #containsKey(Object)
- * containsKey(Object key)} method says: "returns {@code true} if and
- * only if this map contains a mapping for a key {@code k} such that
- * {@code (key==null ? k==null : key.equals(k))}." This specification should
- * <i>not</i> be construed to imply that invoking {@code Map.containsKey}
- * with a non-null argument {@code key} will cause {@code key.equals(k)} to
- * be invoked for any key {@code k}.  Implementations are free to
- * implement optimizations whereby the {@code equals} invocation is avoided,
+ * containsKey(Object key)} method says: "returns <tt>true</tt> if and
+ * only if this map contains a mapping for a key <tt>k</tt> such that
+ * <tt>(key==null ? k==null : key.equals(k))</tt>." This specification should
+ * <i>not</i> be construed to imply that invoking <tt>Map.containsKey</tt>
+ * with a non-null argument <tt>key</tt> will cause <tt>key.equals(k)</tt> to
+ * be invoked for any key <tt>k</tt>.  Implementations are free to
+ * implement optimizations whereby the <tt>equals</tt> invocation is avoided,
  * for example, by first comparing the hash codes of the two keys.  (The
  * {@link Object#hashCode()} specification guarantees that two objects with
  * unequal hash codes cannot be equal.)  More generally, implementations of
@@ -108,13 +109,6 @@
  * the specified behavior of underlying {@link Object} methods wherever the
  * implementor deems it appropriate.
  *
- * <p>Some map operations which perform recursive traversal of the map may fail
- * with an exception for self-referential instances where the map directly or
- * indirectly contains itself. This includes the {@code clone()},
- * {@code equals()}, {@code hashCode()} and {@code toString()} methods.
- * Implementations may optionally handle the self-referential scenario, however
- * most current implementations do not do so.
- *
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
  *
@@ -127,34 +121,34 @@
  * @see Set
  * @since 1.2
  */
-public interface Map<K, V> {
+public interface Map<K,V> {
     // Query Operations
 
     /**
      * Returns the number of key-value mappings in this map.  If the
-     * map contains more than {@code Integer.MAX_VALUE} elements, returns
-     * {@code Integer.MAX_VALUE}.
+     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+     * <tt>Integer.MAX_VALUE</tt>.
      *
      * @return the number of key-value mappings in this map
      */
     int size();
 
     /**
-     * Returns {@code true} if this map contains no key-value mappings.
+     * Returns <tt>true</tt> if this map contains no key-value mappings.
      *
-     * @return {@code true} if this map contains no key-value mappings
+     * @return <tt>true</tt> if this map contains no key-value mappings
      */
     boolean isEmpty();
 
     /**
-     * Returns {@code true} if this map contains a mapping for the specified
-     * key.  More formally, returns {@code true} if and only if
-     * this map contains a mapping for a key {@code k} such that
-     * {@code Objects.equals(key, k)}.  (There can be
+     * Returns <tt>true</tt> if this map contains a mapping for the specified
+     * key.  More formally, returns <tt>true</tt> if and only if
+     * this map contains a mapping for a key <tt>k</tt> such that
+     * <tt>(key==null ? k==null : key.equals(k))</tt>.  (There can be
      * at most one such mapping.)
      *
      * @param key key whose presence in this map is to be tested
-     * @return {@code true} if this map contains a mapping for the specified
+     * @return <tt>true</tt> if this map contains a mapping for the specified
      *         key
      * @throws ClassCastException if the key is of an inappropriate type for
      *         this map
@@ -166,15 +160,15 @@
     boolean containsKey(Object key);
 
     /**
-     * Returns {@code true} if this map maps one or more keys to the
-     * specified value.  More formally, returns {@code true} if and only if
-     * this map contains at least one mapping to a value {@code v} such that
-     * {@code Objects.equals(value, v)}.  This operation
+     * Returns <tt>true</tt> if this map maps one or more keys to the
+     * specified value.  More formally, returns <tt>true</tt> if and only if
+     * this map contains at least one mapping to a value <tt>v</tt> such that
+     * <tt>(value==null ? v==null : value.equals(v))</tt>.  This operation
      * will probably require time linear in the map size for most
-     * implementations of the {@code Map} interface.
+     * implementations of the <tt>Map</tt> interface.
      *
      * @param value value whose presence in this map is to be tested
-     * @return {@code true} if this map maps one or more keys to the
+     * @return <tt>true</tt> if this map maps one or more keys to the
      *         specified value
      * @throws ClassCastException if the value is of an inappropriate type for
      *         this map
@@ -190,9 +184,8 @@
      * or {@code null} if this map contains no mapping for the key.
      *
      * <p>More formally, if this map contains a mapping from a key
-     * {@code k} to a value {@code v} such that
-     * {@code Objects.equals(key, k)},
-     * then this method returns {@code v}; otherwise
+     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
+     * key.equals(k))}, then this method returns {@code v}; otherwise
      * it returns {@code null}.  (There can be at most one such mapping.)
      *
      * <p>If this map permits null values, then a return value of
@@ -219,18 +212,18 @@
      * Associates the specified value with the specified key in this map
      * (optional operation).  If the map previously contained a mapping for
      * the key, the old value is replaced by the specified value.  (A map
-     * {@code m} is said to contain a mapping for a key {@code k} if and only
+     * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
      * if {@link #containsKey(Object) m.containsKey(k)} would return
-     * {@code true}.)
+     * <tt>true</tt>.)
      *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
-     * @return the previous value associated with {@code key}, or
-     *         {@code null} if there was no mapping for {@code key}.
-     *         (A {@code null} return can also indicate that the map
-     *         previously associated {@code null} with {@code key},
-     *         if the implementation supports {@code null} values.)
-     * @throws UnsupportedOperationException if the {@code put} operation
+     * @return the previous value associated with <tt>key</tt>, or
+     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
+     *         (A <tt>null</tt> return can also indicate that the map
+     *         previously associated <tt>null</tt> with <tt>key</tt>,
+     *         if the implementation supports <tt>null</tt> values.)
+     * @throws UnsupportedOperationException if the <tt>put</tt> operation
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
@@ -244,25 +237,25 @@
     /**
      * Removes the mapping for a key from this map if it is present
      * (optional operation).   More formally, if this map contains a mapping
-     * from key {@code k} to value {@code v} such that
-     * {@code Objects.equals(key, k)}, that mapping
+     * from key <tt>k</tt> to value <tt>v</tt> such that
+     * <code>(key==null ?  k==null : key.equals(k))</code>, that mapping
      * is removed.  (The map can contain at most one such mapping.)
      *
      * <p>Returns the value to which this map previously associated the key,
-     * or {@code null} if the map contained no mapping for the key.
+     * or <tt>null</tt> if the map contained no mapping for the key.
      *
      * <p>If this map permits null values, then a return value of
-     * {@code null} does not <i>necessarily</i> indicate that the map
+     * <tt>null</tt> does not <i>necessarily</i> indicate that the map
      * contained no mapping for the key; it's also possible that the map
-     * explicitly mapped the key to {@code null}.
+     * explicitly mapped the key to <tt>null</tt>.
      *
      * <p>The map will not contain a mapping for the specified key once the
      * call returns.
      *
      * @param key key whose mapping is to be removed from the map
-     * @return the previous value associated with {@code key}, or
-     *         {@code null} if there was no mapping for {@code key}.
-     * @throws UnsupportedOperationException if the {@code remove} operation
+     * @return the previous value associated with <tt>key</tt>, or
+     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
+     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
      *         is not supported by this map
      * @throws ClassCastException if the key is of an inappropriate type for
      *         this map
@@ -280,12 +273,12 @@
      * Copies all of the mappings from the specified map to this map
      * (optional operation).  The effect of this call is equivalent to that
      * of calling {@link #put(Object,Object) put(k, v)} on this map once
-     * for each mapping from key {@code k} to value {@code v} in the
+     * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
      * specified map.  The behavior of this operation is undefined if the
      * specified map is modified while the operation is in progress.
      *
      * @param m mappings to be stored in this map
-     * @throws UnsupportedOperationException if the {@code putAll} operation
+     * @throws UnsupportedOperationException if the <tt>putAll</tt> operation
      *         is not supported by this map
      * @throws ClassCastException if the class of a key or value in the
      *         specified map prevents it from being stored in this map
@@ -301,7 +294,7 @@
      * Removes all of the mappings from this map (optional operation).
      * The map will be empty after this call returns.
      *
-     * @throws UnsupportedOperationException if the {@code clear} operation
+     * @throws UnsupportedOperationException if the <tt>clear</tt> operation
      *         is not supported by this map
      */
     void clear();
@@ -314,12 +307,12 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own {@code remove} operation), the results of
+     * the iterator's own <tt>remove</tt> operation), the results of
      * the iteration are undefined.  The set supports element removal,
      * which removes the corresponding mapping from the map, via the
-     * {@code Iterator.remove}, {@code Set.remove},
-     * {@code removeAll}, {@code retainAll}, and {@code clear}
-     * operations.  It does not support the {@code add} or {@code addAll}
+     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
      * operations.
      *
      * @return a set view of the keys contained in this map
@@ -331,13 +324,13 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  If the map is
      * modified while an iteration over the collection is in progress
-     * (except through the iterator's own {@code remove} operation),
+     * (except through the iterator's own <tt>remove</tt> operation),
      * the results of the iteration are undefined.  The collection
      * supports element removal, which removes the corresponding
-     * mapping from the map, via the {@code Iterator.remove},
-     * {@code Collection.remove}, {@code removeAll},
-     * {@code retainAll} and {@code clear} operations.  It does not
-     * support the {@code add} or {@code addAll} operations.
+     * mapping from the map, via the <tt>Iterator.remove</tt>,
+     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
+     * support the <tt>add</tt> or <tt>addAll</tt> operations.
      *
      * @return a collection view of the values contained in this map
      */
@@ -348,33 +341,33 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own {@code remove} operation, or through the
-     * {@code setValue} operation on a map entry returned by the
+     * the iterator's own <tt>remove</tt> operation, or through the
+     * <tt>setValue</tt> operation on a map entry returned by the
      * iterator) the results of the iteration are undefined.  The set
      * supports element removal, which removes the corresponding
-     * mapping from the map, via the {@code Iterator.remove},
-     * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
-     * {@code clear} operations.  It does not support the
-     * {@code add} or {@code addAll} operations.
+     * mapping from the map, via the <tt>Iterator.remove</tt>,
+     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
+     * <tt>clear</tt> operations.  It does not support the
+     * <tt>add</tt> or <tt>addAll</tt> operations.
      *
      * @return a set view of the mappings contained in this map
      */
     Set<Map.Entry<K, V>> entrySet();
 
     /**
-     * A map entry (key-value pair).  The {@code Map.entrySet} method returns
+     * A map entry (key-value pair).  The <tt>Map.entrySet</tt> method returns
      * a collection-view of the map, whose elements are of this class.  The
      * <i>only</i> way to obtain a reference to a map entry is from the
-     * iterator of this collection-view.  These {@code Map.Entry} objects are
+     * iterator of this collection-view.  These <tt>Map.Entry</tt> objects are
      * valid <i>only</i> for the duration of the iteration; more formally,
      * the behavior of a map entry is undefined if the backing map has been
      * modified after the entry was returned by the iterator, except through
-     * the {@code setValue} operation on the map entry.
+     * the <tt>setValue</tt> operation on the map entry.
      *
      * @see Map#entrySet()
      * @since 1.2
      */
-    interface Entry<K, V> {
+    interface Entry<K,V> {
         /**
          * Returns the key corresponding to this entry.
          *
@@ -388,7 +381,7 @@
         /**
          * Returns the value corresponding to this entry.  If the mapping
          * has been removed from the backing map (by the iterator's
-         * {@code remove} operation), the results of this call are undefined.
+         * <tt>remove</tt> operation), the results of this call are undefined.
          *
          * @return the value corresponding to this entry
          * @throws IllegalStateException implementations may, but are not
@@ -401,11 +394,11 @@
          * Replaces the value corresponding to this entry with the specified
          * value (optional operation).  (Writes through to the map.)  The
          * behavior of this call is undefined if the mapping has already been
-         * removed from the map (by the iterator's {@code remove} operation).
+         * removed from the map (by the iterator's <tt>remove</tt> operation).
          *
          * @param value new value to be stored in this entry
          * @return old value corresponding to the entry
-         * @throws UnsupportedOperationException if the {@code put} operation
+         * @throws UnsupportedOperationException if the <tt>put</tt> operation
          *         is not supported by the backing map
          * @throws ClassCastException if the class of the specified value
          *         prevents it from being stored in the backing map
@@ -421,34 +414,34 @@
 
         /**
          * Compares the specified object with this entry for equality.
-         * Returns {@code true} if the given object is also a map entry and
+         * Returns <tt>true</tt> if the given object is also a map entry and
          * the two entries represent the same mapping.  More formally, two
-         * entries {@code e1} and {@code e2} represent the same mapping
+         * entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
          * if<pre>
          *     (e1.getKey()==null ?
          *      e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &amp;&amp;
          *     (e1.getValue()==null ?
          *      e2.getValue()==null : e1.getValue().equals(e2.getValue()))
          * </pre>
-         * This ensures that the {@code equals} method works properly across
-         * different implementations of the {@code Map.Entry} interface.
+         * This ensures that the <tt>equals</tt> method works properly across
+         * different implementations of the <tt>Map.Entry</tt> interface.
          *
          * @param o object to be compared for equality with this map entry
-         * @return {@code true} if the specified object is equal to this map
+         * @return <tt>true</tt> if the specified object is equal to this map
          *         entry
          */
         boolean equals(Object o);
 
         /**
          * Returns the hash code value for this map entry.  The hash code
-         * of a map entry {@code e} is defined to be: <pre>
+         * of a map entry <tt>e</tt> is defined to be: <pre>
          *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
          *     (e.getValue()==null ? 0 : e.getValue().hashCode())
          * </pre>
-         * This ensures that {@code e1.equals(e2)} implies that
-         * {@code e1.hashCode()==e2.hashCode()} for any two Entries
-         * {@code e1} and {@code e2}, as required by the general
-         * contract of {@code Object.hashCode}.
+         * This ensures that <tt>e1.equals(e2)</tt> implies that
+         * <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
+         * <tt>e1</tt> and <tt>e2</tt>, as required by the general
+         * contract of <tt>Object.hashCode</tt>.
          *
          * @return the hash code value for this map entry
          * @see Object#hashCode()
@@ -469,29 +462,12 @@
          * @see Comparable
          * @since 1.8
          */
-        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
+        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
             return (Comparator<Map.Entry<K, V>> & Serializable)
                 (c1, c2) -> c1.getKey().compareTo(c2.getKey());
         }
 
         /**
-         * Returns a comparator that compares {@link Map.Entry} in natural order on value.
-         *
-         * <p>The returned comparator is serializable and throws {@link
-         * NullPointerException} when comparing an entry with null values.
-         *
-         * @param <K> the type of the map keys
-         * @param <V> the {@link Comparable} type of the map values
-         * @return a comparator that compares {@link Map.Entry} in natural order on value.
-         * @see Comparable
-         * @since 1.8
-         */
-        public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
-            return (Comparator<Map.Entry<K, V>> & Serializable)
-                (c1, c2) -> c1.getValue().compareTo(c2.getValue());
-        }
-
-        /**
          * Returns a comparator that compares {@link Map.Entry} by key using the given
          * {@link Comparator}.
          *
@@ -509,49 +485,30 @@
             return (Comparator<Map.Entry<K, V>> & Serializable)
                 (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
         }
-
-        /**
-         * Returns a comparator that compares {@link Map.Entry} by value using the given
-         * {@link Comparator}.
-         *
-         * <p>The returned comparator is serializable if the specified comparator
-         * is also serializable.
-         *
-         * @param  <K> the type of the map keys
-         * @param  <V> the type of the map values
-         * @param  cmp the value {@link Comparator}
-         * @return a comparator that compares {@link Map.Entry} by the value.
-         * @since 1.8
-         */
-        public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
-            Objects.requireNonNull(cmp);
-            return (Comparator<Map.Entry<K, V>> & Serializable)
-                (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
-        }
     }
 
     // Comparison and hashing
 
     /**
      * Compares the specified object with this map for equality.  Returns
-     * {@code true} if the given object is also a map and the two maps
-     * represent the same mappings.  More formally, two maps {@code m1} and
-     * {@code m2} represent the same mappings if
-     * {@code m1.entrySet().equals(m2.entrySet())}.  This ensures that the
-     * {@code equals} method works properly across different implementations
-     * of the {@code Map} interface.
+     * <tt>true</tt> if the given object is also a map and the two maps
+     * represent the same mappings.  More formally, two maps <tt>m1</tt> and
+     * <tt>m2</tt> represent the same mappings if
+     * <tt>m1.entrySet().equals(m2.entrySet())</tt>.  This ensures that the
+     * <tt>equals</tt> method works properly across different implementations
+     * of the <tt>Map</tt> interface.
      *
      * @param o object to be compared for equality with this map
-     * @return {@code true} if the specified object is equal to this map
+     * @return <tt>true</tt> if the specified object is equal to this map
      */
     boolean equals(Object o);
 
     /**
      * Returns the hash code value for this map.  The hash code of a map is
      * defined to be the sum of the hash codes of each entry in the map's
-     * {@code entrySet()} view.  This ensures that {@code m1.equals(m2)}
-     * implies that {@code m1.hashCode()==m2.hashCode()} for any two maps
-     * {@code m1} and {@code m2}, as required by the general contract of
+     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
+     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
+     * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
      * {@link Object#hashCode}.
      *
      * @return the hash code value for this map
@@ -561,37 +518,6 @@
      */
     int hashCode();
 
-    // Defaultable methods
-
-    /**
-     * Returns the value to which the specified key is mapped, or
-     * {@code defaultValue} if this map contains no mapping for the key.
-     *
-     * @implSpec
-     * The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param key the key whose associated value is to be returned
-     * @param defaultValue the default mapping of the key
-     * @return the value to which the specified key is mapped, or
-     * {@code defaultValue} if this map contains no mapping for the key
-     * @throws ClassCastException if the key is of an inappropriate type for
-     * this map
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws NullPointerException if the specified key is null and this map
-     * does not permit null keys
-     * (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @since 1.8
-     */
-    default V getOrDefault(Object key, V defaultValue) {
-        V v;
-        return (((v = get(key)) != null) || containsKey(key))
-            ? v
-            : defaultValue;
-    }
-
     /**
      * Performs the given action for each entry in this map until all entries
      * have been processed or the action throws an exception.   Unless
@@ -625,625 +551,11 @@
             try {
                 k = entry.getKey();
                 v = entry.getValue();
-            } catch (IllegalStateException ise) {
+            } catch(IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
             action.accept(k, v);
         }
     }
-
-    /**
-     * Replaces each entry's value with the result of invoking the given
-     * function on that entry until all entries have been processed or the
-     * function throws an exception.  Exceptions thrown by the function are
-     * relayed to the caller.
-     *
-     * @implSpec
-     * <p>The default implementation is equivalent to, for this {@code map}:
-     * <pre> {@code
-     * for (Map.Entry<K, V> entry : map.entrySet())
-     *     entry.setValue(function.apply(entry.getKey(), entry.getValue()));
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param function the function to apply to each entry
-     * @throws UnsupportedOperationException if the {@code set} operation
-     * is not supported by this map's entry set iterator.
-     * @throws ClassCastException if the class of a replacement value
-     * prevents it from being stored in this map
-     * @throws NullPointerException if the specified function is null, or the
-     * specified replacement value is null, and this map does not permit null
-     * values
-     * @throws ClassCastException if a replacement value is of an inappropriate
-     *         type for this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws NullPointerException if function or a replacement value is null,
-     *         and this map does not permit null keys or values
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of a replacement value
-     *         prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ConcurrentModificationException if an entry is found to be
-     * removed during iteration
-     * @since 1.8
-     */
-    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-        Objects.requireNonNull(function);
-        for (Map.Entry<K, V> entry : entrySet()) {
-            K k;
-            V v;
-            try {
-                k = entry.getKey();
-                v = entry.getValue();
-            } catch (IllegalStateException ise) {
-                // this usually means the entry is no longer in the map.
-                throw new ConcurrentModificationException(ise);
-            }
-
-            // ise thrown from function is not a cme.
-            v = function.apply(k, v);
-
-            try {
-                entry.setValue(v);
-            } catch (IllegalStateException ise) {
-                // this usually means the entry is no longer in the map.
-                throw new ConcurrentModificationException(ise);
-            }
-        }
-    }
-
-    /**
-     * If the specified key is not already associated with a value (or is mapped
-     * to {@code null}) associates it with the given value and returns
-     * {@code null}, else returns the current value.
-     *
-     * @implSpec
-     * The default implementation is equivalent to, for this {@code
-     * map}:
-     *
-     * <pre> {@code
-     * V v = map.get(key);
-     * if (v == null)
-     *     v = map.put(key, value);
-     *
-     * return v;
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param value value to be associated with the specified key
-     * @return the previous value associated with the specified key, or
-     *         {@code null} if there was no mapping for the key.
-     *         (A {@code null} return can also indicate that the map
-     *         previously associated {@code null} with the key,
-     *         if the implementation supports null values.)
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the key or value is of an inappropriate
-     *         type for this map
-     *         (<a href="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>)
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @since 1.8
-     */
-    default V putIfAbsent(K key, V value) {
-        V v = get(key);
-        if (v == null) {
-            v = put(key, value);
-        }
-
-        return v;
-    }
-
-    /**
-     * Removes the entry for the specified key only if it is currently
-     * mapped to the specified value.
-     *
-     * @implSpec
-     * The default implementation is equivalent to, for this {@code map}:
-     *
-     * <pre> {@code
-     * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
-     *     map.remove(key);
-     *     return true;
-     * } else
-     *     return false;
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param key key with which the specified value is associated
-     * @param value value expected to be associated with the specified key
-     * @return {@code true} if the value was removed
-     * @throws UnsupportedOperationException if the {@code remove} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the key or value is of an inappropriate
-     *         type for this map
-     *         (<a href="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>)
-     * @since 1.8
-     */
-    default boolean remove(Object key, Object value) {
-        Object curValue = get(key);
-        if (!Objects.equals(curValue, value) ||
-            (curValue == null && !containsKey(key))) {
-            return false;
-        }
-        remove(key);
-        return true;
-    }
-
-    /**
-     * Replaces the entry for the specified key only if currently
-     * mapped to the specified value.
-     *
-     * @implSpec
-     * The default implementation is equivalent to, for this {@code map}:
-     *
-     * <pre> {@code
-     * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
-     *     map.put(key, newValue);
-     *     return true;
-     * } else
-     *     return false;
-     * }</pre>
-     *
-     * The default implementation does not throw NullPointerException
-     * for maps that do not support null values if oldValue is null unless
-     * newValue is also null.
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param key key with which the specified value is associated
-     * @param oldValue value expected to be associated with the specified key
-     * @param newValue value to be associated with the specified key
-     * @return {@code true} if the value was replaced
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of a specified key or value
-     *         prevents it from being stored in this map
-     * @throws NullPointerException if a specified key or newValue is null,
-     *         and this map does not permit null keys or values
-     * @throws NullPointerException if oldValue is null and this map does not
-     *         permit null values
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of a specified key
-     *         or value prevents it from being stored in this map
-     * @since 1.8
-     */
-    default boolean replace(K key, V oldValue, V newValue) {
-        Object curValue = get(key);
-        if (!Objects.equals(curValue, oldValue) ||
-            (curValue == null && !containsKey(key))) {
-            return false;
-        }
-        put(key, newValue);
-        return true;
-    }
-
-    /**
-     * Replaces the entry for the specified key only if it is
-     * currently mapped to some value.
-     *
-     * @implSpec
-     * The default implementation is equivalent to, for this {@code map}:
-     *
-     * <pre> {@code
-     * if (map.containsKey(key)) {
-     *     return map.put(key, value);
-     * } else
-     *     return null;
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties.
-     *
-     * @param key key with which the specified value is associated
-     * @param value value to be associated with the specified key
-     * @return the previous value associated with the specified key, or
-     *         {@code null} if there was no mapping for the key.
-     *         (A {@code null} return can also indicate that the map
-     *         previously associated {@code null} with the key,
-     *         if the implementation supports null values.)
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of the specified key or value
-     *         prevents it from being stored in this map
-     *         (<a href="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
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     * @since 1.8
-     */
-    default V replace(K key, V value) {
-        V curValue;
-        if (((curValue = get(key)) != null) || containsKey(key)) {
-            curValue = put(key, value);
-        }
-        return curValue;
-    }
-
-    /**
-     * If the specified key is not already associated with a value (or is mapped
-     * to {@code null}), attempts to compute its value using the given mapping
-     * function and enters it into this map unless {@code null}.
-     *
-     * <p>If the mapping function returns {@code null}, no mapping is recorded.
-     * If the mapping function itself throws an (unchecked) exception, the
-     * exception is rethrown, and no mapping is recorded.  The most
-     * common usage is to construct a new object serving as an initial
-     * mapped value or memoized result, as in:
-     *
-     * <pre> {@code
-     * map.computeIfAbsent(key, k -> new Value(f(k)));
-     * }</pre>
-     *
-     * <p>Or to implement a multi-value map, {@code Map<K,Collection<V>>},
-     * supporting multiple values per key:
-     *
-     * <pre> {@code
-     * map.computeIfAbsent(key, k -> new HashSet<V>()).add(v);
-     * }</pre>
-     *
-     * <p>The mapping function should not modify this map during computation.
-     *
-     * @implSpec
-     * The default implementation is equivalent to the following steps for this
-     * {@code map}, then returning the current value or {@code null} if now
-     * absent:
-     *
-     * <pre> {@code
-     * if (map.get(key) == null) {
-     *     V newValue = mappingFunction.apply(key);
-     *     if (newValue != null)
-     *         map.put(key, newValue);
-     * }
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about detecting if the
-     * mapping function modifies this map during computation and, if
-     * appropriate, reporting an error. Non-concurrent implementations should
-     * override this method and, on a best-effort basis, throw a
-     * {@code ConcurrentModificationException} if it is detected that the
-     * mapping function modifies this map during computation. Concurrent
-     * implementations should override this method and, on a best-effort basis,
-     * throw an {@code IllegalStateException} if it is detected that the
-     * mapping function modifies this map during computation and as a result
-     * computation would never complete.
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties. In particular, all implementations of
-     * subinterface {@link java.util.concurrent.ConcurrentMap} must document
-     * whether the mapping function is applied once atomically only if the value
-     * is not present.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param mappingFunction the mapping function to compute a value
-     * @return the current (existing or computed) value associated with
-     *         the specified key, or null if the computed value is null
-     * @throws NullPointerException if the specified key is null and
-     *         this map does not support null keys, or the mappingFunction
-     *         is null
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of the specified key or value
-     *         prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @since 1.8
-     */
-    default V computeIfAbsent(K key,
-            Function<? super K, ? extends V> mappingFunction) {
-        Objects.requireNonNull(mappingFunction);
-        V v;
-        if ((v = get(key)) == null) {
-            V newValue;
-            if ((newValue = mappingFunction.apply(key)) != null) {
-                put(key, newValue);
-                return newValue;
-            }
-        }
-
-        return v;
-    }
-
-    /**
-     * If the value for the specified key is present and non-null, attempts to
-     * compute a new mapping given the key and its current mapped value.
-     *
-     * <p>If the remapping function returns {@code null}, the mapping is removed.
-     * If the remapping function itself throws an (unchecked) exception, the
-     * exception is rethrown, and the current mapping is left unchanged.
-     *
-     * <p>The remapping function should not modify this map during computation.
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if now absent:
-     *
-     * <pre> {@code
-     * if (map.get(key) != null) {
-     *     V oldValue = map.get(key);
-     *     V newValue = remappingFunction.apply(key, oldValue);
-     *     if (newValue != null)
-     *         map.put(key, newValue);
-     *     else
-     *         map.remove(key);
-     * }
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about detecting if the
-     * remapping function modifies this map during computation and, if
-     * appropriate, reporting an error. Non-concurrent implementations should
-     * override this method and, on a best-effort basis, throw a
-     * {@code ConcurrentModificationException} if it is detected that the
-     * remapping function modifies this map during computation. Concurrent
-     * implementations should override this method and, on a best-effort basis,
-     * throw an {@code IllegalStateException} if it is detected that the
-     * remapping function modifies this map during computation and as a result
-     * computation would never complete.
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties. In particular, all implementations of
-     * subinterface {@link java.util.concurrent.ConcurrentMap} must document
-     * whether the remapping function is applied once atomically only if the
-     * value is not present.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param remappingFunction the remapping function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key is null and
-     *         this map does not support null keys, or the
-     *         remappingFunction is null
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of the specified key or value
-     *         prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @since 1.8
-     */
-    default V computeIfPresent(K key,
-            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        V oldValue;
-        if ((oldValue = get(key)) != null) {
-            V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue != null) {
-                put(key, newValue);
-                return newValue;
-            } else {
-                remove(key);
-                return null;
-            }
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Attempts to compute a mapping for the specified key and its current
-     * mapped value (or {@code null} if there is no current mapping). For
-     * example, to either create or append a {@code String} msg to a value
-     * mapping:
-     *
-     * <pre> {@code
-     * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
-     * (Method {@link #merge merge()} is often simpler to use for such purposes.)
-     *
-     * <p>If the remapping function returns {@code null}, the mapping is removed
-     * (or remains absent if initially absent).  If the remapping function
-     * itself throws an (unchecked) exception, the exception is rethrown, and
-     * the current mapping is left unchanged.
-     *
-     * <p>The remapping function should not modify this map during computation.
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
-     *
-     * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null) {
-     *    if (newValue != null)
-     *       map.put(key, newValue);
-     *    else
-     *       map.remove(key);
-     * } else {
-     *    if (newValue != null)
-     *       map.put(key, newValue);
-     *    else
-     *       return null;
-     * }
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about detecting if the
-     * remapping function modifies this map during computation and, if
-     * appropriate, reporting an error. Non-concurrent implementations should
-     * override this method and, on a best-effort basis, throw a
-     * {@code ConcurrentModificationException} if it is detected that the
-     * remapping function modifies this map during computation. Concurrent
-     * implementations should override this method and, on a best-effort basis,
-     * throw an {@code IllegalStateException} if it is detected that the
-     * remapping function modifies this map during computation and as a result
-     * computation would never complete.
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties. In particular, all implementations of
-     * subinterface {@link java.util.concurrent.ConcurrentMap} must document
-     * whether the remapping function is applied once atomically only if the
-     * value is not present.
-     *
-     * @param key key with which the specified value is to be associated
-     * @param remappingFunction the remapping function to compute a value
-     * @return the new value associated with the specified key, or null if none
-     * @throws NullPointerException if the specified key is null and
-     *         this map does not support null keys, or the
-     *         remappingFunction is null
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of the specified key or value
-     *         prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @since 1.8
-     */
-    default V compute(K key,
-            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        V oldValue = get(key);
-
-        V newValue = remappingFunction.apply(key, oldValue);
-        if (newValue == null) {
-            // delete mapping
-            if (oldValue != null || containsKey(key)) {
-                // something to remove
-                remove(key);
-                return null;
-            } else {
-                // nothing to do. Leave things as they were.
-                return null;
-            }
-        } else {
-            // add or replace old mapping
-            put(key, newValue);
-            return newValue;
-        }
-    }
-
-    /**
-     * If the specified key is not already associated with a value or is
-     * associated with null, associates it with the given non-null value.
-     * Otherwise, replaces the associated value with the results of the given
-     * remapping function, or removes if the result is {@code null}. This
-     * method may be of use when combining multiple mapped values for a key.
-     * For example, to either create or append a {@code String msg} to a
-     * value mapping:
-     *
-     * <pre> {@code
-     * map.merge(key, msg, String::concat)
-     * }</pre>
-     *
-     * <p>If the remapping function returns {@code null}, the mapping is removed.
-     * If the remapping function itself throws an (unchecked) exception, the
-     * exception is rethrown, and the current mapping is left unchanged.
-     *
-     * <p>The remapping function should not modify this map during computation.
-     *
-     * @implSpec
-     * The default implementation is equivalent to performing the following
-     * steps for this {@code map}, then returning the current value or
-     * {@code null} if absent:
-     *
-     * <pre> {@code
-     * V oldValue = map.get(key);
-     * V newValue = (oldValue == null) ? value :
-     *              remappingFunction.apply(oldValue, value);
-     * if (newValue == null)
-     *     map.remove(key);
-     * else
-     *     map.put(key, newValue);
-     * }</pre>
-     *
-     * <p>The default implementation makes no guarantees about detecting if the
-     * remapping function modifies this map during computation and, if
-     * appropriate, reporting an error. Non-concurrent implementations should
-     * override this method and, on a best-effort basis, throw a
-     * {@code ConcurrentModificationException} if it is detected that the
-     * remapping function modifies this map during computation. Concurrent
-     * implementations should override this method and, on a best-effort basis,
-     * throw an {@code IllegalStateException} if it is detected that the
-     * remapping function modifies this map during computation and as a result
-     * computation would never complete.
-     *
-     * <p>The default implementation makes no guarantees about synchronization
-     * or atomicity properties of this method. Any implementation providing
-     * atomicity guarantees must override this method and document its
-     * concurrency properties. In particular, all implementations of
-     * subinterface {@link java.util.concurrent.ConcurrentMap} must document
-     * whether the remapping function is applied once atomically only if the
-     * value is not present.
-     *
-     * @param key key with which the resulting value is to be associated
-     * @param value the non-null value to be merged with the existing value
-     *        associated with the key or, if no existing value or a null value
-     *        is associated with the key, to be associated with the key
-     * @param remappingFunction the remapping function to recompute a value if
-     *        present
-     * @return the new value associated with the specified key, or null if no
-     *         value is associated with the key
-     * @throws UnsupportedOperationException if the {@code put} operation
-     *         is not supported by this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws ClassCastException if the class of the specified key or value
-     *         prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws IllegalArgumentException if some property of the specified key
-     *         or value prevents it from being stored in this map
-     *         (<a href="Collection.html#optional-restrictions">optional</a>)
-     * @throws NullPointerException if the specified key is null and this map
-     *         does not support null keys or the value or remappingFunction is
-     *         null
-     * @since 1.8
-     */
-    default V merge(K key, V value,
-            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
-        Objects.requireNonNull(remappingFunction);
-        Objects.requireNonNull(value);
-        V oldValue = get(key);
-        V newValue = (oldValue == null) ? value :
-                   remappingFunction.apply(oldValue, value);
-        if (newValue == null) {
-            remove(key);
-        } else {
-            put(key, newValue);
-        }
-        return newValue;
-    }
 }
diff --git a/ojluni/src/main/java/java/util/NavigableMap.java b/ojluni/src/main/java/java/util/NavigableMap.java
index fdbc0b5..b0d9453 100644
--- a/ojluni/src/main/java/java/util/NavigableMap.java
+++ b/ojluni/src/main/java/java/util/NavigableMap.java
@@ -41,32 +41,30 @@
 /**
  * A {@link SortedMap} extended with navigation methods returning the
  * closest matches for given search targets. Methods
- * {@link #lowerEntry}, {@link #floorEntry}, {@link #ceilingEntry},
- * and {@link #higherEntry} return {@code Map.Entry} objects
+ * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
+ * and {@code 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
- * {@link #lowerKey}, {@link #floorKey}, {@link #ceilingKey}, and
- * {@link #higherKey} return only the associated keys. All of these
+ * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
+ * {@code 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 {@link #descendingMap}
+ * ascending or descending key order.  The {@code 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
- * {@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.
+ * 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.
  *
- * <p>This interface additionally defines methods {@link #firstEntry},
- * {@link #pollFirstEntry}, {@link #lastEntry}, and
- * {@link #pollLastEntry} that return and/or remove the least and
+ * <p>This interface additionally defines methods {@code firstEntry},
+ * {@code pollFirstEntry}, {@code lastEntry}, and
+ * {@code 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
@@ -85,7 +83,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 overridden to return {@link NavigableSet}.
+ * {@link #keySet()} can be overridden to return {@code NavigableSet}.
  *
  * @author Doug Lea
  * @author Josh Bloch
@@ -299,7 +297,7 @@
      * Returns a view of the portion of this map whose keys range from
      * {@code fromKey} to {@code toKey}.  If {@code fromKey} and
      * {@code toKey} are equal, the returned map is empty unless
-     * {@code fromInclusive} and {@code toInclusive} are both true.  The
+     * {@code fromExclusive} and {@code toExclusive} are both true.  The
      * returned map is backed by this map, so changes in the returned map are
      * reflected in this map, and vice-versa.  The returned map supports all
      * optional map operations that this map supports.
diff --git a/ojluni/src/main/java/java/util/NavigableSet.java b/ojluni/src/main/java/java/util/NavigableSet.java
index 412a07d..11a9bdb 100644
--- a/ojluni/src/main/java/java/util/NavigableSet.java
+++ b/ojluni/src/main/java/java/util/NavigableSet.java
@@ -32,36 +32,32 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+package java.util;
+
 // BEGIN android-note
 // removed link to collections framework docs
 // END android-note
 
-package java.util;
-
 /**
  * A {@link SortedSet} extended with navigation methods reporting
- * closest matches for given search targets. Methods {@link #lower},
- * {@link #floor}, {@link #ceiling}, and {@link #higher} return elements
+ * closest matches for given search targets. Methods {@code lower},
+ * {@code floor}, {@code ceiling}, and {@code 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.
- *
- * <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.
+ * 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.
  *
  * <p>The return values of navigation methods may be ambiguous in
  * implementations that permit {@code null} elements. However, even
@@ -195,7 +191,7 @@
      * Returns a view of the portion of this set whose elements range from
      * {@code fromElement} to {@code toElement}.  If {@code fromElement} and
      * {@code toElement} are equal, the returned set is empty unless {@code
-     * fromInclusive} and {@code toInclusive} are both true.  The returned set
+     * fromExclusive} and {@code toExclusive} are both true.  The returned set
      * is backed by this set, so changes in the returned set are reflected in
      * this set, and vice-versa.  The returned set supports all optional set
      * operations that this set supports.
diff --git a/ojluni/src/main/java/java/util/PriorityQueue.java b/ojluni/src/main/java/java/util/PriorityQueue.java
old mode 100644
new mode 100755
index 7c929bd..b42647e
--- a/ojluni/src/main/java/java/util/PriorityQueue.java
+++ b/ojluni/src/main/java/java/util/PriorityQueue.java
@@ -77,7 +77,7 @@
  *
  * @since 1.5
  * @author Josh Bloch, Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public class PriorityQueue<E> extends AbstractQueue<E>
     implements java.io.Serializable {
@@ -99,7 +99,7 @@
     /**
      * The number of elements in the priority queue.
      */
-    int size;
+    private int size = 0;
 
     /**
      * 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;     // non-private to simplify nested class access
+    transient int modCount = 0; // non-private to simplify nested class access
 
     /**
      * Creates a {@code PriorityQueue} with the default initial
@@ -258,8 +258,8 @@
             a = Arrays.copyOf(a, a.length, Object[].class);
         int len = a.length;
         if (len == 1 || this.comparator != null)
-            for (Object e : a)
-                if (e == null)
+            for (int i = 0; i < len; i++)
+                if (a[i] == null)
                     throw new NullPointerException();
         this.queue = a;
         this.size = a.length;
@@ -406,7 +406,7 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        return indexOf(o) >= 0;
+        return indexOf(o) != -1;
     }
 
     /**
@@ -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;
+        private int cursor = 0;
 
         /**
          * 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;
+        private ArrayDeque<E> forgetMeNot = null;
 
         /**
          * Element returned by the most recent call to next iff that
          * element was drawn from the forgetMeNot list.
          */
-        private E lastRetElt;
+        private E lastRetElt = null;
 
         /**
          * The modCount value that the iterator believes that the backing
@@ -609,8 +609,8 @@
      * avoid missing traversing elements.
      */
     @SuppressWarnings("unchecked")
-    E removeAt(int i) {
-        // assert i >= 0 && i < size;
+    private E removeAt(int i) {
+        assert i >= 0 && i < size;
         modCount++;
         int s = --size;
         if (s == i) // removed last element
@@ -756,7 +756,6 @@
      *             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 {
@@ -776,9 +775,6 @@
      * (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 {
@@ -813,7 +809,7 @@
      * @since 1.8
      */
     public final Spliterator<E> spliterator() {
-        return new PriorityQueueSpliterator<>(this, 0, -1, 0);
+        return new PriorityQueueSpliterator<E>(this, 0, -1, 0);
     }
 
     static final class PriorityQueueSpliterator<E> implements Spliterator<E> {
@@ -826,9 +822,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;
@@ -847,8 +843,8 @@
         public PriorityQueueSpliterator<E> trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
-                new PriorityQueueSpliterator<>(pq, lo, index = mid,
-                                               expectedModCount);
+                new PriorityQueueSpliterator<E>(pq, lo, index = mid,
+                                                expectedModCount);
         }
 
         @SuppressWarnings("unchecked")
diff --git a/ojluni/src/main/java/java/util/Queue.java b/ojluni/src/main/java/java/util/Queue.java
index 6520337..b43c6c1 100644
--- a/ojluni/src/main/java/java/util/Queue.java
+++ b/ojluni/src/main/java/java/util/Queue.java
@@ -50,6 +50,7 @@
  * implementations; in most implementations, insert operations cannot
  * fail.
  *
+ * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  * <caption>Summary of Queue methods</caption>
  *  <tr>
@@ -127,9 +128,17 @@
  * always well-defined for queues with the same elements but different
  * ordering properties.
  *
+ * @see java.util.Collection
+ * @see LinkedList
+ * @see PriorityQueue
+ * @see java.util.concurrent.LinkedBlockingQueue
+ * @see java.util.concurrent.BlockingQueue
+ * @see java.util.concurrent.ArrayBlockingQueue
+ * @see java.util.concurrent.LinkedBlockingQueue
+ * @see java.util.concurrent.PriorityBlockingQueue
  * @since 1.5
  * @author Doug Lea
- * @param <E> the type of elements held in this queue
+ * @param <E> the type of elements held in this collection
  */
 public interface Queue<E> extends Collection<E> {
     /**
diff --git a/ojluni/src/main/java/java/util/SplittableRandom.java b/ojluni/src/main/java/java/util/SplittableRandom.java
deleted file mode 100644
index b2a07ec..0000000
--- a/ojluni/src/main/java/java/util/SplittableRandom.java
+++ /dev/null
@@ -1,998 +0,0 @@
-/*
- * Copyright (c) 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
- * 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 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.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.StreamSupport;
-
-
-// TODO(streams): Include in openjdk_java_files.mk
-/**
- * A generator of uniform pseudorandom values applicable for use in
- * (among other contexts) isolated parallel computations that may
- * generate subtasks. Class {@code SplittableRandom} supports methods for
- * producing pseudorandom numbers of type {@code int}, {@code long},
- * and {@code double} with similar usages as for class
- * {@link java.util.Random} but differs in the following ways:
- *
- * <ul>
- *
- * <li>Series of generated values pass the DieHarder suite testing
- * independence and uniformity properties of random number generators.
- * (Most recently validated with <a
- * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
- * 3.31.1</a>.) These tests validate only the methods for certain
- * 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>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>Instances of SplittableRandom are <em>not</em> thread-safe.
- * They are designed to be split, not shared, across threads. For
- * example, a {@link java.util.concurrent.ForkJoinTask
- * fork/join-style} computation using random numbers might include a
- * construction of the form {@code new
- * Subtask(aSplittableRandom.split()).fork()}.
- *
- * <li>This class provides additional methods for generating random
- * streams, that employ the above techniques when used in {@code
- * stream.parallel()} mode.
- *
- * </ul>
- *
- * <p>Instances of {@code SplittableRandom} are not cryptographically
- * secure.  Consider instead using {@link java.security.SecureRandom}
- * in security-sensitive applications. Additionally,
- * default-constructed instances do not use a cryptographically random
- * seed unless the {@linkplain System#getProperty system property}
- * {@code java.util.secureRandomSeed} is set to {@code true}.
- *
- * @author  Guy Steele
- * @author  Doug Lea
- * @since   1.8
- */
-public final class SplittableRandom {
-
-    /*
-     * Implementation Overview.
-     *
-     * This algorithm was inspired by the "DotMix" algorithm by
-     * Leiserson, Schardl, and Sukha "Deterministic Parallel
-     * Random-Number Generation for Dynamic-Multithreading Platforms",
-     * PPoPP 2012, as well as those in "Parallel random numbers: as
-     * easy as 1, 2, 3" by Salmon, Morae, Dror, and Shaw, SC 2011.  It
-     * differs mainly in simplifying and cheapening operations.
-     *
-     * The primary update step (method nextSeed()) is to add a
-     * constant ("gamma") to the current (64 bit) seed, forming a
-     * simple sequence.  The seed and the gamma values for any two
-     * SplittableRandom instances are highly likely to be different.
-     *
-     * Methods nextLong, nextInt, and derivatives do not return the
-     * sequence (seed) values, but instead a hash-like bit-mix of
-     * their bits, producing more independently distributed sequences.
-     * For nextLong, the mix64 function is based on David Stafford's
-     * (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
-     * "Mix13" variant of the "64-bit finalizer" function in Austin
-     * Appleby's MurmurHash3 algorithm (see
-     * http://code.google.com/p/smhasher/wiki/MurmurHash3). The mix32
-     * function is based on Stafford's Mix04 mix function, but returns
-     * the upper 32 bits cast as int.
-     *
-     * The split operation uses the current generator to form the seed
-     * and gamma for another SplittableRandom.  To conservatively
-     * avoid potential correlations between seed and value generation,
-     * gamma selection (method mixGamma) uses different
-     * (Murmurhash3's) mix constants.  To avoid potential weaknesses
-     * in bit-mixing transformations, we restrict gammas to odd values
-     * with at least 24 0-1 or 1-0 bit transitions.  Rather than
-     * rejecting candidates with too few or too many bits set, method
-     * mixGamma flips some bits (which has the effect of mapping at
-     * most 4 to any given gamma value).  This reduces the effective
-     * set of 64bit odd gamma values by about 2%, and serves as an
-     * automated screening for sequence constant selection that is
-     * left as an empirical decision in some other hashing and crypto
-     * algorithms.
-     *
-     * The resulting generator thus transforms a sequence in which
-     * (typically) many bits change on each step, with an inexpensive
-     * mixer with good (but less than cryptographically secure)
-     * avalanching.
-     *
-     * The default (no-argument) constructor, in essence, invokes
-     * split() for a common "defaultGen" SplittableRandom.  Unlike
-     * other cases, this split must be performed in a thread-safe
-     * manner, so we use an AtomicLong to represent the seed rather
-     * than use an explicit SplittableRandom. To bootstrap the
-     * defaultGen, we start off using a seed based on current time
-     * unless the java.util.secureRandomSeed property is set. This
-     * serves as a slimmed-down (and insecure) variant of SecureRandom
-     * that also avoids stalls that may occur when using /dev/random.
-     *
-     * It is a relatively simple matter to apply the basic design here
-     * to use 128 bit seeds. However, emulating 128bit arithmetic and
-     * carrying around twice the state add more overhead than appears
-     * warranted for current usages.
-     *
-     * File organization: First the non-public methods that constitute
-     * the main algorithm, then the main public methods, followed by
-     * some custom spliterator classes needed for stream methods.
-     */
-
-    /**
-     * The golden ratio scaled to 64bits, used as the initial gamma
-     * value for (unsplit) SplittableRandoms.
-     */
-    private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;
-
-    /**
-     * The least non-zero value returned by nextDouble(). This value
-     * is scaled by a random value of 53 bits to produce a result.
-     */
-    private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53);
-
-    /**
-     * The seed. Updated only via method nextSeed.
-     */
-    private long seed;
-
-    /**
-     * The step value.
-     */
-    private final long gamma;
-
-    /**
-     * Internal constructor used by all others except default constructor.
-     */
-    private SplittableRandom(long seed, long gamma) {
-        this.seed = seed;
-        this.gamma = gamma;
-    }
-
-    /**
-     * Computes Stafford variant 13 of 64bit mix function.
-     */
-    private static long mix64(long z) {
-        z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
-        z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
-        return z ^ (z >>> 31);
-    }
-
-    /**
-     * Returns the 32 high bits of Stafford variant 4 mix64 function as int.
-     */
-    private static int mix32(long z) {
-        z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L;
-        return (int)(((z ^ (z >>> 28)) * 0xcb24d0a5c88c35b3L) >>> 32);
-    }
-
-    /**
-     * Returns the gamma value to use for a new split instance.
-     */
-    private static long mixGamma(long z) {
-        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; // MurmurHash3 mix constants
-        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
-        z = (z ^ (z >>> 33)) | 1L;                  // force to be odd
-        int n = Long.bitCount(z ^ (z >>> 1));       // ensure enough transitions
-        return (n < 24) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
-    }
-
-    /**
-     * Adds gamma to seed.
-     */
-    private long nextSeed() {
-        return seed += gamma;
-    }
-
-    // IllegalArgumentException messages
-    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 seed generator for default constructors.
-     */
-    private static final AtomicLong defaultGen
-        = new AtomicLong(mix64(System.currentTimeMillis()) ^
-                         mix64(System.nanoTime()));
-
-    // at end of <clinit> to survive static initialization circularity
-    static {
-        if (java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Boolean>() {
-                public Boolean run() {
-                    return Boolean.getBoolean("java.util.secureRandomSeed");
-                }})) {
-            byte[] seedBytes = java.security.SecureRandom.getSeed(8);
-            long s = (long)seedBytes[0] & 0xffL;
-            for (int i = 1; i < 8; ++i)
-                s = (s << 8) | ((long)seedBytes[i] & 0xffL);
-            defaultGen.set(s);
-        }
-    }
-
-    /*
-     * Internal versions of nextX methods used by streams, as well as
-     * the public nextX(origin, bound) methods.  These exist mainly to
-     * avoid the need for multiple versions of stream spliterators
-     * across the different exported forms of streams.
-     */
-
-    /**
-     * The form of nextLong used by LongStream Spliterators.  If
-     * origin is greater than bound, acts as unbounded form of
-     * nextLong, else as bounded form.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final long internalNextLong(long origin, long bound) {
-        /*
-         * Four Cases:
-         *
-         * 1. If the arguments indicate unbounded form, act as
-         * nextLong().
-         *
-         * 2. If the range is an exact power of two, apply the
-         * associated bit mask.
-         *
-         * 3. If the range is positive, loop to avoid potential bias
-         * when the implicit nextLong() bound (2<sup>64</sup>) is not
-         * evenly divisible by the range. The loop rejects candidates
-         * computed from otherwise over-represented values.  The
-         * expected number of iterations under an ideal generator
-         * varies from 1 to 2, depending on the bound. The loop itself
-         * takes an unlovable form. Because the first candidate is
-         * already available, we need a break-in-the-middle
-         * construction, which is concisely but cryptically performed
-         * within the while-condition of a body-less for loop.
-         *
-         * 4. Otherwise, the range cannot be represented as a positive
-         * long.  The loop repeatedly generates unbounded longs until
-         * obtaining a candidate meeting constraints (with an expected
-         * number of iterations of less than two).
-         */
-
-        long r = mix64(nextSeed());
-        if (origin < bound) {
-            long n = bound - origin, m = n - 1;
-            if ((n & m) == 0L)  // power of two
-                r = (r & m) + origin;
-            else if (n > 0L) {  // reject over-represented candidates
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = mix64(nextSeed()) >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {              // range not representable as long
-                while (r < origin || r >= bound)
-                    r = mix64(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextInt used by IntStream Spliterators.
-     * Exactly the same as long version, except for types.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final int internalNextInt(int origin, int bound) {
-        int r = mix32(nextSeed());
-        if (origin < bound) {
-            int n = bound - origin, m = n - 1;
-            if ((n & m) == 0)
-                r = (r & m) + origin;
-            else if (n > 0) {
-                for (int u = r >>> 1;
-                     u + m - (r = u % n) < 0;
-                     u = mix32(nextSeed()) >>> 1)
-                    ;
-                r += origin;
-            }
-            else {
-                while (r < origin || r >= bound)
-                    r = mix32(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextDouble used by DoubleStream Spliterators.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final double internalNextDouble(double origin, double bound) {
-        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // correct for rounding
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /* ---------------- public methods ---------------- */
-
-    /**
-     * Creates a new SplittableRandom instance using the specified
-     * initial seed. SplittableRandom instances created with the same
-     * seed in the same program generate identical sequences of values.
-     *
-     * @param seed the initial seed
-     */
-    public SplittableRandom(long seed) {
-        this(seed, GOLDEN_GAMMA);
-    }
-
-    /**
-     * Creates a new SplittableRandom instance that is likely to
-     * generate sequences of values that are statistically independent
-     * of those of any other instances in the current program; and
-     * may, and typically does, vary across program invocations.
-     */
-    public SplittableRandom() { // emulate defaultGen.split()
-        long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
-        this.seed = mix64(s);
-        this.gamma = mixGamma(s + GOLDEN_GAMMA);
-    }
-
-    /**
-     * Constructs and returns a new SplittableRandom instance that
-     * shares no mutable state with this instance. However, with very
-     * high probability, the set of values collectively generated by
-     * the two objects has the same statistical properties as if the
-     * same quantity of values were generated by a single thread using
-     * a single SplittableRandom object.  Either or both of the two
-     * objects may be further split using the {@code split()} method,
-     * and the same expected statistical properties apply to the
-     * entire set of generators constructed by such recursive
-     * splitting.
-     *
-     * @return the new SplittableRandom instance
-     */
-    public SplittableRandom split() {
-        return new SplittableRandom(nextLong(), mixGamma(nextSeed()));
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value.
-     *
-     * @return a pseudorandom {@code int} value
-     */
-    public int nextInt() {
-        return mix32(nextSeed());
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code int} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public int nextInt(int bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        // Specialize internalNextInt for origin 0
-        int r = mix32(nextSeed());
-        int m = bound - 1;
-        if ((bound & m) == 0) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (int u = r >>> 1;
-                 u + m - (r = u % bound) < 0;
-                 u = mix32(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code int} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public int nextInt(int origin, int bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextInt(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value.
-     *
-     * @return a pseudorandom {@code long} value
-     */
-    public long nextLong() {
-        return mix64(nextSeed());
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code long} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public long nextLong(long bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        // Specialize internalNextLong for origin 0
-        long r = mix64(nextSeed());
-        long m = bound - 1;
-        if ((bound & m) == 0L) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (long u = r >>> 1;
-                 u + m - (r = u % bound) < 0L;
-                 u = mix64(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code long} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public long nextLong(long origin, long bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextLong(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and one (exclusive)
-     */
-    public double nextDouble() {
-        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between 0.0
-     * (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public double nextDouble(double bound) {
-        if (!(bound > 0.0))
-            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);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between the specified
-     * origin (inclusive) and bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code double} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public double nextDouble(double origin, double bound) {
-        if (!(origin < bound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextDouble(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code boolean} value.
-     *
-     * @return a pseudorandom {@code boolean} value
-     */
-    public boolean nextBoolean() {
-        return mix32(nextSeed()) < 0;
-    }
-
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values from this generator and/or
-     * one split from it.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code int} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public IntStream ints(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, streamSize, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code int}
-     * values from this generator and/or one split from it.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code int} values
-     */
-    public IntStream ints() {
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public IntStream ints(long streamSize, int randomNumberOrigin,
-                          int randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * int} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code long} values from this generator and/or
-     * one split from it.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code long} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public LongStream longs(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, streamSize, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values from this generator and/or one split from it.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code long} values
-     */
-    public LongStream longs() {
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public LongStream longs(long streamSize, long randomNumberOrigin,
-                            long randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values from this generator and/or one split
-     * from it; each value is between zero (inclusive) and one (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of {@code double} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public DoubleStream doubles(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values from this generator and/or one split from it; each value
-     * is between zero (inclusive) and one (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code double} values
-     */
-    public DoubleStream doubles() {
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
-                                double randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Spliterator for int streams.  We multiplex the four int
-     * versions into one class by treating a bound less than origin as
-     * unbounded, and also by treating "infinite" as equivalent to
-     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
-     * approach. The long and double versions of this class are
-     * identical except for types.
-     */
-    private static final class RandomIntsSpliterator
-            implements Spliterator.OfInt {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final int origin;
-        final int bound;
-        RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
-                              int origin, int bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomIntsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextInt(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextInt(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    private static final class RandomLongsSpliterator
-            implements Spliterator.OfLong {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final long origin;
-        final long bound;
-        RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
-                               long origin, long bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomLongsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextLong(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextLong(o, b));
-                } while (++i < f);
-            }
-        }
-
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    private static final class RandomDoublesSpliterator
-            implements Spliterator.OfDouble {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final double origin;
-        final double bound;
-        RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
-                                 double origin, double bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomDoublesSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextDouble(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextDouble(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-}