8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
authordl
Fri, 15 Jul 2016 14:04:09 -0700
changeset 39725 9548f8d846e9
parent 39724 d935d42f6d93
child 39726 0dbf4284a3f6
8080603: Replace Unsafe with VarHandle in java.util.concurrent classes 8153715: Use Unsafe.weakCompareAndSet in java.util.concurrent Reviewed-by: martin, psandoz, rriggs, plevart, dfuchs, shade
jdk/src/java.base/share/classes/java/util/Queue.java
jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java
jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java
jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java
jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java
jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java
jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
jdk/src/java.base/share/classes/java/util/concurrent/package-info.java
jdk/test/java/util/concurrent/tck/Atomic8Test.java
jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java
jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java
jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java
jdk/test/java/util/concurrent/tck/AtomicLong9Test.java
jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java
jdk/test/java/util/concurrent/tck/AtomicReference9Test.java
jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java
jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java
jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java
jdk/test/java/util/concurrent/tck/JSR166TestCase.java
--- a/jdk/src/java.base/share/classes/java/util/Queue.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Queue.java	Fri Jul 15 14:04:09 2016 -0700
@@ -124,7 +124,6 @@
  * always well-defined for queues with the same elements but different
  * ordering properties.
  *
- *
  * <p>This interface is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Jul 15 14:04:09 2016 -0700
@@ -68,6 +68,7 @@
 import java.util.function.ToLongBiFunction;
 import java.util.function.ToLongFunction;
 import java.util.stream.Stream;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A hash table supporting full concurrency of retrievals and
@@ -747,7 +748,7 @@
     /* ---------------- Table element access -------------- */
 
     /*
-     * Volatile access methods are used for table elements as well as
+     * Atomic access methods are used for table elements as well as
      * elements of in-progress next table while resizing.  All uses of
      * the tab arguments must be null checked by callers.  All callers
      * also paranoically precheck that tab's length is not zero (or an
@@ -757,14 +758,12 @@
      * 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 require only release ordering.
      */
 
     @SuppressWarnings("unchecked")
     static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
-        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
+        return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
     }
 
     static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
@@ -773,7 +772,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.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
     }
 
     /* ---------------- Fields -------------- */
@@ -3298,7 +3297,7 @@
             return true;
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private static final long LOCKSTATE;
         static {
             try {
@@ -6341,7 +6340,7 @@
     }
 
     // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractCollection;
 import java.util.Arrays;
 import java.util.Collection;
@@ -292,64 +294,23 @@
         volatile Node<E> prev;
         volatile E item;
         volatile Node<E> next;
-
-        Node() {  // default constructor for NEXT_TERMINATOR, PREV_TERMINATOR
-        }
-
-        /**
-         * Constructs a new node.  Uses relaxed write because item can
-         * only be seen after publication via casNext or casPrev.
-         */
-        Node(E item) {
-            U.putObject(this, ITEM, item);
-        }
-
-        boolean casItem(E cmp, E val) {
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
-        }
-
-        void lazySetNext(Node<E> val) {
-            U.putObjectRelease(this, NEXT, val);
-        }
-
-        boolean casNext(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
-        }
+    }
 
-        void lazySetPrev(Node<E> val) {
-            U.putObjectRelease(this, PREV, val);
-        }
-
-        boolean casPrev(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, PREV, cmp, val);
-        }
-
-        // Unsafe mechanics
-
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long PREV;
-        private static final long ITEM;
-        private static final long NEXT;
-
-        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) {
-                throw new Error(e);
-            }
-        }
+    /**
+     * Returns a new node holding item.  Uses relaxed write because item
+     * can only be seen after piggy-backing publication via CAS.
+     */
+    static <E> Node<E> newNode(E item) {
+        Node<E> node = new Node<E>();
+        ITEM.set(node, item);
+        return node;
     }
 
     /**
      * Links e as first element.
      */
     private void linkFirst(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromHead:
         for (;;)
@@ -363,13 +324,13 @@
                     continue restartFromHead;
                 else {
                     // p is first node
-                    newNode.lazySetNext(p); // CAS piggyback
-                    if (p.casPrev(null, newNode)) {
+                    NEXT.set(newNode, p); // CAS piggyback
+                    if (PREV.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != h) // hop two nodes at a time
-                            casHead(h, newNode);  // Failure is OK.
+                        if (p != h) // hop two nodes at a time; failure is OK
+                            HEAD.weakCompareAndSetVolatile(this, h, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read prev
@@ -381,7 +342,7 @@
      * Links e as last element.
      */
     private void linkLast(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromTail:
         for (;;)
@@ -395,13 +356,13 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    newNode.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, newNode)) {
+                    PREV.set(newNode, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != t) // hop two nodes at a time
-                            casTail(t, newNode);  // Failure is OK.
+                        if (p != t) // hop two nodes at a time; failure is OK
+                            TAIL.weakCompareAndSetVolatile(this, t, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read next
@@ -516,8 +477,8 @@
                 updateTail(); // Ensure x is not reachable from tail
 
                 // Finally, actually gc-unlink
-                x.lazySetPrev(isFirst ? prevTerminator() : x);
-                x.lazySetNext(isLast  ? nextTerminator() : x);
+                PREV.setRelease(x, isFirst ? prevTerminator() : x);
+                NEXT.setRelease(x, isLast  ? nextTerminator() : x);
             }
         }
     }
@@ -531,7 +492,8 @@
         // assert first.item == null;
         for (Node<E> o = null, p = next, q;;) {
             if (p.item != null || (q = p.next) == null) {
-                if (o != null && p.prev != p && first.casNext(next, p)) {
+                if (o != null && p.prev != p &&
+                    NEXT.compareAndSet(first, next, p)) {
                     skipDeletedPredecessors(p);
                     if (first.prev == null &&
                         (p.next == null || p.item != null) &&
@@ -541,8 +503,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetNext(o);
-                        o.lazySetPrev(prevTerminator());
+                        NEXT.setRelease(o, o);
+                        PREV.setRelease(o, prevTerminator());
                     }
                 }
                 return;
@@ -565,7 +527,8 @@
         // assert last.item == null;
         for (Node<E> o = null, p = prev, q;;) {
             if (p.item != null || (q = p.prev) == null) {
-                if (o != null && p.next != p && last.casPrev(prev, p)) {
+                if (o != null && p.next != p &&
+                    PREV.compareAndSet(last, prev, p)) {
                     skipDeletedSuccessors(p);
                     if (last.next == null &&
                         (p.prev == null || p.item != null) &&
@@ -575,8 +538,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetPrev(o);
-                        o.lazySetNext(nextTerminator());
+                        PREV.setRelease(o, o);
+                        NEXT.setRelease(o, nextTerminator());
                     }
                 }
                 return;
@@ -607,7 +570,7 @@
                     (q = (p = q).prev) == null) {
                     // It is possible that p is PREV_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casHead(h, p))
+                    if (HEAD.compareAndSet(this, h, p))
                         return;
                     else
                         continue restartFromHead;
@@ -637,7 +600,7 @@
                     (q = (p = q).next) == null) {
                     // It is possible that p is NEXT_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casTail(t, p))
+                    if (TAIL.compareAndSet(this, t, p))
                         return;
                     else
                         continue restartFromTail;
@@ -675,7 +638,7 @@
             }
 
             // found active CAS target
-            if (prev == p || x.casPrev(prev, p))
+            if (prev == p || PREV.compareAndSet(x, prev, p))
                 return;
 
         } while (x.item != null || x.next == null);
@@ -706,7 +669,7 @@
             }
 
             // found active CAS target
-            if (next == p || x.casNext(next, p))
+            if (next == p || NEXT.compareAndSet(x, next, p))
                 return;
 
         } while (x.item != null || x.prev == null);
@@ -751,7 +714,7 @@
                 else if (p == h
                          // It is possible that p is PREV_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casHead(h, p))
+                         || HEAD.compareAndSet(this, h, p))
                     return p;
                 else
                     continue restartFromHead;
@@ -776,7 +739,7 @@
                 else if (p == t
                          // It is possible that p is NEXT_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casTail(t, p))
+                         || TAIL.compareAndSet(this, t, p))
                     return p;
                 else
                     continue restartFromTail;
@@ -802,7 +765,7 @@
      * Constructs an empty deque.
      */
     public ConcurrentLinkedDeque() {
-        head = tail = new Node<E>(null);
+        head = tail = new Node<E>();
     }
 
     /**
@@ -818,12 +781,12 @@
         // 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));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -836,12 +799,12 @@
     private void initHeadTail(Node<E> h, Node<E> t) {
         if (h == t) {
             if (h == null)
-                h = t = new Node<E>(null);
+                h = t = new Node<E>();
             else {
                 // Avoid edge case of a single Node with non-null item.
-                Node<E> newNode = new Node<E>(null);
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                Node<E> newNode = new Node<E>();
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -934,7 +897,7 @@
     public E pollFirst() {
         for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.item;
-            if (item != null && p.casItem(item, null)) {
+            if (item != null && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return item;
             }
@@ -945,7 +908,7 @@
     public E pollLast() {
         for (Node<E> p = last(); p != null; p = pred(p)) {
             E item = p.item;
-            if (item != null && p.casItem(item, null)) {
+            if (item != null && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return item;
             }
@@ -1031,7 +994,8 @@
         Objects.requireNonNull(o);
         for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            if (item != null && o.equals(item) &&
+                ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1055,7 +1019,8 @@
         Objects.requireNonNull(o);
         for (Node<E> p = last(); p != null; p = pred(p)) {
             E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            if (item != null && o.equals(item) &&
+                ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1159,12 +1124,12 @@
         // 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));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                last.lazySetNext(newNode);
-                newNode.lazySetPrev(last);
+                NEXT.set(last, newNode);
+                PREV.set(newNode, last);
                 last = newNode;
             }
         }
@@ -1184,16 +1149,16 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, beginningOfTheEnd)) {
+                    PREV.set(beginningOfTheEnd, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                         // Successful CAS is the linearization point
                         // for all elements to be added to this deque.
-                        if (!casTail(t, last)) {
+                        if (!TAIL.weakCompareAndSetVolatile(this, t, last)) {
                             // Try a little harder to update tail,
                             // since we may be adding many elements.
                             t = tail;
                             if (last.next == null)
-                                casTail(t, last);
+                                TAIL.weakCompareAndSetVolatile(this, t, last);
                         }
                         return true;
                     }
@@ -1586,41 +1551,38 @@
         Node<E> h = null, t = null;
         for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = new Node<E>((E) item);
+            Node<E> newNode = newNode((E) item);
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
         initHeadTail(h, t);
     }
 
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
-    }
-
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
-    }
-
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle PREV;
+    private static final VarHandle NEXT;
+    private static final VarHandle ITEM;
     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"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedDeque.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedDeque.class, "tail",
+                                   Node.class);
+            PREV = l.findVarHandle(Node.class, "prev", Node.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -166,9 +168,8 @@
      * this is merely an optimization.
      *
      * When constructing a Node (before enqueuing it) we avoid paying
-     * for a volatile write to item by using Unsafe.putObject instead
-     * of a normal write.  This allows the cost of enqueue to be
-     * "one-and-a-half" CASes.
+     * for a volatile write to item.  This allows the cost of enqueue
+     * to be "one-and-a-half" CASes.
      *
      * Both head and tail may or may not point to a Node with a
      * non-null item.  If the queue is empty, all items must of course
@@ -178,33 +179,21 @@
      * optimization.
      */
 
-    private static class Node<E> {
+    static final 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.
+     * can only be seen after piggy-backing publication via CAS.
      */
     static <E> Node<E> newNode(E item) {
         Node<E> node = new Node<E>();
-        U.putObject(node, ITEM, item);
+        ITEM.set(node, item);
         return node;
     }
 
-    static <E> boolean casItem(Node<E> node, E cmp, E val) {
-        return U.compareAndSwapObject(node, ITEM, cmp, val);
-    }
-
-    static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putObjectRelease(node, NEXT, val);
-    }
-
-    static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(node, NEXT, cmp, val);
-    }
-
     /**
      * A node from which the first live (non-deleted) node (if any)
      * can be reached in O(1) time.
@@ -256,7 +245,7 @@
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                NEXT.set(t, newNode);
                 t = newNode;
             }
         }
@@ -286,8 +275,8 @@
      */
     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);
+        if (h != p && HEAD.compareAndSet(this, h, p))
+            NEXT.setRelease(h, h);
     }
 
     /**
@@ -314,12 +303,12 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, newNode)) {
+                if (NEXT.compareAndSet(p, null, newNode)) {
                     // Successful CAS is the linearization point
                     // for e to become an element of this queue,
                     // and for newNode to become "live".
-                    if (p != t) // hop two nodes at a time
-                        casTail(t, newNode);  // Failure is OK.
+                    if (p != t) // hop two nodes at a time; failure is OK
+                        TAIL.weakCompareAndSetVolatile(this, t, newNode);
                     return true;
                 }
                 // Lost CAS race to another thread; re-read next
@@ -342,7 +331,7 @@
             for (Node<E> h = head, p = h, q;;) {
                 E item = p.item;
 
-                if (item != null && casItem(p, item, null)) {
+                if (item != null && ITEM.compareAndSet(p, item, null)) {
                     // Successful CAS is the linearization point
                     // for item to be removed from this queue.
                     if (p != h) // hop two nodes at a time
@@ -483,12 +472,12 @@
                         next = succ(p);
                         continue;
                     }
-                    removed = casItem(p, item, null);
+                    removed = ITEM.compareAndSet(p, item, null);
                 }
 
                 next = succ(p);
                 if (pred != null && next != null) // unlink
-                    casNext(pred, p, next);
+                    NEXT.weakCompareAndSetVolatile(pred, p, next);
                 if (removed)
                     return true;
             }
@@ -520,7 +509,7 @@
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                lazySetNext(last, newNode);
+                NEXT.set(last, newNode);
                 last = newNode;
             }
         }
@@ -532,15 +521,15 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, beginningOfTheEnd)) {
+                if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                     // Successful CAS is the linearization point
                     // for all elements to be added to this queue.
-                    if (!casTail(t, last)) {
+                    if (!TAIL.weakCompareAndSetVolatile(this, t, last)) {
                         // Try a little harder to update tail,
                         // since we may be adding many elements.
                         t = tail;
                         if (last.next == null)
-                            casTail(t, last);
+                            TAIL.weakCompareAndSetVolatile(this, t, last);
                     }
                     return true;
                 }
@@ -744,7 +733,7 @@
                 }
                 // unlink deleted nodes
                 if ((q = succ(p)) != null)
-                    casNext(pred, p, q);
+                    NEXT.compareAndSet(pred, p, q);
             }
         }
 
@@ -801,7 +790,7 @@
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                NEXT.set(t, newNode);
                 t = newNode;
             }
         }
@@ -919,31 +908,20 @@
         return new CLQSpliterator<E>(this);
     }
 
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
-    }
-
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
-    }
-
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long ITEM;
-    private static final long NEXT;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle ITEM;
+    private static final VarHandle NEXT;
     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"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedQueue.class, "tail",
+                                   Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.io.Serializable;
 import java.util.AbstractCollection;
 import java.util.AbstractMap;
@@ -401,7 +403,7 @@
      * compareAndSet head node.
      */
     private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return HEAD.compareAndSet(this, cmp, val);
     }
 
     /* ---------------- Nodes -------------- */
@@ -444,14 +446,14 @@
          * compareAndSet value field.
          */
         boolean casValue(Object cmp, Object val) {
-            return U.compareAndSwapObject(this, VALUE, cmp, val);
+            return VALUE.compareAndSet(this, cmp, val);
         }
 
         /**
          * compareAndSet next field.
          */
         boolean casNext(Node<K,V> cmp, Node<K,V> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return NEXT.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -532,20 +534,16 @@
             return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
         }
 
-        // Unsafe mechanics
-
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
-        private static final long NEXT;
-
+        // VarHandle mechanics
+        private static final VarHandle VALUE;
+        private static final VarHandle NEXT;
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Node.class.getDeclaredField("value"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                VALUE = l.findVarHandle(Node.class, "value", Object.class);
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                    throw new Error(e);
             }
         }
     }
@@ -577,7 +575,7 @@
          * compareAndSet right field.
          */
         final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
-            return U.compareAndSwapObject(this, RIGHT, cmp, val);
+            return RIGHT.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -613,13 +611,12 @@
             return node.value != null && casRight(succ, succ.right);
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long RIGHT;
+        // VarHandle mechanics
+        private static final VarHandle RIGHT;
         static {
             try {
-                RIGHT = U.objectFieldOffset
-                    (Index.class.getDeclaredField("right"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                RIGHT = l.findVarHandle(Index.class, "right", Index.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -3607,13 +3604,13 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentSkipListMap.class.getDeclaredField("head"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentSkipListMap.class, "head",
+                                   HeadIndex.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
@@ -507,15 +509,16 @@
 
     // Support for resetting map in clone
     private void setMap(ConcurrentNavigableMap<E,Object> map) {
-        U.putObjectVolatile(this, MAP, map);
+        MAP.setVolatile(this, map);
     }
 
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long MAP;
+    // VarHandle mechanics
+    private static final VarHandle MAP;
     static {
         try {
-            MAP = U.objectFieldOffset
-                (ConcurrentSkipListSet.class.getDeclaredField("m"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            MAP = l.findVarHandle(ConcurrentSkipListSet.class, "m",
+                                  ConcurrentNavigableMap.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Jul 15 14:04:09 2016 -0700
@@ -34,6 +34,7 @@
 
 package java.util.concurrent;
 
+import java.lang.reflect.Field;
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -1541,17 +1542,21 @@
         }
     }
 
-    // Support for resetting lock while deserializing
+    /** Initializes the lock; for use when deserializing or cloning. */
     private void resetLock() {
-        U.putObjectVolatile(this, LOCK, new Object());
-    }
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long LOCK;
-    static {
+        Field lockField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = CopyOnWriteArrayList.class
+                        .getDeclaredField("lock");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
         try {
-            LOCK = U.objectFieldOffset
-                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
-        } catch (ReflectiveOperationException e) {
+            lockField.set(this, new Object());
+        } catch (IllegalAccessException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@link ForkJoinTask} with a completion action performed when
  * triggered and there are no remaining pending actions.
@@ -524,7 +527,7 @@
      * @param delta the value to add
      */
     public final void addToPendingCount(int delta) {
-        U.getAndAddInt(this, PENDING, delta);
+        PENDING.getAndAdd(this, delta);
     }
 
     /**
@@ -536,7 +539,7 @@
      * @return {@code true} if successful
      */
     public final boolean compareAndSetPendingCount(int expected, int count) {
-        return U.compareAndSwapInt(this, PENDING, expected, count);
+        return PENDING.compareAndSet(this, expected, count);
     }
 
     /**
@@ -548,7 +551,7 @@
     public final int decrementPendingCountUnlessZero() {
         int c;
         do {} while ((c = pending) != 0 &&
-                     !U.compareAndSwapInt(this, PENDING, c, c - 1));
+                     !PENDING.weakCompareAndSetVolatile(this, c, c - 1));
         return c;
     }
 
@@ -581,7 +584,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(a, c, c - 1))
                 return;
         }
     }
@@ -604,7 +607,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(a, c, c - 1))
                 return;
         }
     }
@@ -649,7 +652,7 @@
         for (int c;;) {
             if ((c = pending) == 0)
                 return this;
-            else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(this, c, c - 1))
                 return null;
         }
     }
@@ -753,13 +756,13 @@
      */
     protected void setRawResult(T t) { }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PENDING;
+    // VarHandle mechanics
+    private static final VarHandle PENDING;
     static {
         try {
-            PENDING = U.objectFieldOffset
-                (CountedCompleter.class.getDeclaredField("pending"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PENDING = l.findVarHandle(CountedCompleter.class, "pending", int.class);
+
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Fri Jul 15 14:04:09 2016 -0700
@@ -36,6 +36,10 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.concurrent.locks.LockSupport;
+
 /**
  * A synchronization point at which threads can pair and swap elements
  * within pairs.  Each thread presents some object on entry to the
@@ -155,9 +159,7 @@
      * 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.
+     * @Contended) to Nodes, embedding "bound" as an Exchanger field.
      *
      * The arena starts out with only one used slot. We expand the
      * effective arena size by tracking collisions; i.e., failed CASes
@@ -234,12 +236,12 @@
      * because most of the logic relies on reads of fields that are
      * maintained as local variables so can't be nicely factored --
      * mainly, here, bulky spin->yield->block/cancel code), and
-     * heavily dependent on intrinsics (Unsafe) to use inlined
+     * heavily dependent on intrinsics (VarHandles) to use inlined
      * embedded CAS and related memory access operations (that tend
      * not to be as readily inlined by dynamic compilers when they are
      * hidden behind other methods that would more nicely name and
      * encapsulate the intended effects). This includes the use of
-     * putXRelease to clear fields of the per-thread Nodes between
+     * setRelease to clear fields of the per-thread Nodes between
      * uses. Note that field Node.item is not declared as volatile
      * even though it is read by releasing threads, because they only
      * do so after CAS operations that must precede access, and all
@@ -252,10 +254,10 @@
      */
 
     /**
-     * The byte distance (as a shift value) between any two used slots
-     * in the arena.  1 << ASHIFT should be at least cacheline size.
+     * The index distance (as a shift value) between any two used slots
+     * in the arena, spacing them out to avoid false sharing.
      */
-    private static final int ASHIFT = 7;
+    private static final int ASHIFT = 5;
 
     /**
      * The maximum supported arena index. The maximum allocatable
@@ -356,27 +358,31 @@
      */
     private final Object arenaExchange(Object item, boolean timed, long ns) {
         Node[] a = arena;
+        int alen = a.length;
         Node p = participant.get();
         for (int i = p.index;;) {                      // access slot at i
-            int b, m, c; long j;                       // j is raw array offset
-            Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
-            if (q != null && U.compareAndSwapObject(a, j, q, null)) {
+            int b, m, c;
+            int j = (i << ASHIFT) + ((1 << ASHIFT) - 1);
+            if (j < 0 || j >= alen)
+                j = alen - 1;
+            Node q = (Node)AA.getAcquire(a, j);
+            if (q != null && AA.compareAndSet(a, j, q, null)) {
                 Object v = q.item;                     // release
                 q.match = item;
                 Thread w = q.parked;
                 if (w != null)
-                    U.unpark(w);
+                    LockSupport.unpark(w);
                 return v;
             }
             else if (i <= (m = (b = bound) & MMASK) && q == null) {
                 p.item = item;                         // offer
-                if (U.compareAndSwapObject(a, j, null, p)) {
+                if (AA.compareAndSet(a, j, null, p)) {
                     long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
                     Thread t = Thread.currentThread(); // wait
                     for (int h = p.hash, spins = SPINS;;) {
                         Object v = p.match;
                         if (v != null) {
-                            U.putObjectRelease(p, MATCH, null);
+                            MATCH.setRelease(p, null);
                             p.item = null;             // clear for next use
                             p.hash = h;
                             return v;
@@ -389,22 +395,24 @@
                                      (--spins & ((SPINS >>> 1) - 1)) == 0)
                                 Thread.yield();        // two yields per wait
                         }
-                        else if (U.getObjectVolatile(a, j) != p)
+                        else if (AA.getAcquire(a, j) != p)
                             spins = SPINS;       // releaser hasn't set match yet
                         else if (!t.isInterrupted() && m == 0 &&
                                  (!timed ||
                                   (ns = end - System.nanoTime()) > 0L)) {
-                            U.putObject(t, BLOCKER, this); // emulate LockSupport
                             p.parked = t;              // minimize window
-                            if (U.getObjectVolatile(a, j) == p)
-                                U.park(false, ns);
+                            if (AA.getAcquire(a, j) == p) {
+                                if (ns == 0L)
+                                    LockSupport.park(this);
+                                else
+                                    LockSupport.parkNanos(this, ns);
+                            }
                             p.parked = null;
-                            U.putObject(t, BLOCKER, null);
                         }
-                        else if (U.getObjectVolatile(a, j) == p &&
-                                 U.compareAndSwapObject(a, j, p, null)) {
+                        else if (AA.getAcquire(a, j) == p &&
+                                 AA.compareAndSet(a, j, p, null)) {
                             if (m != 0)                // try to shrink
-                                U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
+                                BOUND.compareAndSet(this, b, b + SEQ - 1);
                             p.item = null;
                             p.hash = h;
                             i = p.index >>>= 1;        // descend
@@ -426,7 +434,7 @@
                     i = (i != m || m == 0) ? m : m - 1;
                 }
                 else if ((c = p.collides) < m || m == FULL ||
-                         !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
+                         !BOUND.compareAndSet(this, b, b + SEQ + 1)) {
                     p.collides = c + 1;
                     i = (i == 0) ? m : i - 1;          // cyclically traverse
                 }
@@ -455,24 +463,24 @@
 
         for (Node q;;) {
             if ((q = slot) != null) {
-                if (U.compareAndSwapObject(this, SLOT, q, null)) {
+                if (SLOT.compareAndSet(this, q, null)) {
                     Object v = q.item;
                     q.match = item;
                     Thread w = q.parked;
                     if (w != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                     return v;
                 }
                 // create arena on contention, but continue until slot null
                 if (NCPU > 1 && bound == 0 &&
-                    U.compareAndSwapInt(this, BOUND, 0, SEQ))
+                    BOUND.compareAndSet(this, 0, SEQ))
                     arena = new Node[(FULL + 2) << ASHIFT];
             }
             else if (arena != null)
                 return null; // caller must reroute to arenaExchange
             else {
                 p.item = item;
-                if (U.compareAndSwapObject(this, SLOT, null, p))
+                if (SLOT.compareAndSet(this, null, p))
                     break;
                 p.item = null;
             }
@@ -495,19 +503,21 @@
                 spins = SPINS;
             else if (!t.isInterrupted() && arena == null &&
                      (!timed || (ns = end - System.nanoTime()) > 0L)) {
-                U.putObject(t, BLOCKER, this);
                 p.parked = t;
-                if (slot == p)
-                    U.park(false, ns);
+                if (slot == p) {
+                    if (ns == 0L)
+                        LockSupport.park(this);
+                    else
+                        LockSupport.parkNanos(this, ns);
+                }
                 p.parked = null;
-                U.putObject(t, BLOCKER, null);
             }
-            else if (U.compareAndSwapObject(this, SLOT, p, null)) {
+            else if (SLOT.compareAndSet(this, p, null)) {
                 v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
                 break;
             }
         }
-        U.putObjectRelease(p, MATCH, null);
+        MATCH.setRelease(p, null);
         p.item = null;
         p.hash = h;
         return v;
@@ -556,8 +566,9 @@
     @SuppressWarnings("unchecked")
     public V exchange(V x) throws InterruptedException {
         Object v;
+        Node[] a;
         Object item = (x == null) ? NULL_ITEM : x; // translate null args
-        if ((arena != null ||
+        if (((a = arena) != null ||
              (v = slotExchange(item, false, 0L)) == null) &&
             ((Thread.interrupted() || // disambiguates null return
               (v = arenaExchange(item, false, 0L)) == null)))
@@ -623,31 +634,18 @@
         return (v == NULL_ITEM) ? null : (V)v;
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long BOUND;
-    private static final long SLOT;
-    private static final long MATCH;
-    private static final long BLOCKER;
-    private static final int ABASE;
+    // VarHandle mechanics
+    private static final VarHandle BOUND;
+    private static final VarHandle SLOT;
+    private static final VarHandle MATCH;
+    private static final VarHandle AA;
     static {
         try {
-            BOUND = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("bound"));
-            SLOT = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("slot"));
-
-            MATCH = U.objectFieldOffset
-                (Node.class.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");
-            // ABASE absorbs padding in front of element 0
-            ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
+            SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
+            MATCH = l.findVarHandle(Node.class, "match", Object.class);
+            AA = MethodHandles.arrayElementVarHandle(Node[].class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -69,9 +71,6 @@
      * cancellation races. Sync control in the current design relies
      * on a "state" field updated via CAS to track completion, along
      * with a simple Treiber stack to hold waiting threads.
-     *
-     * Style note: As usual, we bypass overhead of using
-     * AtomicXFieldUpdaters and instead directly use Unsafe intrinsics.
      */
 
     /**
@@ -163,9 +162,8 @@
     }
 
     public boolean cancel(boolean mayInterruptIfRunning) {
-        if (!(state == NEW &&
-              U.compareAndSwapInt(this, STATE, NEW,
-                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
+        if (!(state == NEW && STATE.compareAndSet
+              (this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
             return false;
         try {    // in case call to interrupt throws exception
             if (mayInterruptIfRunning) {
@@ -174,7 +172,7 @@
                     if (t != null)
                         t.interrupt();
                 } finally { // final state
-                    U.putIntRelease(this, STATE, INTERRUPTED);
+                    STATE.setRelease(this, INTERRUPTED);
                 }
             }
         } finally {
@@ -228,9 +226,9 @@
      * @param v the value
      */
     protected void set(V v) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = v;
-            U.putIntRelease(this, STATE, NORMAL); // final state
+            STATE.setRelease(this, NORMAL); // final state
             finishCompletion();
         }
     }
@@ -246,16 +244,16 @@
      * @param t the cause of failure
      */
     protected void setException(Throwable t) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = t;
-            U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
+            STATE.setRelease(this, EXCEPTIONAL); // final state
             finishCompletion();
         }
     }
 
     public void run() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return;
         try {
             Callable<V> c = callable;
@@ -296,7 +294,7 @@
      */
     protected boolean runAndReset() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return false;
         boolean ran = false;
         int s = state;
@@ -363,7 +361,7 @@
     private void finishCompletion() {
         // assert state > COMPLETING;
         for (WaitNode q; (q = waiters) != null;) {
-            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
+            if (WAITERS.weakCompareAndSetVolatile(this, q, null)) {
                 for (;;) {
                     Thread t = q.thread;
                     if (t != null) {
@@ -425,8 +423,7 @@
                 q = new WaitNode();
             }
             else if (!queued)
-                queued = U.compareAndSwapObject(this, WAITERS,
-                                                q.next = waiters, q);
+                queued = WAITERS.weakCompareAndSetVolatile(this, q.next = waiters, q);
             else if (timed) {
                 final long parkNanos;
                 if (startTime == 0L) { // first time
@@ -475,7 +472,7 @@
                         if (pred.thread == null) // check for race
                             continue retry;
                     }
-                    else if (!U.compareAndSwapObject(this, WAITERS, q, s))
+                    else if (!WAITERS.compareAndSet(this, q, s))
                         continue retry;
                 }
                 break;
@@ -483,19 +480,16 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long RUNNER;
-    private static final long WAITERS;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle RUNNER;
+    private static final VarHandle WAITERS;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("state"));
-            RUNNER = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("runner"));
-            WAITERS = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("waiters"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
+            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
+            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -444,7 +446,7 @@
 
     /**
      * Queue nodes. Uses Object, not E, for items to allow forgetting
-     * them after use.  Relies heavily on Unsafe mechanics to minimize
+     * them after use.  Relies heavily on VarHandles to minimize
      * unnecessary ordering constraints: Writes that are intrinsically
      * ordered wrt other accesses or CASes use simple relaxed forms.
      */
@@ -456,12 +458,12 @@
 
         // CAS methods for fields
         final boolean casNext(Node cmp, Node val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return NEXT.compareAndSet(this, cmp, val);
         }
 
         final boolean casItem(Object cmp, Object val) {
             // assert cmp == null || cmp.getClass() != Node.class;
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
+            return ITEM.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -469,7 +471,7 @@
          * only be seen after publication via casNext.
          */
         Node(Object item, boolean isData) {
-            U.putObject(this, ITEM, item); // relaxed write
+            ITEM.set(this, item); // relaxed write
             this.isData = isData;
         }
 
@@ -478,7 +480,7 @@
          * only after CASing head field, so uses relaxed write.
          */
         final void forgetNext() {
-            U.putObject(this, NEXT, this);
+            NEXT.set(this, this);
         }
 
         /**
@@ -491,8 +493,8 @@
          * else we don't care).
          */
         final void forgetContents() {
-            U.putObject(this, ITEM, this);
-            U.putObject(this, WAITER, null);
+            ITEM.set(this, this);
+            WAITER.set(this, null);
         }
 
         /**
@@ -537,19 +539,16 @@
 
         private static final long serialVersionUID = -3375979862319811754L;
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long ITEM;
-        private static final long NEXT;
-        private static final long WAITER;
+        // VarHandle mechanics
+        private static final VarHandle ITEM;
+        private static final VarHandle NEXT;
+        private static final VarHandle WAITER;
         static {
             try {
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                WAITER = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waiter"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                ITEM = l.findVarHandle(Node.class, "item", Object.class);
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
+                WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -567,15 +566,15 @@
 
     // CAS methods for fields
     private boolean casTail(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        return TAIL.compareAndSet(this, cmp, val);
     }
 
     private boolean casHead(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return HEAD.compareAndSet(this, cmp, val);
     }
 
     private boolean casSweepVotes(int cmp, int val) {
-        return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
+        return SWEEPVOTES.compareAndSet(this, cmp, val);
     }
 
     /*
@@ -1562,20 +1561,19 @@
         }
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long SWEEPVOTES;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle SWEEPVOTES;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("tail"));
-            SWEEPVOTES = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(LinkedTransferQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(LinkedTransferQueue.class, "tail",
+                                   Node.class);
+            SWEEPVOTES = l.findVarHandle(LinkedTransferQueue.class, "sweepVotes",
+                                         int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 
@@ -221,7 +223,6 @@
  *   phaser.arriveAndDeregister();
  * }}</pre>
  *
- *
  * <p>To create a set of {@code n} tasks using a tree of phasers, you
  * could use code of the following form, assuming a Task class with a
  * constructor accepting a {@code Phaser} that it registers with upon
@@ -384,7 +385,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 (STATE.compareAndSet(this, s, s-=adjust)) {
                 if (unarrived == 1) {
                     long n = s & PARTIES_MASK;  // base of next state
                     int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -397,12 +398,12 @@
                             n |= nextUnarrived;
                         int nextPhase = (phase + 1) & MAX_PHASE;
                         n |= (long)nextPhase << PHASE_SHIFT;
-                        U.compareAndSwapLong(this, STATE, s, n);
+                        STATE.compareAndSet(this, s, n);
                         releaseWaiters(phase);
                     }
                     else if (nextUnarrived == 0) { // propagate deregistration
                         phase = parent.doArrive(ONE_DEREGISTER);
-                        U.compareAndSwapLong(this, STATE, s, s | EMPTY);
+                        STATE.compareAndSet(this, s, s | EMPTY);
                     }
                     else
                         phase = parent.doArrive(ONE_ARRIVAL);
@@ -437,13 +438,13 @@
                 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 (STATE.compareAndSet(this, 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 (STATE.compareAndSet(this, s, next))
                     break;
             }
             else {
@@ -455,8 +456,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 (!STATE.weakCompareAndSetVolatile
+                               (this, s,
                                 ((long)phase << PHASE_SHIFT) | adjust)) {
                             s = state;
                             phase = (int)(root.state >>> PHASE_SHIFT);
@@ -487,8 +488,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,
+                   !STATE.weakCompareAndSetVolatile
+                   (this, s,
                     s = (((long)phase << PHASE_SHIFT) |
                          ((phase < 0) ? (s & COUNTS_MASK) :
                           (((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -677,7 +678,7 @@
             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 (STATE.compareAndSet(this, s, s -= ONE_ARRIVAL)) {
                 if (unarrived > 1)
                     return root.internalAwaitAdvance(phase, null);
                 if (root != this)
@@ -692,7 +693,7 @@
                     n |= nextUnarrived;
                 int nextPhase = (phase + 1) & MAX_PHASE;
                 n |= (long)nextPhase << PHASE_SHIFT;
-                if (!U.compareAndSwapLong(this, STATE, s, n))
+                if (!STATE.compareAndSet(this, s, n))
                     return (int)(state >>> PHASE_SHIFT); // terminated
                 releaseWaiters(phase);
                 return nextPhase;
@@ -808,7 +809,7 @@
         final Phaser root = this.root;
         long s;
         while ((s = root.state) >= 0) {
-            if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
+            if (STATE.compareAndSet(root, s, s | TERMINATION_BIT)) {
                 // signal all threads
                 releaseWaiters(0); // Waiters on evenQ
                 releaseWaiters(1); // Waiters on oddQ
@@ -1043,6 +1044,8 @@
                     node = new QNode(this, phase, false, false, 0L);
                     node.wasInterrupted = interrupted;
                 }
+                else
+                    Thread.onSpinWait();
             }
             else if (node.isReleasable()) // done or aborted
                 break;
@@ -1131,14 +1134,12 @@
         }
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (Phaser.class.getDeclaredField("state"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(Phaser.class, "state", long.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -289,7 +291,7 @@
         lock.unlock(); // must release and then re-acquire main lock
         Object[] newArray = null;
         if (allocationSpinLock == 0 &&
-            U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
+            ALLOCATIONSPINLOCK.compareAndSet(this, 0, 1)) {
             try {
                 int newCap = oldCap + ((oldCap < 64) ?
                                        (oldCap + 2) : // grow faster if small
@@ -1009,13 +1011,14 @@
         return new PBQSpliterator<E>(this, null, 0, -1);
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long ALLOCATIONSPINLOCK;
+    // VarHandle mechanics
+    private static final VarHandle ALLOCATIONSPINLOCK;
     static {
         try {
-            ALLOCATIONSPINLOCK = U.objectFieldOffset
-                (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            ALLOCATIONSPINLOCK = l.findVarHandle(PriorityBlockingQueue.class,
+                                                 "allocationSpinLock",
+                                                 int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Fri Jul 15 14:04:09 2016 -0700
@@ -36,6 +36,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Collection;
 import java.util.Collections;
@@ -247,7 +249,7 @@
 
             boolean casNext(SNode cmp, SNode val) {
                 return cmp == next &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    SNEXT.compareAndSet(this, cmp, val);
             }
 
             /**
@@ -260,7 +262,7 @@
              */
             boolean tryMatch(SNode s) {
                 if (match == null &&
-                    U.compareAndSwapObject(this, MATCH, null, s)) {
+                    SMATCH.compareAndSet(this, null, s)) {
                     Thread w = waiter;
                     if (w != null) {    // waiters need at most one unpark
                         waiter = null;
@@ -275,24 +277,21 @@
              * Tries to cancel a wait by matching node to itself.
              */
             void tryCancel() {
-                U.compareAndSwapObject(this, MATCH, null, this);
+                SMATCH.compareAndSet(this, null, this);
             }
 
             boolean isCancelled() {
                 return match == this;
             }
 
-            // Unsafe mechanics
-            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-            private static final long MATCH;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle SMATCH;
+            private static final VarHandle SNEXT;
             static {
                 try {
-                    MATCH = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("match"));
-                    NEXT = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    SMATCH = l.findVarHandle(SNode.class, "match", SNode.class);
+                    SNEXT = l.findVarHandle(SNode.class, "next", SNode.class);
                 } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
@@ -304,7 +303,7 @@
 
         boolean casHead(SNode h, SNode nh) {
             return h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh);
+                SHEAD.compareAndSet(this, h, nh);
         }
 
         /**
@@ -451,8 +450,10 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
+                    Thread.onSpinWait();
                     spins = shouldSpin(s) ? (spins - 1) : 0;
+                }
                 else if (s.waiter == null)
                     s.waiter = w; // establish waiter so can park next iter
                 else if (!timed)
@@ -508,13 +509,12 @@
             }
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
+        // VarHandle mechanics
+        private static final VarHandle SHEAD;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferStack.class.getDeclaredField("head"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                SHEAD = l.findVarHandle(TransferStack.class, "head", SNode.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -546,19 +546,19 @@
 
             boolean casNext(QNode cmp, QNode val) {
                 return next == cmp &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    QNEXT.compareAndSet(this, cmp, val);
             }
 
             boolean casItem(Object cmp, Object val) {
                 return item == cmp &&
-                    U.compareAndSwapObject(this, ITEM, cmp, val);
+                    QITEM.compareAndSet(this, cmp, val);
             }
 
             /**
              * Tries to cancel by CAS'ing ref to this as item.
              */
             void tryCancel(Object cmp) {
-                U.compareAndSwapObject(this, ITEM, cmp, this);
+                QITEM.compareAndSet(this, cmp, this);
             }
 
             boolean isCancelled() {
@@ -574,17 +574,14 @@
                 return next == this;
             }
 
-            // Unsafe mechanics
-            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-            private static final long ITEM;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle QITEM;
+            private static final VarHandle QNEXT;
             static {
                 try {
-                    ITEM = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("item"));
-                    NEXT = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    QITEM = l.findVarHandle(QNode.class, "item", Object.class);
+                    QNEXT = l.findVarHandle(QNode.class, "next", QNode.class);
                 } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
@@ -614,7 +611,7 @@
          */
         void advanceHead(QNode h, QNode nh) {
             if (h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh))
+                QHEAD.compareAndSet(this, h, nh))
                 h.next = h; // forget old next
         }
 
@@ -623,7 +620,7 @@
          */
         void advanceTail(QNode t, QNode nt) {
             if (tail == t)
-                U.compareAndSwapObject(this, TAIL, t, nt);
+                QTAIL.compareAndSet(this, t, nt);
         }
 
         /**
@@ -631,7 +628,7 @@
          */
         boolean casCleanMe(QNode cmp, QNode val) {
             return cleanMe == cmp &&
-                U.compareAndSwapObject(this, CLEANME, cmp, val);
+                QCLEANME.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -752,8 +749,10 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
                     --spins;
+                    Thread.onSpinWait();
+                }
                 else if (s.waiter == null)
                     s.waiter = w;
                 else if (!timed)
@@ -817,18 +816,19 @@
             }
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
-        private static final long TAIL;
-        private static final long CLEANME;
+        // VarHandle mechanics
+        private static final VarHandle QHEAD;
+        private static final VarHandle QTAIL;
+        private static final VarHandle QCLEANME;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("head"));
-                TAIL = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("tail"));
-                CLEANME = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("cleanMe"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                QHEAD = l.findVarHandle(TransferQueue.class, "head",
+                                        QNode.class);
+                QTAIL = l.findVarHandle(TransferQueue.class, "tail",
+                                        QNode.class);
+                QCLEANME = l.findVarHandle(TransferQueue.class, "cleanMe",
+                                           QNode.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,27 +35,26 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@code boolean} value that may be updated atomically. See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicBoolean} is used in applications such as atomically
- * updated flags, and cannot be used as a replacement for a
- * {@link java.lang.Boolean}.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicBoolean} is used in
+ * applications such as atomically updated flags, and cannot be used
+ * as a replacement for a {@link java.lang.Boolean}.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicBoolean.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicBoolean.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -79,7 +78,8 @@
     }
 
     /**
-     * Returns the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -88,40 +88,39 @@
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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));
+    public final boolean compareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.compareAndSet(this,
+                                   (expectedValue ? 1 : 0),
+                                   (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public boolean weakCompareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+    public boolean weakCompareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSet(this,
+                                       (expectedValue ? 1 : 0),
+                                       (newValue ? 1 : 0));
     }
 
     /**
-     * Unconditionally sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -130,17 +129,19 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
+        VALUE.setRelease(this, (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets to the given value and returns the previous value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
@@ -161,4 +162,178 @@
         return Boolean.toString(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getPlain() {
+        return (int)VALUE.get(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(boolean newValue) {
+        VALUE.set(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getOpaque() {
+        return (int)VALUE.getOpaque(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(boolean newValue) {
+        VALUE.setOpaque(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getAcquire() {
+        return (int)VALUE.getAcquire(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(boolean newValue) {
+        VALUE.setRelease(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchange(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchange(this,
+                                             (expectedValue ? 1 : 0),
+                                             (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeAcquire(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeAcquire(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeRelease(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeRelease(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetVolatile(this,
+                                               (expectedValue ? 1 : 0),
+                                               (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetAcquire(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetRelease(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,32 +35,30 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicInteger} is used in applications such as atomically
- * incremented counters, and cannot be used as a replacement for an
- * {@link java.lang.Integer}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicInteger} is used in
+ * applications such as atomically incremented counters, and cannot be
+ * used as a replacement for an {@link java.lang.Integer}. However,
+ * this class does extend {@code Number} to allow uniform access by
+ * tools and utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicInteger.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicInteger.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -84,7 +82,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -93,7 +92,8 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -102,108 +102,122 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putIntRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        return U.getAndSetInt(this, VALUE, newValue);
+        return (int)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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);
+    public final boolean compareAndSet(int expectedValue, int newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+    public final boolean weakCompareAndSet(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final int getAndIncrement() {
-        return U.getAndAddInt(this, VALUE, 1);
+        return (int)VALUE.getAndAdd(this, 1);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final int getAndDecrement() {
-        return U.getAndAddInt(this, VALUE, -1);
+        return (int)VALUE.getAndAdd(this, -1);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        return U.getAndAddInt(this, VALUE, delta);
+        return (int)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final int incrementAndGet() {
-        return U.getAndAddInt(this, VALUE, 1) + 1;
+        return (int)VALUE.addAndGet(this, 1);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final int decrementAndGet() {
-        return U.getAndAddInt(this, VALUE, -1) - 1;
+        return (int)VALUE.addAndGet(this, -1);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        return U.getAndAddInt(this, VALUE, delta) + delta;
+        return (int)VALUE.addAndGet(this, delta);
     }
 
     /**
@@ -217,12 +231,14 @@
      * @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;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -236,12 +252,14 @@
      * @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;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -260,12 +278,14 @@
      */
     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;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -284,12 +304,14 @@
      */
     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;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -301,7 +323,10 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as an {@code int}.
+     * Returns the current value of this {@code AtomicInteger} as an
+     * {@code int},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
+     *
      * Equivalent to {@link #get()}.
      */
     public int intValue() {
@@ -309,8 +334,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code long}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code long} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public long longValue() {
@@ -318,8 +344,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code float} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -327,12 +354,175 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code double} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain() {
+        return (int)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque() {
+        return (int)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire() {
+        return (int)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,44 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(int[].class);
     private final int[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(int[].class);
-        int scale = U.arrayIndexScale(int[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicIntegerArray of the given length, with all
      * elements initially zero.
@@ -105,147 +85,155 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final int get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private int getRaw(long offset) {
-        return U.getIntVolatile(array, offset);
+        return (int)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, int newValue) {
-        U.putIntVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putIntRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int i, int newValue) {
-        return U.getAndSetInt(array, checkedByteOffset(i), newValue);
+        return (int)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, int expect, int update) {
-        return U.compareAndSwapInt(array, offset, expect, update);
+    public final boolean compareAndSet(int i, int expectedValue, int newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, int expect, int update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (int)AA.getAndAdd(array, i, 1);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (int)AA.getAndAdd(array, i, -1);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
-        return U.getAndAddInt(array, checkedByteOffset(i), delta);
+        return (int)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (int)AA.addAndGet(array, i, 1);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (int)AA.addAndGet(array, i, -1);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
-        return getAndAdd(i, delta) + delta;
+        return (int)AA.addAndGet(array, i, delta);
     }
 
     /**
@@ -260,13 +248,14 @@
      * @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;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -281,23 +270,25 @@
      * @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;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -307,23 +298,25 @@
      */
     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;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -333,13 +326,14 @@
      */
     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;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -354,11 +348,190 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain(int i) {
+        return (int)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, int newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque(int i) {
+        return (int)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, int newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire(int i) {
+        return (int)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, int newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Fri Jul 15 14:04:09 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -150,8 +151,8 @@
     public abstract void lazySet(T obj, int newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -367,7 +368,7 @@
      */
     private static final class AtomicIntegerFieldUpdaterImpl<T>
         extends AtomicIntegerFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,31 +35,30 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicLong} is used in applications such as atomically
- * incremented sequence numbers, and cannot be used as a replacement
- * for a {@link java.lang.Long}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicLong} is used in applications
+ * such as atomically incremented sequence numbers, and cannot be used
+ * as a replacement for a {@link java.lang.Long}. However, this class
+ * does extend {@code Number} to allow uniform access by tools and
+ * utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    private static final VarHandle VALUE;
 
     /**
      * Records whether the underlying JVM supports lockless
-     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
+     * compareAndSwap for longs. While the intrinsic compareAndSwapLong
      * method works in either case, some constructions should be
      * handled at Java level to avoid locking user-visible locks.
      */
@@ -73,8 +72,8 @@
 
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicLong.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicLong.class, "value", long.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -98,7 +97,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -107,119 +107,132 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @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.setVolatile(this, newValue);
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putLongRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        return U.getAndSetLong(this, VALUE, newValue);
+        return (long)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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);
+    public final boolean compareAndSet(long expectedValue, long newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+    public final boolean weakCompareAndSet(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final long getAndIncrement() {
-        return U.getAndAddLong(this, VALUE, 1L);
+        return (long)VALUE.getAndAdd(this, 1L);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final long getAndDecrement() {
-        return U.getAndAddLong(this, VALUE, -1L);
+        return (long)VALUE.getAndAdd(this, -1L);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        return U.getAndAddLong(this, VALUE, delta);
+        return (long)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final long incrementAndGet() {
-        return U.getAndAddLong(this, VALUE, 1L) + 1L;
+        return (long)VALUE.addAndGet(this, 1L);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final long decrementAndGet() {
-        return U.getAndAddLong(this, VALUE, -1L) - 1L;
+        return (long)VALUE.addAndGet(this, -1L);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        return U.getAndAddLong(this, VALUE, delta) + delta;
+        return (long)VALUE.addAndGet(this, delta);
     }
 
     /**
@@ -233,12 +246,14 @@
      * @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;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -252,12 +267,14 @@
      * @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;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -276,12 +293,14 @@
      */
     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;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -300,12 +319,14 @@
      */
     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;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -317,8 +338,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as an {@code int}
-     * after a narrowing primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as an {@code int}
+     * after a narrowing primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public int intValue() {
@@ -326,7 +348,8 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code long}.
+     * Returns the current value of this {@code AtomicLong} as a {@code long},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * Equivalent to {@link #get()}.
      */
     public long longValue() {
@@ -334,8 +357,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code float}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -343,12 +367,175 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code double}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as if the
+     * variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain() {
+        return (long)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(long newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque() {
+        return (long)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(long newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire() {
+        return (long)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(long newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,43 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package specification
- * for description of the properties of atomic variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(long[].class);
     private final long[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(long[].class);
-        int scale = U.arrayIndexScale(long[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicLongArray of the given length, with all
      * elements initially zero.
@@ -104,147 +85,155 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final long get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private long getRaw(long offset) {
-        return U.getLongVolatile(array, offset);
+        return (long)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, long newValue) {
-        U.putLongVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putLongRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given value
-     * and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(int i, long newValue) {
-        return U.getAndSetLong(array, checkedByteOffset(i), newValue);
+        return (long)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, long expect, long update) {
-        return U.compareAndSwapLong(array, offset, expect, update);
+    public final boolean compareAndSet(int i, long expectedValue, long newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, long expect, long update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (long)AA.getAndAdd(array, i, 1L);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (long)AA.getAndAdd(array, i, -1L);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
-        return U.getAndAddLong(array, checkedByteOffset(i), delta);
+        return (long)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (long)AA.addAndGet(array, i, 1L);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (long)AA.addAndGet(array, i, -1L);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public long addAndGet(int i, long delta) {
-        return getAndAdd(i, delta) + delta;
+        return (long)AA.addAndGet(array, i, delta);
     }
 
     /**
@@ -259,13 +248,14 @@
      * @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;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -280,23 +270,25 @@
      * @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;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -306,23 +298,25 @@
      */
     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;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -332,13 +326,14 @@
      */
     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;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -353,11 +348,189 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain(int i) {
+        return (long)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, long newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque(int i) {
+        return (long)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, long newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire(int i) {
+        return (long)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, long newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Fri Jul 15 14:04:09 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -153,8 +154,8 @@
     public abstract void lazySet(T obj, long newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -366,7 +367,7 @@
     }
 
     private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -497,7 +498,7 @@
     }
 
     private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicMarkableReference} maintains an object reference
  * along with a mark bit, that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newMark)));
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicMarkableReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicMarkableReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,33 +35,32 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
- * An object reference that may be updated atomically. See the {@link
- * java.util.concurrent.atomic} package specification for description
- * of the properties of atomic variables.
+ * An object reference that may be updated atomically.  See the {@link
+ * VarHandle} specification for descriptions of the properties of
+ * atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <V> The type of object referred to by this reference
  */
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicReference.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
-    private volatile V value;
+    private volatile Object value;
 
     /**
      * Creates a new AtomicReference with the given initial value.
@@ -79,16 +78,19 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
+    @SuppressWarnings("unchecked")
     public final V get() {
-        return value;
+        return (V)value;
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -97,52 +99,53 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putObjectRelease(this, VALUE, newValue);
-    }
-
-    /**
-     * Atomically sets the value to the given updated value
-     * 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
-     * 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);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
-     * @return {@code true} if successful
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful. False return indicates that
+     * the actual value was not equal to the expected value.
      */
-    public final boolean weakCompareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+    public final boolean compareAndSet(V expectedValue, V newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     */
+    public final boolean weakCompareAndSet(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     @SuppressWarnings("unchecked")
     public final V getAndSet(V newValue) {
-        return (V)U.getAndSetObject(this, VALUE, newValue);
+        return (V)VALUE.getAndSet(this, newValue);
     }
 
     /**
@@ -156,12 +159,14 @@
      * @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;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -175,12 +180,14 @@
      * @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;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -199,12 +206,14 @@
      */
     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;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -223,12 +232,14 @@
      */
     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;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -239,4 +250,166 @@
         return String.valueOf(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getPlain() {
+        return (V)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(V newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getOpaque() {
+        return (V)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(V newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getAcquire() {
+        return (V)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(V newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchange(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeAcquire(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeRelease(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,54 +35,28 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.lang.reflect.Array;
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
  * An array of object references in which elements may be updated
- * atomically.  See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * atomically.  See the {@link VarHandle} specification for
+ * descriptions of the properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <E> The base class of elements held in this array
  */
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long ARRAY;
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(Object[].class);
     private final Object[] array; // must have exact type Object[]
 
-    static {
-        try {
-            ARRAY = U.objectFieldOffset
-                (AtomicReferenceArray.class.getDeclaredField("array"));
-            ABASE = U.arrayBaseOffset(Object[].class);
-            int scale = U.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(e);
-        }
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicReferenceArray of the given length, with all
      * elements initially null.
@@ -115,44 +89,44 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
+    @SuppressWarnings("unchecked")
     public final E get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    @SuppressWarnings("unchecked")
-    private E getRaw(long offset) {
-        return (E) U.getObjectVolatile(array, offset);
+        return (E)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, E newValue) {
-        U.putObjectVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putObjectRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
@@ -160,42 +134,36 @@
      */
     @SuppressWarnings("unchecked")
     public final E getAndSet(int i, E newValue) {
-        return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
+        return (E)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code 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) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, E expect, E update) {
-        return U.compareAndSwapObject(array, offset, expect, update);
+    public final boolean compareAndSet(int i, E expectedValue, E newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, E expect, E update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
@@ -210,13 +178,14 @@
      * @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;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -231,23 +200,25 @@
      * @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;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -257,23 +228,25 @@
      */
     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;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * 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
+     * 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.
+     * applied with the current value of the element 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
@@ -283,13 +256,14 @@
      */
     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;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -304,7 +278,7 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
@@ -326,7 +300,199 @@
             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);
+        Field arrayField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = AtomicReferenceArray.class
+                        .getDeclaredField("array");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
+        try {
+            arrayField.set(this, a);
+        } catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+    }
+
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getPlain(int i) {
+        return (E)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, E newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getOpaque(int i) {
+        return (E)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, E newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getAcquire(int i) {
+        return (E)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, E newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchange(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeAcquire(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeRelease(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Fri Jul 15 14:04:09 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -168,8 +169,8 @@
     public abstract void lazySet(T obj, V newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -284,7 +285,7 @@
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicStampedReference} maintains an object reference
  * along with an integer "stamp", that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newStamp)));
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicStampedReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicStampedReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java	Fri Jul 15 14:04:09 2016 -0700
@@ -68,7 +68,7 @@
  * <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}.
+ * 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
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,10 +35,13 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.function.DoubleBinaryOperator;
 import java.util.function.LongBinaryOperator;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A package-local class holding common representation and mechanics
@@ -123,22 +126,21 @@
         volatile long value;
         Cell(long x) { value = x; }
         final boolean cas(long cmp, long val) {
-            return U.compareAndSwapLong(this, VALUE, cmp, val);
+            return VALUE.compareAndSet(this, cmp, val);
         }
         final void reset() {
-            U.putLongVolatile(this, VALUE, 0L);
+            VALUE.setVolatile(this, 0L);
         }
         final void reset(long identity) {
-            U.putLongVolatile(this, VALUE, identity);
+            VALUE.setVolatile(this, identity);
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
+        // VarHandle mechanics
+        private static final VarHandle VALUE;
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Cell.class.getDeclaredField("value"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                VALUE = l.findVarHandle(Cell.class, "value", long.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -174,14 +176,14 @@
      * CASes the base field.
      */
     final boolean casBase(long cmp, long val) {
-        return U.compareAndSwapLong(this, BASE, cmp, val);
+        return BASE.compareAndSet(this, cmp, val);
     }
 
     /**
      * CASes the cellsBusy field from 0 to 1 to acquire lock.
      */
     final boolean casCellsBusy() {
-        return U.compareAndSwapInt(this, CELLSBUSY, 0, 1);
+        return CELLSBUSY.compareAndSet(this, 0, 1);
     }
 
     /**
@@ -371,18 +373,16 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long BASE;
-    private static final long CELLSBUSY;
+    // Unsafe and VarHandle mechanics
+    private static final Unsafe U = Unsafe.getUnsafe();
+    private static final VarHandle BASE;
+    private static final VarHandle CELLSBUSY;
     private static final long PROBE;
     static {
         try {
-            BASE = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("base"));
-            CELLSBUSY = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("cellsBusy"));
-
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BASE = l.findVarHandle(Striped64.class, "base", long.class);
+            CELLSBUSY = l.findVarHandle(Striped64.class, "cellsBusy", int.class);
             PROBE = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomProbe"));
         } catch (ReflectiveOperationException e) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,26 +35,10 @@
 
 /**
  * A small toolkit of classes that support lock-free thread-safe
- * programming on single variables.  In essence, the classes in this
- * package extend the notion of {@code volatile} values, fields, and
- * array elements to those that also provide an atomic conditional update
- * operation of the form:
- *
- * <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
- * currently holds the {@code expectedValue}, reporting {@code true} on
- * success.  The classes in this package also contain methods to get and
- * unconditionally set values, as well as a weaker conditional atomic
- * update operation {@code weakCompareAndSet} described below.
- *
- * <p>The specifications of these methods enable implementations to
- * employ efficient machine-level atomic instructions that are available
- * on contemporary processors.  However on some platforms, support may
- * entail some form of internal locking.  Thus the methods are not
- * strictly guaranteed to be non-blocking --
- * a thread may block transiently before performing the operation.
+ * programming on single variables.  Instances of Atomic classes
+ * maintain values that are accessed and updated using methods
+ * otherwise available for fields using associated atomic {@link
+ * java.lang.invoke.VarHandle} operations.
  *
  * <p>Instances of classes
  * {@link java.util.concurrent.atomic.AtomicBoolean},
@@ -92,45 +76,26 @@
  *   return prev; // 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>:
- *
- * <ul>
- *
- *   <li>{@code get} has the memory effects of reading a
- * {@code volatile} variable.
- *
- *   <li>{@code set} has the memory effects of writing (assigning) a
- * {@code volatile} variable.
+ * <p>These classes are not general purpose replacements for {@code
+ * java.lang.Integer} and related classes.  They do <em>not</em>
+ * define methods such as {@code equals}, {@code hashCode} and {@code
+ * compareTo}.  Because atomic variables are expected to be mutated,
+ * they are poor choices for hash table keys.
  *
- *   <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}
- *   writes.  Among other usage contexts, {@code lazySet} may apply when
- *   nulling out, for the sake of garbage collection, a reference that is
- *   never accessed again.
+ * <p>The
+ * {@link java.util.concurrent.atomic.AtomicIntegerArray},
+ * {@link java.util.concurrent.atomic.AtomicLongArray}, and
+ * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
+ * further extend atomic operation support to arrays of these types.
+ * These classes are also notable in providing {@code volatile} access
+ * semantics for their array elements.
  *
- *   <li>{@code weakCompareAndSet} atomically reads and conditionally
- *   writes a variable but does <em>not</em>
- *   create any happens-before orderings, so provides no guarantees
- *   with respect to previous or subsequent reads and writes of any
- *   variables other than the target of the {@code weakCompareAndSet}.
- *
- *   <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.
- * </ul>
- *
- * <p>In addition to classes representing single values, this package
- * contains <em>Updater</em> classes that can be used to obtain
- * {@code compareAndSet} operations on any selected {@code volatile}
- * field of any selected class.
- *
+ * <p>In addition to classes representing single values and arrays,
+ * this package contains <em>Updater</em> classes that can be used to
+ * obtain {@code compareAndSet} and related operations on any selected
+ * {@code volatile} field of any selected class. These classes
+ * predate the introduction of {@link
+ * java.lang.invoke.VarHandle}, and are of more limited use.
  * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
  * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
  * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
@@ -143,38 +108,6 @@
  * reflection-based setup, less convenient usage, and weaker
  * guarantees.
  *
- * <p>The
- * {@link java.util.concurrent.atomic.AtomicIntegerArray},
- * {@link java.util.concurrent.atomic.AtomicLongArray}, and
- * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
- * further extend atomic operation support to arrays of these types.
- * These classes are also notable in providing {@code volatile} access
- * semantics for their array elements, which is not supported for
- * ordinary arrays.
- *
- * <p id="weakCompareAndSet">The atomic classes also support method
- * {@code weakCompareAndSet}, which has limited applicability.  On some
- * platforms, the weak version may be more efficient than {@code
- * compareAndSet} in the normal case, but differs in that any given
- * invocation of the {@code weakCompareAndSet} method may return {@code
- * false} <em>spuriously</em> (that is, for no apparent reason).  A
- * {@code false} return means only that the operation may be retried if
- * desired, relying on the guarantee that repeated invocation when the
- * variable holds {@code expectedValue} and no other thread is also
- * attempting to set the variable will eventually succeed.  (Such
- * spurious failures may for example be due to memory contention effects
- * that are unrelated to whether the expected and current values are
- * equal.)  Additionally {@code weakCompareAndSet} does not provide
- * ordering guarantees that are usually needed for synchronization
- * control.  However, the method may be useful for updating counters and
- * statistics when such updates are unrelated to the other
- * happens-before orderings of a program.  When a thread sees an update
- * to an atomic variable caused by a {@code weakCompareAndSet}, it does
- * not necessarily see updates to any <em>other</em> variables that
- * occurred before the {@code weakCompareAndSet}.  This may be
- * acceptable when, for example, updating performance statistics, but
- * rarely otherwise.
- *
  * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
  * class associates a single boolean with a reference.  For example, this
  * bit might be used inside a data structure to mean that the object
@@ -185,29 +118,6 @@
  * used for example, to represent version numbers corresponding to
  * series of updates.
  *
- * <p>Atomic classes are designed primarily as building blocks for
- * implementing non-blocking data structures and related infrastructure
- * classes.  The {@code compareAndSet} method is not a general
- * replacement for locking.  It applies only when critical updates for an
- * object are confined to a <em>single</em> variable.
- *
- * <p>Atomic classes are not general purpose replacements for
- * {@code java.lang.Integer} and related classes.  They do <em>not</em>
- * define methods such as {@code equals}, {@code hashCode} and
- * {@code compareTo}.  (Because atomic variables are expected to be
- * mutated, they are poor choices for hash table keys.)  Additionally,
- * classes are provided only for those types that are commonly useful in
- * intended applications.  For example, there is no atomic class for
- * representing {@code byte}.  In those infrequent cases where you would
- * like to do so, you can use an {@code AtomicInteger} to hold
- * {@code byte} values, and cast appropriately.
- *
- * You can also hold floats using
- * {@link java.lang.Float#floatToRawIntBits} and
- * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
- * {@link java.lang.Double#doubleToRawLongBits} and
- * {@link java.lang.Double#longBitsToDouble} conversions.
- *
  * @since 1.5
  */
 package java.util.concurrent.atomic;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -113,7 +115,7 @@
     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.setVolatile(this, newState);
     }
 
     /**
@@ -128,7 +130,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(long expect, long update) {
-        return U.compareAndSwapLong(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -149,7 +151,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -172,7 +174,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -1810,28 +1812,17 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicLong, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "state", long.class);
+            HEAD = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -1846,7 +1837,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -1854,6 +1845,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,11 +35,12 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
-import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * Provides a framework for implementing blocking locks and related
@@ -506,40 +507,41 @@
         /** Constructor used by addWaiter. */
         Node(Node nextWaiter) {
             this.nextWaiter = nextWaiter;
-            U.putObject(this, THREAD, Thread.currentThread());
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** Constructor used by addConditionWaiter. */
         Node(int waitStatus) {
-            U.putInt(this, WAITSTATUS, waitStatus);
-            U.putObject(this, THREAD, Thread.currentThread());
+            WAITSTATUS.set(this, waitStatus);
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** CASes waitStatus field. */
         final boolean compareAndSetWaitStatus(int expect, int update) {
-            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
+            return WAITSTATUS.compareAndSet(this, expect, update);
         }
 
         /** CASes next field. */
         final boolean compareAndSetNext(Node expect, Node update) {
-            return U.compareAndSwapObject(this, NEXT, expect, update);
+            return NEXT.compareAndSet(this, expect, update);
+        }
+
+        final void setPrevRelaxed(Node p) {
+            PREV.set(this, p);
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long NEXT;
-        static final long PREV;
-        private static final long THREAD;
-        private static final long WAITSTATUS;
+        // VarHandle mechanics
+        private static final VarHandle NEXT;
+        private static final VarHandle PREV;
+        private static final VarHandle THREAD;
+        private static final VarHandle 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"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
+                PREV = l.findVarHandle(Node.class, "prev", Node.class);
+                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
+                WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -595,7 +597,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
-        return U.compareAndSwapInt(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -616,7 +618,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -639,7 +641,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -887,7 +889,6 @@
      * @param arg the acquire argument
      * @return {@code true} if interrupted while waiting
      */
-    @ReservedStackAccess
     final boolean acquireQueued(final Node node, int arg) {
         try {
             boolean interrupted = false;
@@ -1220,7 +1221,6 @@
      *        {@link #tryAcquire} but is otherwise uninterpreted and
      *        can represent anything you like.
      */
-    @ReservedStackAccess
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1284,7 +1284,6 @@
      *        can represent anything you like.
      * @return the value returned from {@link #tryRelease}
      */
-    @ReservedStackAccess
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
@@ -1365,7 +1364,6 @@
      *        and can represent anything you like.
      * @return the value returned from {@link #tryReleaseShared}
      */
-    @ReservedStackAccess
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
             doReleaseShared();
@@ -2279,28 +2277,17 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicInteger, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedSynchronizer.class, "state", int.class);
+            HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -2315,7 +2302,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -2323,6 +2310,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri Jul 15 14:04:09 2016 -0700
@@ -396,7 +396,6 @@
      * re-acquire the lock associated with this condition. When the
      * thread returns it is <em>guaranteed</em> to hold this lock.
      *
-     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
@@ -408,7 +407,6 @@
      * case, whether or not the test for interruption occurs before the lock
      * is released.
      *
-     *
      * <p>The return value indicates whether the deadline has elapsed,
      * which can be used as follows:
      * <pre> {@code
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Fri Jul 15 14:04:09 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import jdk.internal.misc.Unsafe;
+
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
@@ -405,16 +407,30 @@
         return 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);
+    }
+
     // Hotspot implementation via intrinsics API
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long PARKBLOCKER;
     private static final long SECONDARY;
+    private static final long TID;
     static {
         try {
             PARKBLOCKER = U.objectFieldOffset
                 (Thread.class.getDeclaredField("parkBlocker"));
             SECONDARY = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+            TID = U.objectFieldOffset
+                (Thread.class.getDeclaredField("tid"));
+
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Fri Jul 15 14:04:09 2016 -0700
@@ -79,7 +79,6 @@
  * and measurement will establish whether the use of a read-write lock is
  * suitable for your application.
  *
- *
  * <p>Although the basic operation of a read-write lock is straight-forward,
  * there are many policy decisions that an implementation must make, which
  * may affect the effectiveness of the read-write lock in a given application.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Fri Jul 15 14:04:09 2016 -0700
@@ -119,12 +119,6 @@
         private static final long serialVersionUID = -5179523762034025860L;
 
         /**
-         * Performs {@link Lock#lock}. The main reason for subclassing
-         * is to allow fast path for nonfair version.
-         */
-        abstract void lock();
-
-        /**
          * Performs non-fair tryLock.  tryAcquire is implemented in
          * subclasses, but both need nonfair try for trylock method.
          */
@@ -201,19 +195,6 @@
      */
     static final class NonfairSync extends Sync {
         private static final long serialVersionUID = 7316153563782823691L;
-
-        /**
-         * Performs lock.  Try immediate barge, backing up to normal
-         * acquire on failure.
-         */
-        @ReservedStackAccess
-        final void lock() {
-            if (compareAndSetState(0, 1))
-                setExclusiveOwnerThread(Thread.currentThread());
-            else
-                acquire(1);
-        }
-
         protected final boolean tryAcquire(int acquires) {
             return nonfairTryAcquire(acquires);
         }
@@ -224,11 +205,6 @@
      */
     static final class FairSync extends Sync {
         private static final long serialVersionUID = -3000897897090466540L;
-
-        final void lock() {
-            acquire(1);
-        }
-
         /**
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
@@ -288,7 +264,7 @@
      * at which time the lock hold count is set to one.
      */
     public void lock() {
-        sync.lock();
+        sync.acquire(1);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri Jul 15 14:04:09 2016 -0700
@@ -37,6 +37,7 @@
 
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * An implementation of {@link ReadWriteLock} supporting similar
@@ -278,7 +279,7 @@
         static final class HoldCounter {
             int count;          // initially 0
             // Use id, not reference, to avoid garbage retention
-            final long tid = getThreadId(Thread.currentThread());
+            final long tid = LockSupport.getThreadId(Thread.currentThread());
         }
 
         /**
@@ -367,7 +368,7 @@
          * both read and write holds that are all released during a
          * condition wait and re-established in tryAcquire.
          */
-
+        @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
@@ -379,6 +380,7 @@
             return free;
         }
 
+        @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             /*
              * Walkthrough:
@@ -411,6 +413,7 @@
             return true;
         }
 
+        @ReservedStackAccess
         protected final boolean tryReleaseShared(int unused) {
             Thread current = Thread.currentThread();
             if (firstReader == current) {
@@ -421,7 +424,8 @@
                     firstReaderHoldCount--;
             } else {
                 HoldCounter rh = cachedHoldCounter;
-                if (rh == null || rh.tid != getThreadId(current))
+                if (rh == null ||
+                    rh.tid != LockSupport.getThreadId(current))
                     rh = readHolds.get();
                 int count = rh.count;
                 if (count <= 1) {
@@ -447,6 +451,7 @@
                 "attempt to unlock read lock, not locked by current thread");
         }
 
+        @ReservedStackAccess
         protected final int tryAcquireShared(int unused) {
             /*
              * Walkthrough:
@@ -479,7 +484,8 @@
                     firstReaderHoldCount++;
                 } else {
                     HoldCounter rh = cachedHoldCounter;
-                    if (rh == null || rh.tid != getThreadId(current))
+                    if (rh == null ||
+                        rh.tid != LockSupport.getThreadId(current))
                         cachedHoldCounter = rh = readHolds.get();
                     else if (rh.count == 0)
                         readHolds.set(rh);
@@ -516,7 +522,8 @@
                     } else {
                         if (rh == null) {
                             rh = cachedHoldCounter;
-                            if (rh == null || rh.tid != getThreadId(current)) {
+                            if (rh == null ||
+                                rh.tid != LockSupport.getThreadId(current)) {
                                 rh = readHolds.get();
                                 if (rh.count == 0)
                                     readHolds.remove();
@@ -537,7 +544,8 @@
                     } else {
                         if (rh == null)
                             rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -554,6 +562,7 @@
          * This is identical in effect to tryAcquire except for lack
          * of calls to writerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryWriteLock() {
             Thread current = Thread.currentThread();
             int c = getState();
@@ -575,6 +584,7 @@
          * This is identical in effect to tryAcquireShared except for
          * lack of calls to readerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryReadLock() {
             Thread current = Thread.currentThread();
             for (;;) {
@@ -593,7 +603,8 @@
                         firstReaderHoldCount++;
                     } else {
                         HoldCounter rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             cachedHoldCounter = rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -644,7 +655,7 @@
                 return firstReaderHoldCount;
 
             HoldCounter rh = cachedHoldCounter;
-            if (rh != null && rh.tid == getThreadId(current))
+            if (rh != null && rh.tid == LockSupport.getThreadId(current))
                 return rh.count;
 
             int count = readHolds.get().count;
@@ -1490,26 +1501,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 jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long TID;
-    static {
-        try {
-            TID = U.objectFieldOffset
-                (Thread.class.getDeclaredField("tid"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Fri Jul 15 14:04:09 2016 -0700
@@ -262,7 +262,6 @@
  *
  * </ul>
  *
- *
  * The methods of all classes in {@code java.util.concurrent} and its
  * subpackages extend these guarantees to higher-level
  * synchronization.  In particular:
--- a/jdk/test/java/util/concurrent/tck/Atomic8Test.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/Atomic8Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -179,7 +179,7 @@
      * result of supplied function
      */
     public void testReferenceGetAndUpdate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17));
         assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.get());
@@ -190,7 +190,7 @@
      * returns result.
      */
     public void testReferenceUpdateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.get());
@@ -201,7 +201,7 @@
      * with supplied function.
      */
     public void testReferenceGetAndAccumulate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(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());
@@ -212,7 +212,7 @@
      * returns result.
      */
     public void testReferenceAccumulateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(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());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicBoolean9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicBoolean9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getPlain());
+        ai.set(false);
+        assertEquals(false, ai.getPlain());
+        ai.set(true);
+        assertEquals(true, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getOpaque());
+        ai.set(false);
+        assertEquals(false, ai.getOpaque());
+        ai.set(true);
+        assertEquals(true, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getAcquire());
+        ai.set(false);
+        assertEquals(false, ai.getAcquire());
+        ai.set(true);
+        assertEquals(true, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setPlain(false);
+        assertEquals(false, ai.get());
+        ai.setPlain(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setOpaque(false);
+        assertEquals(false, ai.get());
+        ai.setOpaque(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setRelease(false);
+        assertEquals(false, ai.get());
+        ai.setRelease(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchange(true, false));
+        assertEquals(false, ai.compareAndExchange(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchange(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchange(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchangeAcquire(true, false));
+        assertEquals(false, ai.compareAndExchangeAcquire(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeAcquire(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeAcquire(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchangeRelease(true, false));
+        assertEquals(false, ai.compareAndExchangeRelease(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeRelease(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeRelease(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetVolatile(true, false));
+        do {} while (!ai.weakCompareAndSetVolatile(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetAcquire(true, false));
+        do {} while (!ai.weakCompareAndSetAcquire(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetRelease(true, false));
+        do {} while (!ai.weakCompareAndSetRelease(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(false, true));
+        assertEquals(true, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicInteger9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicInteger9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getPlain());
+        ai.set(2);
+        assertEquals(2, ai.getPlain());
+        ai.set(-3);
+        assertEquals(-3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getOpaque());
+        ai.set(2);
+        assertEquals(2, ai.getOpaque());
+        ai.set(-3);
+        assertEquals(-3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAcquire());
+        ai.set(2);
+        assertEquals(2, ai.getAcquire());
+        ai.set(-3);
+        assertEquals(-3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setPlain(2);
+        assertEquals(2, ai.get());
+        ai.setPlain(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setOpaque(2);
+        assertEquals(2, ai.get());
+        ai.setOpaque(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setRelease(2);
+        assertEquals(2, ai.get());
+        ai.setRelease(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchange(1, 2));
+        assertEquals(2, ai.compareAndExchange(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchangeAcquire(1, 2));
+        assertEquals(2, ai.compareAndExchangeAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchangeRelease(1, 2));
+        assertEquals(2, ai.compareAndExchangeRelease(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetVolatile(1, 2));
+        do {} while (!ai.weakCompareAndSetVolatile(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetAcquire(1, 2));
+        do {} while (!ai.weakCompareAndSetAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetRelease(1, 2));
+        do {} while (!ai.weakCompareAndSetRelease(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,267 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicIntegerArray9Test extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicIntegerArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, 1),
+                () -> aa.setOpaque(j, 1),
+                () -> aa.setRelease(j, 1),
+                () -> aa.compareAndExchange(j, 1, 2),
+                () -> aa.compareAndExchangeAcquire(j, 1, 2),
+                () -> aa.compareAndExchangeRelease(j, 1, 2),
+                () -> aa.weakCompareAndSetVolatile(j, 1, 2),
+                () -> aa.weakCompareAndSetAcquire(j, 1, 2),
+                () -> aa.weakCompareAndSetRelease(j, 1, 2),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getPlain(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getPlain(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getOpaque(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getOpaque(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAcquire(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getAcquire(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setPlain(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setPlain(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setOpaque(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setOpaque(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setRelease(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setRelease(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchange(i, 1, 2));
+            assertEquals(2, aa.compareAndExchange(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeAcquire(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeRelease(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetVolatile(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetVolatile(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetAcquire(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetRelease(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLong9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLong9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getPlain());
+        ai.set(2);
+        assertEquals(2, ai.getPlain());
+        ai.set(-3);
+        assertEquals(-3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getOpaque());
+        ai.set(2);
+        assertEquals(2, ai.getOpaque());
+        ai.set(-3);
+        assertEquals(-3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAcquire());
+        ai.set(2);
+        assertEquals(2, ai.getAcquire());
+        ai.set(-3);
+        assertEquals(-3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setPlain(2);
+        assertEquals(2, ai.get());
+        ai.setPlain(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setOpaque(2);
+        assertEquals(2, ai.get());
+        ai.setOpaque(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setRelease(2);
+        assertEquals(2, ai.get());
+        ai.setRelease(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchange(1, 2));
+        assertEquals(2, ai.compareAndExchange(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchangeAcquire(1, 2));
+        assertEquals(2, ai.compareAndExchangeAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchangeRelease(1, 2));
+        assertEquals(2, ai.compareAndExchangeRelease(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetVolatile(1, 2));
+        do {} while (!ai.weakCompareAndSetVolatile(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetAcquire(1, 2));
+        do {} while (!ai.weakCompareAndSetAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetRelease(1, 2));
+        do {} while (!ai.weakCompareAndSetRelease(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,266 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLongArray9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLongArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, 1),
+                () -> aa.setOpaque(j, 1),
+                () -> aa.setRelease(j, 1),
+                () -> aa.compareAndExchange(j, 1, 2),
+                () -> aa.compareAndExchangeAcquire(j, 1, 2),
+                () -> aa.compareAndExchangeRelease(j, 1, 2),
+                () -> aa.weakCompareAndSetVolatile(j, 1, 2),
+                () -> aa.weakCompareAndSetAcquire(j, 1, 2),
+                () -> aa.weakCompareAndSetRelease(j, 1, 2),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getPlain(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getPlain(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getOpaque(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getOpaque(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAcquire(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getAcquire(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setPlain(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setPlain(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setOpaque(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setOpaque(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setRelease(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setRelease(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchange(i, 1, 2));
+            assertEquals(2, aa.compareAndExchange(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeAcquire(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeRelease(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetVolatile(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetVolatile(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetAcquire(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetRelease(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicReference9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicReference9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getPlain());
+        ai.set(two);
+        assertEquals(two, ai.getPlain());
+        ai.set(m3);
+        assertEquals(m3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getOpaque());
+        ai.set(two);
+        assertEquals(two, ai.getOpaque());
+        ai.set(m3);
+        assertEquals(m3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getAcquire());
+        ai.set(two);
+        assertEquals(two, ai.getAcquire());
+        ai.set(m3);
+        assertEquals(m3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setPlain(two);
+        assertEquals(two, ai.get());
+        ai.setPlain(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setOpaque(two);
+        assertEquals(two, ai.get());
+        ai.setOpaque(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setRelease(two);
+        assertEquals(two, ai.get());
+        ai.setRelease(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchange(one, two));
+        assertEquals(two, ai.compareAndExchange(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchange(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchange(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchangeAcquire(one, two));
+        assertEquals(two, ai.compareAndExchangeAcquire(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeAcquire(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeAcquire(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchangeRelease(one, two));
+        assertEquals(two, ai.compareAndExchangeRelease(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeRelease(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeRelease(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetVolatile(one, two));
+        do {} while (!ai.weakCompareAndSetVolatile(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetAcquire(one, two));
+        do {} while (!ai.weakCompareAndSetAcquire(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetRelease(one, two));
+        do {} while (!ai.weakCompareAndSetRelease(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java	Fri Jul 15 14:04:09 2016 -0700
@@ -0,0 +1,266 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicReferenceArray9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicReferenceArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, null),
+                () -> aa.setOpaque(j, null),
+                () -> aa.setRelease(j, null),
+                () -> aa.compareAndExchange(j, null, null),
+                () -> aa.compareAndExchangeAcquire(j, null, null),
+                () -> aa.compareAndExchangeRelease(j, null, null),
+                () -> aa.weakCompareAndSetVolatile(j, null, null),
+                () -> aa.weakCompareAndSetAcquire(j, null, null),
+                () -> aa.weakCompareAndSetRelease(j, null, null),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getPlain(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getPlain(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getOpaque(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getOpaque(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getAcquire(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getAcquire(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setPlain(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setPlain(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setOpaque(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setOpaque(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setRelease(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setRelease(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchange(i, one, two));
+            assertEquals(two, aa.compareAndExchange(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchange(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchange(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchangeAcquire(i, one, two));
+            assertEquals(two, aa.compareAndExchangeAcquire(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeAcquire(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeAcquire(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchangeRelease(i, one, two));
+            assertEquals(two, aa.compareAndExchangeRelease(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeRelease(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeRelease(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetVolatile(i, one, two));
+            do {} while (!aa.weakCompareAndSetVolatile(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetAcquire(i, one, two));
+            do {} while (!aa.weakCompareAndSetAcquire(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetRelease(i, one, two));
+            do {} while (!aa.weakCompareAndSetRelease(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+}
--- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java	Fri Jul 15 14:04:09 2016 -0700
@@ -243,4 +243,5 @@
         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
         assertEquals(Arrays.toString(a), aa.toString());
     }
+
 }
--- a/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java	Fri Jul 15 14:04:09 2016 -0700
@@ -161,7 +161,7 @@
      * toString returns current value.
      */
     public void testToString() {
-        AtomicReference<Integer> ai = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
         assertEquals(one.toString(), ai.toString());
         ai.set(two);
         assertEquals(two.toString(), ai.toString());
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Fri Jul 15 13:59:58 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Fri Jul 15 14:04:09 2016 -0700
@@ -548,6 +548,13 @@
         // Java9+ test classes
         if (atLeastJava9()) {
             String[] java9TestClassNames = {
+                "AtomicBoolean9Test",
+                "AtomicInteger9Test",
+                "AtomicIntegerArray9Test",
+                "AtomicLong9Test",
+                "AtomicLongArray9Test",
+                "AtomicReference9Test",
+                "AtomicReferenceArray9Test",
                 "ExecutorCompletionService9Test",
             };
             addNamedTestClasses(suite, java9TestClassNames);
@@ -975,7 +982,11 @@
         }
     }
 
-    /** Like Runnable, but with the freedom to throw anything */
+    /**
+     * Like Runnable, but with the freedom to throw anything.
+     * junit folks had the same idea:
+     * http://junit.org/junit5/docs/snapshot/api/org/junit/gen5/api/Executable.html
+     */
     interface Action { public void run() throws Throwable; }
 
     /**
@@ -1006,6 +1017,15 @@
      * Uninteresting threads are filtered out.
      */
     static void dumpTestThreads() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                System.setSecurityManager(null);
+            } catch (SecurityException giveUp) {
+                return;
+            }
+        }
+
         ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
         System.err.println("------ stacktrace dump start ------");
         for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
@@ -1023,6 +1043,8 @@
             System.err.print(info);
         }
         System.err.println("------ stacktrace dump end ------");
+
+        if (sm != null) System.setSecurityManager(sm);
     }
 
     /**