changeset 14242:b37554a7984d

Merge
author ddehaven
date Mon, 11 Apr 2016 11:19:33 -0700
parents 061cb940b183 (current diff) bb8379287f37 (diff)
children 2ad92ad4e9a9
files src/java.base/share/classes/java/lang/reflect/WeakCache.java src/java.base/share/classes/sun/misc/CRC16.java src/java.base/share/classes/sun/misc/Cache.java src/java.base/share/classes/sun/misc/ManagedLocalsThread.java src/java.base/share/classes/sun/misc/Signal.java src/java.base/share/classes/sun/misc/SignalHandler.java src/java.base/share/classes/sun/misc/SoftCache.java src/java.base/share/classes/sun/misc/Unsafe.java src/java.base/share/classes/sun/net/spi/nameservice/NameService.java src/java.base/share/classes/sun/net/spi/nameservice/NameServiceDescriptor.java src/java.base/unix/classes/sun/misc/GThreadHelper.java src/jdk.naming.dns/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java src/jdk.naming.dns/share/classes/sun/net/spi/nameservice/dns/DNSNameServiceDescriptor.java test/java/net/Inet4Address/DummyNameService.java test/java/net/Inet4Address/DummyNameServiceDescriptor.java test/java/net/Inet4Address/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/java/net/URLPermission/nstest/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/java/net/URLPermission/nstest/SimpleNameService.java test/java/net/URLPermission/nstest/SimpleNameServiceDescriptor.java test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/sun/net/InetAddress/nameservice/chaining/Providers.java test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java test/sun/net/InetAddress/nameservice/deadlock/Hang.java test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/sun/security/krb5/canonicalize/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor test/sun/security/x509/URICertStore/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
diffstat 300 files changed, 44693 insertions(+), 5572 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Apr 11 21:07:34 2016 +0300
+++ b/.hgtags	Mon Apr 11 11:19:33 2016 -0700
@@ -355,3 +355,4 @@
 9417e1bcded6af5532c3b26235437ab227758877 jdk-9+110
 b2a69d66dc65ad1d3aeb3bd362cf5bb0deba040e jdk-9+111
 1565a0efe6f0ca411a6df277df1e069431c60988 jdk-9+112
+68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113
--- a/make/gensrc/Gensrc-java.base.gmk	Mon Apr 11 21:07:34 2016 +0300
+++ b/make/gensrc/Gensrc-java.base.gmk	Mon Apr 11 11:19:33 2016 -0700
@@ -33,6 +33,7 @@
 include GensrcCharsetCoder.gmk
 include GensrcBuffer.gmk
 include GensrcExceptions.gmk
+include GensrcVarHandles.gmk
 include GensrcModuleLoaderMap.gmk
 
 ################################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/gensrc/GensrcVarHandles.gmk	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,162 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+GENSRC_VARHANDLES :=
+
+VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
+VARHANDLES_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/invoke
+
+################################################################################
+# Setup a rule for generating a VarHandle java class
+# Param 1 - Variable declaration prefix
+# Param 2 - Type with first letter capitalized
+define GenerateVarHandle
+
+  $1_Type := $2
+
+  $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
+
+  ifneq ($$(findstring $$($1_Type), Object Int Long), )
+    $1_ARGS += -KCAS
+  endif
+
+  ifneq ($$(findstring $$($1_Type), Int Long), )
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  $$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
+        ifeq ($$($1_Type), Object)
+	  $$(eval $1_type := $$($1_Type))
+        else
+	  $$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
+        endif
+	$$(call MakeDir, $$(@D))
+	$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
+	    $$($1_ARGS) < $$< > $$@
+
+  GENSRC_VARHANDLES += $$($1_FILENAME)
+endef
+
+################################################################################
+
+################################################################################
+# Setup a rule for generating a VarHandleByteArray java class
+# Param 1 - Variable declaration prefix
+# Param 2 - Type with first letter capitalized
+define GenerateVarHandleByteArray
+
+  $1_Type := $2
+
+  $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
+
+  ifeq ($$($1_Type), Short)
+    $1_type := short
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+  endif
+
+  ifeq ($$($1_Type), Char)
+    $1_type := char
+    $1_BoxType := Character
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+  endif
+
+  ifeq ($$($1_Type), Int)
+    $1_type := int
+    $1_BoxType := Integer
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  ifeq ($$($1_Type), Long)
+    $1_type := long
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  ifeq ($$($1_Type), Float)
+    $1_type := float
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := int
+    $1_RawType := Int
+    $1_RawBoxType := Integer
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KfloatingPoint
+  endif
+
+  ifeq ($$($1_Type), Double)
+    $1_type := double
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := long
+    $1_RawType := Long
+    $1_RawBoxType := Long
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KfloatingPoint
+  endif
+
+  $$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
+	$$(call MakeDir, $$(@D))
+	$(TOOL_SPP) -nel -K$$($1_type) \
+	    -Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
+	    -DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
+	    $$($1_ARGS) < $$< > $$@
+
+  GENSRC_VARHANDLES += $$($1_FILENAME)
+endef
+
+################################################################################
+
+# List the types to generate source for, with capitalized first letter
+VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Object
+$(foreach t, $(VARHANDLES_TYPES), \
+  $(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
+
+# List the types to generate source for, with capitalized first letter
+VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
+$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
+  $(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
+
+GENSRC_JAVA_BASE += $(GENSRC_VARHANDLES)
--- a/make/lib/Awt2dLibraries.gmk	Mon Apr 11 21:07:34 2016 +0300
+++ b/make/lib/Awt2dLibraries.gmk	Mon Apr 11 11:19:33 2016 -0700
@@ -312,7 +312,7 @@
         $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
         #
 
-    ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris), )
+    ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
       LIBAWT_XAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
     endif
 
@@ -888,7 +888,7 @@
     LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/macosx/native/libsplashscreen
   endif
 
-  ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris), )
+  ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
     LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
   endif
 
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
 
 package sun.nio.ch;
 
-import sun.misc.*;
 import java.io.IOException;
 import java.io.FileDescriptor;
 import java.util.Iterator;
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java	Mon Apr 11 11:19:33 2016 -0700
@@ -36,7 +36,6 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
-import sun.misc.*;
 
 class KQueueSelectorImpl
     extends SelectorImpl
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Mon Apr 11 11:19:33 2016 -0700
@@ -2625,6 +2625,25 @@
     // the ServiceCatalog for modules associated with this class loader.
     private volatile ServicesCatalog servicesCatalog;
 
+    /**
+     * Returns the ConcurrentHashMap used as a storage for ClassLoaderValue(s)
+     * associated with this ClassLoader, creating it if it doesn't already exist.
+     */
+    ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap() {
+        ConcurrentHashMap<?, ?> map = classLoaderValueMap;
+        if (map == null) {
+            map = new ConcurrentHashMap<>();
+            boolean set = trySetObjectField("classLoaderValueMap", map);
+            if (!set) {
+                // beaten by someone else
+                map = classLoaderValueMap;
+            }
+        }
+        return map;
+    }
+
+    // the storage for ClassLoaderValue(s) associated with this ClassLoader
+    private volatile ConcurrentHashMap<?, ?> classLoaderValueMap;
 
     /**
      * Attempts to atomically set a volatile field in this object. Returns
--- a/src/java.base/share/classes/java/lang/StringCoding.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/StringCoding.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,7 +146,7 @@
     }
 
     @HotSpotIntrinsicCandidate
-    private static boolean hasNegatives(byte[] ba, int off, int len) {
+    public static boolean hasNegatives(byte[] ba, int off, int len) {
         for (int i = off; i < off + len; i++) {
             if (ba[i] < 0) {
                 return true;
--- a/src/java.base/share/classes/java/lang/System.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/System.java	Mon Apr 11 11:19:33 2016 -0700
@@ -49,6 +49,7 @@
 import java.security.PrivilegedAction;
 import java.nio.channels.Channel;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
 import java.util.Objects;
@@ -2026,6 +2027,9 @@
             public ServicesCatalog createOrGetServicesCatalog(ClassLoader cl) {
                 return cl.createOrGetServicesCatalog();
             }
+            public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
+                return cl.createOrGetClassLoaderValueMap();
+            }
             public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
                 return cl.findBootstrapClassOrNull(name);
             }
--- a/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java	Mon Apr 11 11:19:33 2016 -0700
@@ -41,7 +41,7 @@
     private final int referenceKind;
 
     InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
-        assert(member.isResolved() || member.isMethodHandleInvoke());
+        assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());
         assert(member.referenceKindIsConsistentWith(referenceKind));
         this.member = member;
         this.referenceKind = referenceKind;
@@ -79,7 +79,8 @@
 
     @Override
     public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
-        if (member.isMethodHandleInvoke() && !member.isVarargs()) {
+        if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())
+            && !member.isVarargs()) {
             // This member is an instance of a signature-polymorphic method, which cannot be reflected
             // A method handle invoker can come in either of two forms:
             // A generic placeholder (present in the source code, and varargs)
--- a/src/java.base/share/classes/java/lang/invoke/Invokers.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/Invokers.java	Mon Apr 11 11:19:33 2016 -0700
@@ -93,6 +93,16 @@
         return setCachedInvoker(INV_BASIC, invoker);
     }
 
+    /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
+        // TODO cache invoker
+        return makeVarHandleMethodInvoker(ak);
+    }
+
+    /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
+        // TODO cache invoker
+        return makeVarHandleMethodExactInvoker(ak);
+    }
+
     private MethodHandle cachedInvoker(int idx) {
         return invokers[idx];
     }
@@ -117,6 +127,36 @@
         return invoker;
     }
 
+    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
+        MethodType mtype = targetType;
+        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
+
+        LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.name(), mtype);
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
+
+        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
+        assert(checkVarHandleInvoker(invoker));
+
+        maybeCompileToBytecode(invoker);
+        return invoker;
+    }
+
+    private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
+        MethodType mtype = targetType;
+        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
+
+        LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.name(), mtype);
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
+
+        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
+        assert(checkVarHandleInvoker(invoker));
+
+        maybeCompileToBytecode(invoker);
+        return invoker;
+    }
+
     /** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
     private void maybeCompileToBytecode(MethodHandle invoker) {
         final int EAGER_COMPILE_ARITY_LIMIT = 10;
@@ -146,6 +186,16 @@
         return true;
     }
 
+    private boolean checkVarHandleInvoker(MethodHandle invoker) {
+        MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class);
+        assert(invokerType.equals(invoker.type()))
+                : java.util.Arrays.asList(targetType, invokerType, invoker);
+        assert(invoker.internalMemberName() == null ||
+               invoker.internalMemberName().getMethodType().equals(targetType));
+        assert(!invoker.isVarargsCollector());
+        return true;
+    }
+
     /**
      * Find or create an invoker which passes unchanged a given number of arguments
      * and spreads the rest from a trailing array argument.
@@ -193,9 +243,9 @@
                                                      Object[] appendixResult) {
         int which;
         switch (name) {
-        case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
-        case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
-        default:             throw new InternalError("not invoker: "+name);
+            case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
+            case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
+            default:             throw new InternalError("not invoker: "+name);
         }
         LambdaForm lform;
         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
@@ -296,6 +346,199 @@
         return lform;
     }
 
+
+    static MemberName varHandleInvokeLinkerMethod(String name,
+                                                  MethodType mtype) {
+        LambdaForm lform;
+        if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
+            lform = varHandleMethodGenericLinkerHandleForm(name, mtype);
+        } else {
+            // TODO
+            throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
+        }
+        return lform.vmentry;
+    }
+
+    private static LambdaForm varHandleMethodGenericLinkerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_VH      = 0;
+        final int ARG_BASE     = THIS_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
+        final int LINKER_CALL  = nameCursor++;
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+        names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[THIS_VH], names[VAD_ARG]);
+
+        Object[] outArgs = new Object[ARG_LIMIT + 1];
+        outArgs[0] = names[CHECK_TYPE];
+        for (int i = 0; i < ARG_LIMIT; i++) {
+            outArgs[i + 1] = names[i];
+        }
+
+        if (CHECK_CUSTOM != -1) {
+            names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
+        }
+
+        MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType();
+        names[LINKER_CALL] = new Name(outCallType, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT + 1, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_MH      = 0;
+        final int CALL_VH      = THIS_MH + 1;
+        final int ARG_BASE     = CALL_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int GET_MEMBER   = nameCursor++;
+        final int LINKER_CALL  = nameCursor++;
+
+        MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType()
+                .appendParameterTypes(MemberName.class);
+
+        MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
+        try {
+            linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
+        } catch (ReflectiveOperationException ex) {
+            throw newInternalError(ex);
+        }
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
+        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+
+        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+
+        NamedFunction getter = speciesData.getterFunction(0);
+        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
+
+        Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
+
+        names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
+        outArgs[outArgs.length - 1] = names[GET_MEMBER];
+
+        names[LINKER_CALL] = new Name(linker, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_MH      = 0;
+        final int CALL_VH      = THIS_MH + 1;
+        final int ARG_BASE     = CALL_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int LINKER_CALL  = nameCursor++;
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
+        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+
+        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+
+        NamedFunction getter = speciesData.getterFunction(0);
+        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
+
+        Object[] outArgs = new Object[ARG_LIMIT];
+        outArgs[0] = names[CHECK_TYPE];
+        for (int i = 1; i < ARG_LIMIT; i++) {
+            outArgs[i] = names[i];
+        }
+
+        MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType();
+        names[LINKER_CALL] = new Name(outCallType, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MethodType expected = vad.symbolicMethodType;
+        MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
+
+        MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
+        if (mn == null)
+            throw vh.unsupported();
+        // TODO the following MH is not constant, cache in stable field array
+        // on VarForm?
+        MethodHandle mh = DirectMethodHandle.make(mn);
+        if (actual == expected) {
+            return mh;
+        }
+        else {
+            // Adapt to the actual (which should never fail since mh's method
+            // type is in the basic form), then to the expected (which my fail
+            // if the symbolic type descriptor does not match)
+            // TODO optimize for the case of actual.erased() == expected.erased()
+            return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
+                    asType(expected.insertParameterTypes(0, VarHandle.class));
+        }
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MethodType expected = vad.symbolicMethodType;
+        MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
+        if (actual != expected)
+            throw newWrongMethodTypeException(expected, actual);
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
+        if (mn == null) {
+            throw vh.unsupported();
+        }
+        return mn;
+    }
+
     /*non-public*/ static
     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
         // FIXME: merge with JVM logic for throwing WMTE
@@ -415,7 +658,10 @@
         NF_checkExactType,
         NF_checkGenericType,
         NF_getCallSiteTarget,
-        NF_checkCustomized;
+        NF_checkCustomized,
+        NF_checkVarHandleGenericType,
+        NF_checkVarHandleExactType,
+        NF_getVarHandleMemberName;
     static {
         try {
             NamedFunction nfs[] = {
@@ -426,7 +672,13 @@
                 NF_getCallSiteTarget = new NamedFunction(Invokers.class
                         .getDeclaredMethod("getCallSiteTarget", CallSite.class)),
                 NF_checkCustomized = new NamedFunction(Invokers.class
-                        .getDeclaredMethod("checkCustomized", MethodHandle.class))
+                        .getDeclaredMethod("checkCustomized", MethodHandle.class)),
+                NF_checkVarHandleGenericType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
+                NF_checkVarHandleExactType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
+                NF_getVarHandleMemberName = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java	Mon Apr 11 11:19:33 2016 -0700
@@ -363,6 +363,23 @@
             return false;
         }
     }
+    public boolean isVarHandleMethodInvoke() {
+        final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
+        final int negs = Modifier.STATIC;
+        if (testFlags(bits | negs, bits) &&
+            clazz == VarHandle.class) {
+            return isVarHandleMethodInvokeName(name);
+        }
+        return false;
+    }
+    public static boolean isVarHandleMethodInvokeName(String name) {
+        try {
+            VarHandle.AccessMode.valueOf(name);
+            return true;
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
     private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
 
     /** Utility method to query the modifier flags of this member. */
@@ -538,6 +555,17 @@
                 if (isMethodHandleInvoke())
                     return;
             }
+            if (m.getDeclaringClass() == VarHandle.class &&
+                isVarHandleMethodInvokeName(m.getName())) {
+                // The JVM did not reify this signature-polymorphic instance.
+                // Need a special case here.
+                // See comments on MethodHandleNatives.linkMethod.
+                MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+                int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
+                init(VarHandle.class, m.getName(), type, flags);
+                if (isVarHandleMethodInvoke())
+                    return;
+            }
             throw new LinkageError(m.toString());
         }
         assert(isResolved() && this.clazz != null);
@@ -666,6 +694,16 @@
         return mem;
     }
 
+    static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
+        return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
+    }
+    static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
+        MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
+        mem.flags |= mods;  // it's not resolved, but add these modifiers anyway
+        assert(mem.isVarHandleMethodInvoke()) : mem;
+        return mem;
+    }
+
     // bare-bones constructor; the JVM will fill it in
     MemberName() { }
 
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,9 +26,11 @@
 package java.lang.invoke;
 
 
-import java.util.*;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
@@ -92,14 +94,16 @@
  * and {@code invoke} compile to an {@code invokevirtual} instruction.
  * More unusually, the compiler must record the actual argument types,
  * and may not perform method invocation conversions on the arguments.
- * Instead, it must push them on the stack according to their own unconverted types.
- * The method handle object itself is pushed on the stack before the arguments.
- * The compiler then calls the method handle with a symbolic type descriptor which
- * describes the argument and return types.
+ * Instead, it must generate instructions that push them on the stack according
+ * to their own unconverted types.  The method handle object itself is pushed on
+ * the stack before the arguments.
+ * The compiler then generates an {@code invokevirtual} instruction that invokes
+ * the method handle with a symbolic type descriptor which describes the argument
+ * and return types.
  * <p>
  * To issue a complete symbolic type descriptor, the compiler must also determine
  * the return type.  This is based on a cast on the method invocation expression,
- * if there is one, or else {@code Object} if the invocation is an expression
+ * if there is one, or else {@code Object} if the invocation is an expression,
  * or else {@code void} if the invocation is a statement.
  * The cast may be to a primitive type (but not {@code void}).
  * <p>
@@ -109,12 +113,12 @@
  * {@code Void} except the null reference.
  *
  * <h1>Method handle invocation</h1>
- * The first time a {@code invokevirtual} instruction is executed
- * it is linked, by symbolically resolving the names in the instruction
+ * The first time an {@code invokevirtual} instruction is executed
+ * it is linked by symbolically resolving the names in the instruction
  * and verifying that the method call is statically legal.
- * This is true of calls to {@code invokeExact} and {@code invoke}.
+ * This also holds for calls to {@code invokeExact} and {@code invoke}.
  * In this case, the symbolic type descriptor emitted by the compiler is checked for
- * correct syntax and names it contains are resolved.
+ * correct syntax, and names it contains are resolved.
  * Thus, an {@code invokevirtual} instruction which invokes
  * a method handle will always link, as long
  * as the symbolic type descriptor is syntactically well-formed
@@ -163,7 +167,7 @@
  * in a program which uses method handles.
  * <p>
  * Because method types contain "live" {@code Class} objects,
- * method type matching takes into account both types names and class loaders.
+ * method type matching takes into account both type names and class loaders.
  * Thus, even if a method handle {@code M} is created in one
  * class loader {@code L1} and used in another {@code L2},
  * method handle calls are type-safe, because the caller's symbolic type
@@ -174,7 +178,7 @@
  * and its type is assigned, while the resolution in {@code L2} happens
  * when the {@code invokevirtual} instruction is linked.
  * <p>
- * Apart from the checking of type descriptors,
+ * Apart from type descriptor checks,
  * a method handle's capability to call its underlying method is unrestricted.
  * If a method handle is formed on a non-public method by a class
  * that has access to that method, the resulting handle can be used
@@ -196,7 +200,7 @@
  * Java code can create a method handle that directly accesses
  * any method, constructor, or field that is accessible to that code.
  * This is done via a reflective, capability-based API called
- * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
+ * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}.
  * For example, a static method handle can be obtained
  * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
  * There are also conversion methods from Core Reflection API objects,
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1060,6 +1060,19 @@
         FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
         return mh;
     }
+    static MethodHandle fakeVarHandleInvoke(MemberName method) {
+        // TODO caching, is it necessary?
+        MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
+                                                VarHandle.class, Object[].class);
+        MethodHandle mh = throwException(type);
+        mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
+        if (!method.getInvocationType().equals(mh.type()))
+            throw new InternalError(method.toString());
+        mh = mh.withInternalMemberName(method, false);
+        mh = mh.asVarargsCollector(Object[].class);
+        assert(method.isVarargs());
+        return mh;
+    }
 
     /**
      * Create an alias for the method handle which, when called,
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,12 +25,15 @@
 
 package java.lang.invoke;
 
+import jdk.internal.ref.CleanerFactory;
+import sun.invoke.util.Wrapper;
+
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Field;
+
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import jdk.internal.ref.CleanerFactory;
 
 /**
  * The JVM interface for the method handles package is all here.
@@ -367,8 +370,14 @@
                                      Class<?> defc, String name, Object type,
                                      Object[] appendixResult) {
         try {
-            if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
-                return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
+            if (refKind == REF_invokeVirtual) {
+                if (defc == MethodHandle.class) {
+                    return Invokers.methodHandleInvokeLinkerMethod(
+                            name, fixMethodType(callerClass, type), appendixResult);
+                } else if (defc == VarHandle.class) {
+                    return varHandleOperationLinkerMethod(
+                            name, fixMethodType(callerClass, type), appendixResult);
+                }
             }
         } catch (Throwable ex) {
             if (ex instanceof LinkageError)
@@ -400,6 +409,80 @@
         }
     }
 
+    /**
+     * Obtain the method to link to the VarHandle operation.
+     * This method is located here and not in Invokers to avoid
+     * intializing that and other classes early on in VM bootup.
+     */
+    private static MemberName varHandleOperationLinkerMethod(String name,
+                                                             MethodType mtype,
+                                                             Object[] appendixResult) {
+        // Get the signature method type
+        MethodType sigType = mtype.basicType();
+
+        // Get the access kind from the method name
+        VarHandle.AccessMode ak;
+        try {
+            ak = VarHandle.AccessMode.valueOf(name);
+        } catch (IllegalArgumentException e) {
+            throw MethodHandleStatics.newInternalError(e);
+        }
+
+        // If not polymorphic in the return type, such as the compareAndSet
+        // methods that return boolean
+        if (ak.isPolyMorphicInReturnType) {
+            if (ak.returnType != mtype.returnType()) {
+                // The caller contains a different return type than that
+                // defined by the method
+                throw newNoSuchMethodErrorOnVarHandle(name, mtype);
+            }
+            // Adjust the return type of the signature method type
+            sigType = sigType.changeReturnType(ak.returnType);
+        }
+
+        // Get the guard method type for linking
+        MethodType guardType = sigType
+                // VarHandle at start
+                .insertParameterTypes(0, VarHandle.class)
+                // Access descriptor at end
+                .appendParameterTypes(VarHandle.AccessDescriptor.class);
+
+        // Create the appendix descriptor constant
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        appendixResult[0] = ad;
+
+        if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
+            MemberName linker = new MemberName(
+                    VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
+                    guardType, REF_invokeStatic);
+            try {
+                return MemberName.getFactory().resolveOrFail(
+                        REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
+            } catch (ReflectiveOperationException ex) {
+                // Fall back to lambda form linkage if guard method is not available
+                // TODO Optionally log fallback ?
+            }
+        }
+        return Invokers.varHandleInvokeLinkerMethod(name, mtype);
+    }
+    static String getVarHandleMethodSignature(MethodType mt) {
+        StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
+
+        for (int i = 0; i < mt.parameterCount(); i++) {
+            Class<?> pt = mt.parameterType(i);
+            sb.append(getCharType(pt));
+        }
+
+        sb.append('_').append(getCharType(mt.returnType()));
+
+        return sb.toString();
+    }
+    static char getCharType(Class<?> pt) {
+        return Wrapper.forBasicType(pt).basicTypeChar();
+    }
+    static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
+        return new NoSuchMethodError("VarHandle." + name + mtype);
+    }
 
     /**
      * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Mon Apr 11 11:19:33 2016 -0700
@@ -50,9 +50,10 @@
     static final int PROFILE_LEVEL;
     static final boolean PROFILE_GWT;
     static final int CUSTOMIZE_THRESHOLD;
+    static final boolean VAR_HANDLE_GUARDS;
 
     static {
-        final Object[] values = new Object[9];
+        final Object[] values = new Object[10];
         AccessController.doPrivileged(new PrivilegedAction<>() {
                 public Void run() {
                     values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
@@ -64,6 +65,7 @@
                     values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
                     values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
                     values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
+                    values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
                     return null;
                 }
             });
@@ -76,6 +78,7 @@
         PROFILE_LEVEL             = (Integer) values[6];
         PROFILE_GWT               = (Boolean) values[7];
         CUSTOMIZE_THRESHOLD       = (Integer) values[8];
+        VAR_HANDLE_GUARDS         = (Boolean) values[9];
 
         if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
             throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Apr 11 11:19:33 2016 -0700
@@ -53,6 +53,10 @@
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
 
+import static java.lang.invoke.MethodHandleImpl.Intrinsic;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+
 /**
  * This class consists exclusively of static methods that operate on or return
  * method handles. They fall into several categories:
@@ -873,7 +877,14 @@
          * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
          * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
          * with the same {@code type} argument.
-         *
+         * <p>
+         * If the class is {@code VarHandle} and the name string corresponds to
+         * the name of a signature-polymorphic access mode method, the resulting
+         * method handle is equivalent to one produced by
+         * {@link java.lang.invoke.MethodHandles#varHandleInvoker} with
+         * the access mode corresponding to the name string and with the same
+         * {@code type} arguments.
+         * <p>
          * <b>Example:</b>
          * <blockquote><pre>{@code
 import static java.lang.invoke.MethodHandles.*;
@@ -920,6 +931,9 @@
             if (refc == MethodHandle.class) {
                 MethodHandle mh = findVirtualForMH(name, type);
                 if (mh != null)  return mh;
+            } else if (refc == VarHandle.class) {
+                MethodHandle mh = findVirtualForVH(name, type);
+                if (mh != null)  return mh;
             }
             byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
             MemberName method = resolveOrFail(refKind, refc, name, type);
@@ -936,6 +950,13 @@
             assert(!MemberName.isMethodHandleInvokeName(name));
             return null;
         }
+        private MethodHandle findVirtualForVH(String name, MethodType type) {
+            try {
+                return varHandleInvoker(VarHandle.AccessMode.valueOf(name), type);
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+        }
 
         /**
          * Produces a method handle which creates an object and initializes it, using
@@ -1135,6 +1156,7 @@
          * @exception SecurityException if a security manager is present and it
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
+         * @see #findVarHandle(Class, String, Class)
          */
         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(REF_getField, refc, name, type);
@@ -1157,6 +1179,7 @@
          * @exception SecurityException if a security manager is present and it
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
+         * @see #findVarHandle(Class, String, Class)
          */
         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(REF_putField, refc, name, type);
@@ -1164,6 +1187,53 @@
         }
 
         /**
+         * Produces a VarHandle giving access to non-static fields of type
+         * {@code T} declared by a receiver class of type {@code R}, supporting
+         * shape {@code (R : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param recv the receiver class, of type {@code R}, that declares the
+         * non-static field
+         * @param name the field's name
+         * @param type the field's type, of type {@code T}
+         * @return a VarHandle giving access to non-static fields.
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         * @since 9
+         */
+        public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            MemberName getField = resolveOrFail(REF_getField, recv, name, type);
+            MemberName putField = resolveOrFail(REF_putField, recv, name, type);
+            return getFieldVarHandle(REF_getField, REF_putField, recv, getField, putField);
+        }
+
+        /**
          * Produces a method handle giving read access to a static field.
          * The type of the method handle will have a return type of the field's
          * value type.
@@ -1212,6 +1282,55 @@
         }
 
         /**
+         * Produces a VarHandle giving access to a static field of type
+         * {@code T} declared by a given declaring class, supporting shape
+         * {@code ((empty) : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class.
+         * <p>
+         * If the returned VarHandle is operated on, the declaring class will be
+         * initialized, if it has not already been initialized.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param decl the class that declares the static field
+         * @param name the field's name
+         * @param type the field's type, of type {@code T}
+         * @return a VarHandle giving access to a static field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         * @since 9
+         */
+        public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            MemberName getField = resolveOrFail(REF_getStatic, decl, name, type);
+            MemberName putField = resolveOrFail(REF_putStatic, decl, name, type);
+            return getFieldVarHandle(REF_getStatic, REF_putStatic, decl, getField, putField);
+        }
+
+        /**
          * Produces an early-bound method handle for a non-static method.
          * The receiver must have a supertype {@code defc} in which a method
          * of the given name and type is accessible to the lookup class.
@@ -1297,6 +1416,10 @@
                 MethodHandle mh = unreflectForMH(m);
                 if (mh != null)  return mh;
             }
+            if (m.getDeclaringClass() == VarHandle.class) {
+                MethodHandle mh = unreflectForVH(m);
+                if (mh != null)  return mh;
+            }
             MemberName method = new MemberName(m);
             byte refKind = method.getReferenceKind();
             if (refKind == REF_invokeSpecial)
@@ -1311,6 +1434,12 @@
                 return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
             return null;
         }
+        private MethodHandle unreflectForVH(Method m) {
+            // these names require special lookups because they throw UnsupportedOperationException
+            if (MemberName.isVarHandleMethodInvokeName(m.getName()))
+                return MethodHandleImpl.fakeVarHandleInvoke(new MemberName(m));
+            return null;
+        }
 
         /**
          * Produces a method handle for a reflected method.
@@ -1435,6 +1564,57 @@
         }
 
         /**
+         * Produces a VarHandle that accesses fields of type {@code T} declared
+         * by a class of type {@code R}, as described by the given reflected
+         * field.
+         * If the field is non-static the VarHandle supports a shape of
+         * {@code (R : T)}, otherwise supports a shape of {@code ((empty) : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class, regardless of the value of the field's {@code accessible}
+         * flag.
+         * <p>
+         * If the field is static, and if the returned VarHandle is operated
+         * on, the field's declaring class will be initialized, if it has not
+         * already been initialized.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param f the reflected field, with a field of type {@code T}, and
+         * a declaring class of type {@code R}
+         * @return a VarHandle giving access to non-static fields or a static
+         * field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         * @since 9
+         */
+        public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
+            MemberName getField = new MemberName(f, false);
+            MemberName putField = new MemberName(f, true);
+            return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(),
+                                                      f.getDeclaringClass(), getField, putField);
+        }
+
+        /**
          * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
          * created by this lookup object or a similar one.
          * Security and access checks are performed to ensure that this lookup object
@@ -1454,7 +1634,9 @@
          */
         public MethodHandleInfo revealDirect(MethodHandle target) {
             MemberName member = target.internalMemberName();
-            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
+            if (member == null || (!member.isResolved() &&
+                                   !member.isMethodHandleInvoke() &&
+                                   !member.isVarHandleMethodInvoke()))
                 throw newIllegalArgumentException("not a direct method handle");
             Class<?> defc = member.getDeclaringClass();
             byte refKind = member.getReferenceKind();
@@ -1829,6 +2011,52 @@
                 return restrictReceiver(field, dmh, lookupClass());
             return dmh;
         }
+        private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind,
+                                            Class<?> refc, MemberName getField, MemberName putField)
+                throws IllegalAccessException {
+            final boolean checkSecurity = true;
+            return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
+        }
+        private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind,
+                                                             Class<?> refc, MemberName getField, MemberName putField)
+                throws IllegalAccessException {
+            final boolean checkSecurity = false;
+            return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
+        }
+        private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind,
+                                                  Class<?> refc, MemberName getField, MemberName putField,
+                                                  boolean checkSecurity) throws IllegalAccessException {
+            assert getField.isStatic() == putField.isStatic();
+            assert getField.isGetter() && putField.isSetter();
+            assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind);
+            assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind);
+
+            checkField(getRefKind, refc, getField);
+            if (checkSecurity)
+                checkSecurityManager(refc, getField);
+
+            if (!putField.isFinal()) {
+                // A VarHandle does not support updates to final fields, any
+                // such VarHandle to a final field will be read-only and
+                // therefore the following write-based accessibility checks are
+                // only required for non-final fields
+                checkField(putRefKind, refc, putField);
+                if (checkSecurity)
+                    checkSecurityManager(refc, putField);
+            }
+
+            boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
+                                  restrictProtectedReceiver(getField));
+            if (doRestrict) {
+                assert !getField.isStatic();
+                // receiver type of VarHandle is too wide; narrow to caller
+                if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
+                    throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
+                }
+                refc = lookupClass();
+            }
+            return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);
+        }
         /** Check access and get the requested constructor. */
         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
             final boolean checkSecurity = true;
@@ -2018,6 +2246,205 @@
         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
     }
 
+    /**
+     *
+     * Produces a VarHandle giving access to elements of an array type
+     * {@code T[]}, supporting shape {@code (T[], int : T)}.
+     * <p>
+     * Certain access modes of the returned VarHandle are unsupported under
+     * the following conditions:
+     * <ul>
+     * <li>if the component type is anything other than {@code int},
+     *     {@code long} or a reference type, then atomic update access modes
+     *     are unsupported.  (Future major platform releases of the JDK may
+     *     support additional types for certain currently unsupported access
+     *     modes.)
+     * <li>if the component type is anything other than {@code int} or
+     *     {@code long}, then numeric atomic update access modes are
+     *     unsupported.  (Future major platform releases of the JDK may
+     *     support additional numeric types for certain currently
+     *     unsupported access modes.)
+     * </ul>
+     * @param arrayClass the class of an array, of type {@code T[]}
+     * @return a VarHandle giving access to elements of an array
+     * @throws NullPointerException if the arrayClass is null
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     * @since 9
+     */
+    public static
+    VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
+        return VarHandles.makeArrayElementHandle(arrayClass);
+    }
+
+    /**
+     * Produces a VarHandle giving access to elements of a {@code byte[]} array
+     * viewed as if it were a different primitive array type, such as
+     * {@code int[]} or {@code long[]}.  The shape of the resulting VarHandle is
+     * {@code (byte[], int : T)}, where the {@code int} coordinate type
+     * corresponds to an argument that is an index in a {@code byte[]} array,
+     * and {@code T} is the component type of the given view array class.  The
+     * returned VarHandle accesses bytes at an index in a {@code byte[]} array,
+     * composing bytes to or from a value of {@code T} according to the given
+     * endianness.
+     * <p>
+     * The supported component types (variables types) are {@code short},
+     * {@code char}, {@code int}, {@code long}, {@code float} and
+     * {@code double}.
+     * <p>
+     * Access of bytes at a given index will result in an
+     * {@code IndexOutOfBoundsException} if the index is less than {@code 0}
+     * or greater than the {@code byte[]} array length minus the size (in bytes)
+     * of {@code T}.
+     * <p>
+     * Access of bytes at an index may be aligned or misaligned for {@code T},
+     * with respect to the underlying memory address, {@code A} say, associated
+     * with the array and index.
+     * If access is misaligned then access for anything other than the
+     * {@code get} and {@code set} access modes will result in an
+     * {@code IllegalStateException}.  In such cases atomic access is only
+     * guaranteed with respect to the largest power of two that divides the GCD
+     * of {@code A} and the size (in bytes) of {@code T}.
+     * If access is aligned then following access modes are supported and are
+     * guaranteed to support atomic access:
+     * <ul>
+     * <li>read write access modes for all {@code T};
+     * <li>atomic update access modes for {@code int}, {@code long},
+     *     {@code float} or {@code double}.
+     *     (Future major platform releases of the JDK may support additional
+     *     types for certain currently unsupported access modes.)
+     * <li>numeric atomic update access modes for {@code int} and {@code long}.
+     *     (Future major platform releases of the JDK may support additional
+     *     numeric types for certain currently unsupported access modes.)
+     * </ul>
+     * <p>
+     * Misaligned access, and therefore atomicity guarantees, may be determined
+     * for {@code byte[]} arrays without operating on a specific array.  Given
+     * an {@code index}, {@code T} and it's corresponding boxed type,
+     * {@code T_BOX}, misalignment may be determined as follows:
+     * <pre>{@code
+     * int sizeOfT = T_BOX.BYTES;  // size in bytes of T
+     * int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
+     *     alignmentOffset(0, sizeOfT);
+     * int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
+     * boolean isMisaligned = misalignedAtIndex != 0;
+     * }</pre>
+     *
+     * @implNote
+     * The variable types {@code float} and {@code double} are supported as if
+     * by transformation to and access with the variable types {@code int} and
+     * {@code long} respectively.  For example, the transformation of a
+     * {@code double} value to a long value is performed as if using
+     * {@link Double#doubleToRawLongBits(double)}, and the reverse
+     * transformation is performed as if using
+     * {@link Double#longBitsToDouble(long)}.
+     *
+     * @param viewArrayClass the view array class, with a component type of
+     * type {@code T}
+     * @param bigEndian true if the endianness of the view array elements, as
+     * stored in the underlying {@code byte} array, is big endian, otherwise
+     * little endian
+     * @return a VarHandle giving access to elements of a {@code byte[]} array
+     * viewed as if elements corresponding to the components type of the view
+     * array class
+     * @throws NullPointerException if viewArrayClass is null
+     * @throws IllegalArgumentException if viewArrayClass is not an array type
+     * @throws UnsupportedOperationException if the component type of
+     * viewArrayClass is not supported as a variable type
+     * @since 9
+     */
+    public static
+    VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
+                                     boolean bigEndian) throws IllegalArgumentException {
+        return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
+    }
+
+    /**
+     * Produces a VarHandle giving access to elements of a {@code ByteBuffer}
+     * viewed as if it were an array of elements of a different primitive
+     * component type to that of {@code byte}, such as {@code int[]} or
+     * {@code long[]}.  The shape of the resulting VarHandle is
+     * {@code (ByteBuffer, int : T)}, where the {@code int} coordinate type
+     * corresponds to an argument that is an index in a {@code ByteBuffer}, and
+     * {@code T} is the component type of the given view array class.  The
+     * returned VarHandle accesses bytes at an index in a {@code ByteBuffer},
+     * composing bytes to or from a value of {@code T} according to the given
+     * endianness.
+     * <p>
+     * The supported component types (variables types) are {@code short},
+     * {@code char}, {@code int}, {@code long}, {@code float} and
+     * {@code double}.
+     * <p>
+     * Access will result in a {@code ReadOnlyBufferException} for anything
+     * other than the read access modes if the {@code ByteBuffer} is read-only.
+     * <p>
+     * Access of bytes at a given index will result in an
+     * {@code IndexOutOfBoundsException} if the index is less than {@code 0}
+     * or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
+     * {@code T}.
+     * <p>
+     * Access of bytes at an index may be aligned or misaligned for {@code T},
+     * with respect to the underlying memory address, {@code A} say, associated
+     * with the {@code ByteBuffer} and index.
+     * If access is misaligned then access for anything other than the
+     * {@code get} and {@code set} access modes will result in an
+     * {@code IllegalStateException}.  In such cases atomic access is only
+     * guaranteed with respect to the largest power of two that divides the GCD
+     * of {@code A} and the size (in bytes) of {@code T}.
+     * If access is aligned then following access modes are supported and are
+     * guaranteed to support atomic access:
+     * <ul>
+     * <li>read write access modes for all {@code T};
+     * <li>atomic update access modes for {@code int}, {@code long},
+     *     {@code float} or {@code double}.
+     *     (Future major platform releases of the JDK may support additional
+     *     types for certain currently unsupported access modes.)
+     * <li>numeric atomic update access modes for {@code int} and {@code long}.
+     *     (Future major platform releases of the JDK may support additional
+     *     numeric types for certain currently unsupported access modes.)
+     * </ul>
+     * <p>
+     * Misaligned access, and therefore atomicity guarantees, may be determined
+     * for a {@code ByteBuffer}, {@code bb} (direct or otherwise), an
+     * {@code index}, {@code T} and it's corresponding boxed type,
+     * {@code T_BOX}, as follows:
+     * <pre>{@code
+     * int sizeOfT = T_BOX.BYTES;  // size in bytes of T
+     * ByteBuffer bb = ...
+     * int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
+     * boolean isMisaligned = misalignedAtIndex != 0;
+     * }</pre>
+     *
+     * @implNote
+     * The variable types {@code float} and {@code double} are supported as if
+     * by transformation to and access with the variable types {@code int} and
+     * {@code long} respectively.  For example, the transformation of a
+     * {@code double} value to a long value is performed as if using
+     * {@link Double#doubleToRawLongBits(double)}, and the reverse
+     * transformation is performed as if using
+     * {@link Double#longBitsToDouble(long)}.
+     *
+     * @param viewArrayClass the view array class, with a component type of
+     * type {@code T}
+     * @param bigEndian true if the endianness of the view array elements, as
+     * stored in the underlying {@code ByteBuffer}, is big endian, otherwise
+     * little endian (Note this overrides the endianness of a
+     * {@code ByteBuffer})
+     * @return a VarHandle giving access to elements of a {@code ByteBuffer}
+     * viewed as if elements corresponding to the components type of the view
+     * array class
+     * @throws NullPointerException if viewArrayClass is null
+     * @throws IllegalArgumentException if viewArrayClass is not an array type
+     * @throws UnsupportedOperationException if the component type of
+     * viewArrayClass is not supported as a variable type
+     * @since 9
+     */
+    public static
+    VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
+                                      boolean bigEndian) throws IllegalArgumentException {
+        return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
+    }
+
+
     /// method handle invocation (reflective style)
 
     /**
@@ -2153,6 +2580,54 @@
         return type.invokers().genericInvoker();
     }
 
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke a signature-polymorphic access mode method on any VarHandle whose
+     * associated access mode type is compatible with the given type.
+     * The resulting invoker will have a type which is exactly equal to the
+     * desired given type, except that it will accept an additional leading
+     * argument of type {@code VarHandle}.
+     *
+     * @param accessMode the VarHandle access mode
+     * @param type the desired target type
+     * @return a method handle suitable for invoking an access mode method of
+     *         any VarHandle whose access mode type is of the given type.
+     * @since 9
+     */
+    static public
+    MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
+        return type.invokers().varHandleMethodExactInvoker(accessMode);
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke a signature-polymorphic access mode method on any VarHandle whose
+     * associated access mode type is compatible with the given type.
+     * The resulting invoker will have a type which is exactly equal to the
+     * desired given type, except that it will accept an additional leading
+     * argument of type {@code VarHandle}.
+     * <p>
+     * Before invoking its target, if the access mode type differs from the
+     * desired given type, the invoker will apply reference casts as necessary
+     * and box, unbox, or widen primitive values, as if by
+     * {@link MethodHandle#asType asType}.  Similarly, the return value will be
+     * converted as necessary.
+     * <p>
+     * This method is equivalent to the following code (though it may be more
+     * efficient): {@code publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)}
+     *
+     * @param accessMode the VarHandle access mode
+     * @param type the desired target type
+     * @return a method handle suitable for invoking an access mode method of
+     *         any VarHandle whose access mode type is convertible to the given
+     *         type.
+     * @since 9
+     */
+    static public
+    MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
+        return type.invokers().varHandleMethodInvoker(accessMode);
+    }
+
     static /*non-public*/
     MethodHandle basicInvoker(MethodType type) {
         return type.invokers().basicInvoker();
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java	Mon Apr 11 11:19:33 2016 -0700
@@ -95,7 +95,7 @@
 
     // The rtype and ptypes fields define the structural identity of the method type:
     private final Class<?>   rtype;
-    private final Class<?>[] ptypes;
+    private final @Stable Class<?>[] ptypes;
 
     // The remaining fields are caches of various sorts:
     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import jdk.internal.vm.annotation.Stable;
+
+import java.lang.invoke.VarHandle.AccessMode;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A var handle form containing a set of member name, one for each operation.
+ * Each member characterizes a static method.
+ */
+class VarForm {
+
+    // Holds VarForm for VarHandle implementation classes
+    private static final ClassValue<VarForm> VFORMS
+            = new ClassValue<>() {
+        @Override
+        protected VarForm computeValue(Class<?> impl) {
+            return new VarForm(linkFromStatic(impl));
+        }
+    };
+
+    final @Stable MemberName[] table;
+
+    VarForm(MemberName[] table) {
+        this.table = table;
+    }
+
+    /**
+     * Creates a var form given an VarHandle implementation class.
+     * Each signature polymorphic method is linked to a static method of the
+     * same name on the implementation class or a super class.
+     */
+    static VarForm createFromStatic(Class<? extends VarHandle> impl) {
+        return VFORMS.get(impl);
+    }
+
+    /**
+     * Link all signature polymorphic methods.
+     */
+    private static MemberName[] linkFromStatic(Class<?> implClass) {
+        MemberName[] table = new MemberName[AccessMode.values().length];
+
+        for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
+            for (Method m : c.getDeclaredMethods()) {
+                if (Modifier.isStatic(m.getModifiers())) {
+                    try {
+                        AccessMode am = AccessMode.valueOf(m.getName());
+                        assert table[am.ordinal()] == null;
+                        table[am.ordinal()] = new MemberName(m);
+                    } catch (IllegalArgumentException ex) {
+                        // Ignore. Note the try/catch will be removed when
+                        // AccessMode enum constant names are renamed
+                    }
+                }
+            }
+        }
+        return table;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1360 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.ForceInline;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+import static java.lang.invoke.MethodHandleStatics.newInternalError;
+
+/**
+ * A VarHandle is a dynamically typed reference to a variable, or to a
+ * parametrically-defined family of variables, including static fields,
+ * non-static fields, array elements, or components of an off-heap data
+ * structure.  Access to such variables is supported under various
+ * <em>access modes</em>, including plain read/write access, volatile
+ * read/write access, and compare-and-swap.
+ *
+ * <p>VarHandles are immutable and have no visible state.  VarHandles cannot be
+ * subclassed by the user.
+ *
+ * <p>A VarHandle has:
+ * <ul>
+ * <li>a {@link #varType variable type}, referred to as {@code T}, which is the
+ * type of variable(s) referenced by this VarHandle;
+ * <li>a list of {@link #coordinateTypes coordinate types}, referred to as
+ * {@code CT}, where the types (primitive and reference) are represented by
+ * {@link Class} objects).  A list of arguments corresponding to instances of
+ * the coordinate types uniquely locates a variable referenced by this
+ * VarHandle; and
+ * <li>a <em>shape</em>, that combines the variable type and coordinate types,
+ * and is declared with the notation {@code (CT : T)}.  An empty list of
+ * coordinate types is declared as {@code (empty)}.
+ * </ul>
+ *
+ * <p>Factory methods that produce or {@link java.lang.invoke.MethodHandles.Lookup
+ * lookup} VarHandle instances document the supported variable type, coordinate
+ * types, and shape.
+ *
+ * For example, a VarHandle referencing a non-static field will declare a shape
+ * of {@code (R : T)}, where {@code R} is the receiver type and
+ * {@code T} is the field type, and where the VarHandle and an instance of the
+ * receiver type can be utilized to access the field variable.
+ * A VarHandle referencing array elements will declare a shape of
+ * {@code (T[], int : T)}, where {@code T[]} is the array type and {@code T}
+ * its component type, and where the VarHandle, an instance of the array type,
+ * and an {@code int} index can be utilized to access an array element variable.
+ *
+ * <p>Each access mode is associated with a
+ * <a href="MethodHandle.html#sigpoly">signature polymorphic</a> method of the
+ * same name, where the VarHandle shape and access mode uniquely determine the
+ * canonical {@link #accessModeType(AccessMode) access mode type},
+ * which in turn determines the matching constraints on a valid symbolic
+ * type descriptor at the call site of an access mode's method
+ * <a href="VarHandle.html#invoke">invocation</a>.
+ *
+ * As such, VarHandles are dynamically and strongly typed.  Their arity,
+ * argument types, and return type of an access mode method invocation are not
+ * statically checked.  If they, and associated values, do not match the arity
+ * and types of the access mode's type, an exception will be thrown.
+ *
+ * The parameter types of an access mode method type will consist of those that
+ * are the VarHandles's coordinate types (in order), followed by access mode
+ * parameter types specific to the access mode.
+ *
+ * <p>An access mode's method documents the form of its method signature, which
+ * is derived from the access mode parameter types.  The form is declared with
+ * the notation {@code (CT, P1 p1, P2 p2, ..., PN pn)R}, where {@code CT} is the
+ * coordinate types (as documented by a VarHandle factory method), {@code P1},
+ * {@code P2} and {@code PN} are the first, second and the n'th access mode
+ * parameters named {@code p1}, {@code p2} and {@code pn} respectively, and
+ * {@code R} is the return type.
+ *
+ * For example, for the generic shape of {@code (CT : T)} the
+ * {@link #compareAndSet} access mode method documents that its method
+ * signature is of the form {@code (CT, T expectedValue, T newValue)boolean},
+ * where the parameter types named {@code extendedValue} and {@code newValue}
+ * are the access mode parameter types.  If the VarHandle accesses array
+ * elements with a shape of say {@code (T[], int : T)} then the access mode
+ * method type is {@code (T[], int, T, T)boolean}.
+ *
+ * <p>Access modes are grouped into the following categories:
+ * <ul>
+ * <li>read access modes that get the value of a variable under specified
+ * memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #get get},
+ * {@link #getVolatile getVolatile},
+ * {@link #getAcquire getAcquire},
+ * {@link #getOpaque getOpaque}.
+ * <li>write access modes that set the value of a variable under specified
+ * memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #set set},
+ * {@link #setVolatile setVolatile},
+ * {@link #setRelease setRelease},
+ * {@link #setOpaque setOpaque}.
+ * <li>atomic update access modes that, for example, atomically compare and set
+ * the value of a variable under specified memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #compareAndSet compareAndSet},
+ * {@link #weakCompareAndSet weakCompareAndSet},
+ * {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire},
+ * {@link #weakCompareAndSetRelease weakCompareAndSetRelease},
+ * {@link #compareAndExchangeAcquire compareAndExchangeAcquire},
+ * {@link #compareAndExchangeVolatile compareAndExchangeVolatile},
+ * {@link #compareAndExchangeRelease compareAndExchangeRelease},
+ * {@link #getAndSet getAndSet}.
+ * <li>numeric atomic update access modes that, for example, atomically get and
+ * set with addition the value of a variable under specified memory ordering
+ * effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #getAndAdd getAndAdd},
+ * {@link #addAndGet addAndGet}.
+ * </ul>
+ *
+ * <p>Factory methods that produce or {@link java.lang.invoke.MethodHandles.Lookup
+ * lookup} VarHandle instances document the set of access modes that are
+ * supported, which may also include documenting restrictions based on the
+ * variable type and whether a variable is read-only.  If an access mode is not
+ * supported then the corresponding signature-polymorphic method will on
+ * invocation throw an {@code UnsupportedOperationException}.
+ * The {@link #get get} access mode is supported for all
+ * VarHandle instances and the corresponding method never throws
+ * {@code UnsupportedOperationException}.
+ * If a VarHandle references a read-only variable (for example a {@code final}
+ * field) then write, atomic update and numeric atomic update access modes are
+ * not supported and corresponding methods throw
+ * {@code UnsupportedOperationException}.
+ * Read/write access modes (if supported), with the exception of
+ * {@code get} and {@code set}, provide atomic access for
+ * reference types and all primitive types.
+ * Unless stated otherwise in the documentation of a factory method, the access
+ * modes {@code get} and {@code set} (if supported) provide atomic access for
+ * reference types and all primitives types, with the exception of {@code long}
+ * and {@code double} on 32-bit platforms
+ *
+ * <p>Access modes will override any memory ordering effects specified at
+ * the declaration site of a variable.  For example, a VarHandle accessing a
+ * a field using the {@code get} access mode will access the field as
+ * specified <em>by its access mode</em> even if that field is declared
+ * {@code volatile}.  When mixed access is performed extreme care should be
+ * taken since the Java Memory Model may permit surprising results.
+ *
+ * <p>In addition to supporting access to variables under various access modes,
+ * a set of static methods, referred to as memory fence methods, is also
+ * provided for fine-grained control of memory ordering.
+ *
+ * The Java Language Specification permits other threads to observe operations
+ * as if they were executed in orders different than are apparent in program
+ * source code, subject to constraints arising, for example, from the use of
+ * locks, {@code volatile} fields or VarHandles.  The static methods,
+ * {@link #fullFence fullFence}, {@link #acquireFence acquireFence},
+ * {@link #releaseFence releaseFence}, {@link #loadLoadFence loadLoadFence} and
+ * {@link #storeStoreFence storeStoreFence}, can also be used to impose
+ * constraints.  Their specifications, as is the case for certain access modes,
+ * are phrased in terms of the lack of "reorderings" -- observable ordering
+ * effects that might otherwise occur if the fence was not present.  More
+ * precise phrasing of the specification of access mode methods and memory fence
+ * methods may accompany future updates of the Java Language Specification.
+ *
+ * <h1>Compilation of an access mode's method</h1>
+ * A Java method call expression naming an access mode method can invoke a
+ * VarHandle from Java source code.  From the viewpoint of source code, these
+ * methods can take any arguments and their polymorphic result (if expressed)
+ * can be cast to any return type.  Formally this is accomplished by giving the
+ * access mode methods variable arity {@code Object} arguments and
+ * {@code Object} return types (if the return type is polymorphic), but they
+ * have an additional quality called <em>signature polymorphism</em> which
+ * connects this freedom of invocation directly to the JVM execution stack.
+ * <p>
+ * As is usual with virtual methods, source-level calls to access mode methods
+ * compile to an {@code invokevirtual} instruction.  More unusually, the
+ * compiler must record the actual argument types, and may not perform method
+ * invocation conversions on the arguments.  Instead, it must generate
+ * instructions to push them on the stack according to their own unconverted
+ * types.  The VarHandle object itself will be pushed on the stack before the
+ * arguments.  The compiler then generates an {@code invokevirtual} instruction
+ * that invokes the access mode method with a symbolic type descriptor which
+ * describes the argument and return types.
+ * <p>
+ * To issue a complete symbolic type descriptor, the compiler must also
+ * determine the return type (if polymorphic).  This is based on a cast on the
+ * method invocation expression, if there is one, or else {@code Object} if the
+ * invocation is an expression, or else {@code void} if the invocation is a
+ * statement.  The cast may be to a primitive type (but not {@code void}).
+ * <p>
+ * As a corner case, an uncasted {@code null} argument is given a symbolic type
+ * descriptor of {@code java.lang.Void}.  The ambiguity with the type
+ * {@code Void} is harmless, since there are no references of type {@code Void}
+ * except the null reference.
+ *
+ *
+ * <h1><a name="invoke">Invocation of an access mode's method</a></h1>
+ * The first time an {@code invokevirtual} instruction is executed it is linked
+ * by symbolically resolving the names in the instruction and verifying that
+ * the method call is statically legal.  This also holds for calls to access mode
+ * methods.  In this case, the symbolic type descriptor emitted by the compiler
+ * is checked for correct syntax, and names it contains are resolved.  Thus, an
+ * {@code invokevirtual} instruction which invokes an access mode method will
+ * always link, as long as the symbolic type descriptor is syntactically
+ * well-formed and the types exist.
+ * <p>
+ * When the {@code invokevirtual} is executed after linking, the receiving
+ * VarHandle's access mode type is first checked by the JVM to ensure that it
+ * matches the symbolic type descriptor.  If the type
+ * match fails, it means that the access mode method which the caller is
+ * invoking is not present on the individual VarHandle being invoked.
+ *
+ * <p>
+ * Invocation of an access mode's signature-polymorphic method behaves as if an
+ * invocation of {@link MethodHandle#invoke}, where the receiving method handle
+ * is bound to a VarHandle instance and the access mode.  More specifically, the
+ * following:
+ * <pre> {@code
+ * VarHandle vh = ..
+ * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
+ * }</pre>
+ * behaves as if (modulo the access mode methods do not declare throwing of
+ * {@code Throwable}):
+ * <pre> {@code
+ * VarHandle vh = ..
+ * MethodHandle mh = MethodHandles.varHandleExactInvoker(
+ *                       VarHandle.AccessMode.{access-mode},
+ *                       vh.accessModeType(VarHandle.AccessMode.{access-mode}));
+ *
+ * mh = mh.bindTo(vh);
+ * R r = (R) mh.invoke(p1, p2, ..., pN)
+ * }</pre>
+ * or, more concisely, behaves as if:
+ * <pre> {@code
+ * VarHandle vh = ..
+ * MethodHandle mh = vh.toMethodHandle(VarHandle.AccessMode.{access-mode});
+ *
+ * R r = (R) mh.invoke(p1, p2, ..., pN)
+ * }</pre>
+ * In terms of equivalent {@code invokevirtual} bytecode behaviour an access
+ * mode method invocation is equivalent to:
+ * <pre> {@code
+ * MethodHandle mh = MethodHandles.lookup().findVirtual(
+ *                       VarHandle.class,
+ *                       VarHandle.AccessMode.{access-mode}.name(),
+ *                       MethodType.methodType(R, p1, p2, ..., pN));
+ *
+ * R r = (R) mh.invokeExact(vh, p1, p2, ..., pN)
+ * }</pre>
+ * where the desired method type is the symbolic type descriptor and a
+ * {@link MethodHandle#invokeExact} is performed, since before invocation of the
+ * target, the handle will apply reference casts as necessary and box, unbox, or
+ * widen primitive values, as if by {@link MethodHandle#asType asType} (see also
+ * {@link MethodHandles#varHandleInvoker}).
+ *
+ * <h1>Invocation checking</h1>
+ * In typical programs, VarHandle access mode type matching will usually
+ * succeed.  But if a match fails, the JVM will throw a
+ * {@link WrongMethodTypeException}.
+ * <p>
+ * Thus, an access mode type mismatch which might show up as a linkage error
+ * in a statically typed program can show up as a dynamic
+ * {@code WrongMethodTypeException} in a program which uses VarHandles.
+ * <p>
+ * Because access mode types contain "live" {@code Class} objects, method type
+ * matching takes into account both type names and class loaders.
+ * Thus, even if a VarHandle {@code VH} is created in one class loader
+ * {@code L1} and used in another {@code L2}, VarHandle access mode method
+ * calls are type-safe, because the caller's symbolic type descriptor, as
+ * resolved in {@code L2}, is matched against the original callee method's
+ * symbolic type descriptor, as resolved in {@code L1}.  The resolution in
+ * {@code L1} happens when {@code VH} is created and its access mode types are
+ * assigned, while the resolution in {@code L2} happens when the
+ * {@code invokevirtual} instruction is linked.
+ * <p>
+ * Apart from type descriptor checks, a VarHandles's capability to
+ * access it's variables is unrestricted.
+ * If a VarHandle is formed on a non-public variable by a class that has access
+ * to that variable, the resulting VarHandle can be used in any place by any
+ * caller who receives a reference to it.
+ * <p>
+ * Unlike with the Core Reflection API, where access is checked every time a
+ * reflective method is invoked, VarHandle access checking is performed
+ * <a href="MethodHandles.Lookup.html#access">when the VarHandle is
+ * created</a>.
+ * Thus, VarHandles to non-public variables, or to variables in non-public
+ * classes, should generally be kept secret.  They should not be passed to
+ * untrusted code unless their use from the untrusted code would be harmless.
+ *
+ *
+ * <h1>VarHandle creation</h1>
+ * Java code can create a VarHandle that directly accesses any field that is
+ * accessible to that code.  This is done via a reflective, capability-based
+ * API called {@link java.lang.invoke.MethodHandles.Lookup
+ * MethodHandles.Lookup}.
+ * For example, a VarHandle for a non-static field can be obtained
+ * from {@link java.lang.invoke.MethodHandles.Lookup#findVarHandle
+ * Lookup.findVarHandle}.
+ * There is also a conversion method from Core Reflection API objects,
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflectVarHandle
+ * Lookup.unreflectVarHandle}.
+ * <p>
+ * Access to protected field members is restricted to receivers only of the
+ * accessing class, or one of its subclasses, and the accessing class must in
+ * turn be a subclass (or package sibling) of the protected member's defining
+ * class.  If a VarHandle refers to a protected non-static field of a declaring
+ * class outside the current package, the receiver argument will be narrowed to
+ * the type of the accessing class.
+ *
+ * <h1>Interoperation between VarHandles and the Core Reflection API</h1>
+ * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup
+ * Lookup} API, any field represented by a Core Reflection API object
+ * can be converted to a behaviorally equivalent VarHandle.
+ * For example, a reflective {@link java.lang.reflect.Field Field} can
+ * be converted to a VarHandle using
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflectVarHandle
+ * Lookup.unreflectVarHandle}.
+ * The resulting VarHandles generally provide more direct and efficient
+ * access to the underlying fields.
+ * <p>
+ * As a special case, when the Core Reflection API is used to view the
+ * signature polymorphic access mode methods in this class, they appear as
+ * ordinary non-polymorphic methods.  Their reflective appearance, as viewed by
+ * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
+ * is unaffected by their special status in this API.
+ * For example, {@link java.lang.reflect.Method#getModifiers
+ * Method.getModifiers}
+ * will report exactly those modifier bits required for any similarly
+ * declared method, including in this case {@code native} and {@code varargs}
+ * bits.
+ * <p>
+ * As with any reflected method, these methods (when reflected) may be invoked
+ * directly via {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke},
+ * via JNI, or indirectly via
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * However, such reflective calls do not result in access mode method
+ * invocations.  Such a call, if passed the required argument (a single one, of
+ * type {@code Object[]}), will ignore the argument and will throw an
+ * {@code UnsupportedOperationException}.
+ * <p>
+ * Since {@code invokevirtual} instructions can natively invoke VarHandle
+ * access mode methods under any symbolic type descriptor, this reflective view
+ * conflicts with the normal presentation of these methods via bytecodes.
+ * Thus, these native methods, when reflectively viewed by
+ * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
+ * <p>
+ * In order to obtain an invoker method for a particular access mode type,
+ * use {@link java.lang.invoke.MethodHandles#varHandleExactInvoker} or
+ * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.  The
+ * {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
+ * API is also able to return a method handle to call an access mode method for
+ * any specified access mode type and is equivalent in behaviour to
+ * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
+ *
+ * <h1>Interoperation between VarHandles and Java generics</h1>
+ * A VarHandle can be obtained for a variable, such as a a field, which is
+ * declared with Java generic types.  As with the Core Reflection API, the
+ * VarHandle's variable type will be constructed from the erasure of the
+ * source-level type.  When a VarHandle access mode method is invoked, the
+ * types
+ * of its arguments or the return value cast type may be generic types or type
+ * instances.  If this occurs, the compiler will replace those types by their
+ * erasures when it constructs the symbolic type descriptor for the
+ * {@code invokevirtual} instruction.
+ *
+ * @see MethodHandle
+ * @see MethodHandles
+ * @see MethodType
+ * @since 9
+ */
+public abstract class VarHandle {
+    // Use explicit final fields rather than an @Stable array as
+    // this can reduce the memory per handle
+    // e.g. by 24 bytes on 64 bit architectures
+    final MethodType typeGet;
+    final MethodType typeSet;
+    final MethodType typeCompareSwap;
+    final MethodType typeCompareExchange;
+    final MethodType typeGetAndUpdate;
+
+    final VarForm vform;
+
+    VarHandle(VarForm vform, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
+        this.vform = vform;
+
+        // (Receiver, <Intermediates>)
+        List<Class<?>> l = new ArrayList<>();
+        if (receiver != null)
+            l.add(receiver);
+        l.addAll(Arrays.asList(intermediate));
+
+        // (Receiver, <Intermediates>)Value
+        this.typeGet = MethodType.methodType(value, l);
+
+        // (Receiver, <Intermediates>, Value)void
+        l.add(value);
+        this.typeSet = MethodType.methodType(void.class, l);
+
+        // (Receiver, <Intermediates>, Value)Value
+        this.typeGetAndUpdate = MethodType.methodType(value, l);
+
+        // (Receiver, <Intermediates>, Value, Value)boolean
+        l.add(value);
+        this.typeCompareSwap = MethodType.methodType(boolean.class, l);
+
+        // (Receiver, <Intermediates>, Value, Value)Value
+        this.typeCompareExchange = MethodType.methodType(value, l);
+    }
+
+    RuntimeException unsupported() {
+        return new UnsupportedOperationException();
+    }
+
+    // Plain accessors
+
+    /**
+     * Returns the value of a variable, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.  Commonly referred to
+     * as plain read access.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code get}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.get)} on this VarHandle.
+     *
+     * <p>This access mode is supported by all VarHandle instances and never
+     * throws {@code UnsupportedOperationException}.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object get(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, with memory
+     * semantics of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.  Commonly referred to as plain write access.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}
+     *
+     * <p>The symbolic type descriptor at the call site of {@code set}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.set)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void set(Object... args);
+
+
+    // Volatile accessors
+
+    /**
+     * Returns the value of a variable, with memory semantics of reading as if
+     * the variable was declared {@code volatile}.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getVolatile)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getVolatile(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, with memory
+     * semantics of setting as if the variable was declared {@code volatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setVolatile)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_seq_cst}.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setVolatile(Object... args);
+
+
+    /**
+     * Returns the value of a variable, accessed in program order, but with no
+     * assurance of memory ordering effects with respect to other threads.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getOpaque}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getOpaque)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getOpaque(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, in program order,
+     * but with no assurance of memory ordering effects with respect to other
+     * threads.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setOpaque}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setOpaque)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setOpaque(Object... args);
+
+
+    // Lazy accessors
+
+    /**
+     * Returns the value of a variable, and ensures that subsequent loads and
+     * stores are not reordered before this access.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAcquire)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_acquire} ordering.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAcquire(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, and ensures that
+     * prior loads and stores are not reordered after this access.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_release} ordering.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setRelease(Object... args);
+
+
+    // Compare and set accessors
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndSet} must match the access mode type that is the result of
+     * calling {@code accessModeType(VarHandle.AccessMode.compareAndSet)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean compareAndSet(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeVolatile)}
+     * on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeVolatile(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getAcquire}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeAcquire)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #getAcquire(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeAcquire(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setRelease} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setRelease(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeRelease(Object... args);
+
+    // Weak (spurious failures allowed)
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSet} must match the access mode type that is the result of
+     * calling {@code accessModeType(VarHandle.AccessMode.weakCompareAndSet)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSet(Object... args);
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getAcquire}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSetAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetAcquire)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #getAcquire(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSetAcquire(Object... args);
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #setRelease} if the variable's current
+     * value, referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSetRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setRelease(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSetRelease(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} and returns the variable's
+     * previous value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAndSet}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAndSet)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the previous value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAndSet(Object... args);
+
+
+    // Primitive adders
+    // Throw UnsupportedOperationException for refs
+
+    /**
+     * Atomically adds the {@code value} to the current value of a variable with
+     * the memory semantics of {@link #setVolatile}, and returns the variable's
+     * previous value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T value)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAndAdd}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAndAdd)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T value)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the previous value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAndAdd(Object... args);
+
+    /**
+     * Atomically adds the {@code value} to the current value of a variable with
+     * the memory semantics of {@link #setVolatile}, and returns the variable's
+     * current (updated) value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T value)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code addAndGet}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.addAndGet)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T value)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the current value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object addAndGet(Object... args);
+
+    enum AccessType {
+        get,                  // 0
+        set,                  // 1
+        compareAndSwap,       // 2
+        compareAndExchange,   // 3
+        getAndUpdate;         // 4
+
+        MethodType getMethodType(VarHandle vh) {
+            return getMethodType(this.ordinal(), vh);
+        }
+
+        @ForceInline
+        static MethodType getMethodType(int ordinal, VarHandle vh) {
+            if (ordinal == 0) {
+                return vh.typeGet;
+            }
+            else if (ordinal == 1) {
+                return vh.typeSet;
+            }
+            else if (ordinal == 2) {
+                return vh.typeCompareSwap;
+            }
+            else if (ordinal == 3) {
+                return vh.typeCompareExchange;
+            }
+            else if (ordinal == 4) {
+                return vh.typeGetAndUpdate;
+            }
+            else {
+                throw new IllegalStateException("Illegal access type: " + ordinal);
+            }
+        }
+    }
+
+    /**
+     * The set of access modes that specify how a variable, referenced by a
+     * VarHandle, is accessed.
+     */
+    public enum AccessMode {
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#get VarHandle.get}
+         */
+        get(AccessType.get, Object.class),   // 0
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#set VarHandle.set}
+         */
+        set(AccessType.set, void.class),     // 1
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getVolatile VarHandle.getVolatile}
+         */
+        getVolatile(AccessType.get, Object.class),  // 2
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setVolatile VarHandle.setVolatile}
+         */
+        setVolatile(AccessType.set, void.class),    // 3
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAcquire VarHandle.getAcquire}
+         */
+        getAcquire(AccessType.get, Object.class),   // 4
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setRelease VarHandle.setRelease}
+         */
+        setRelease(AccessType.set, void.class),     // 5
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getOpaque VarHandle.getOpaque}
+         */
+        getOpaque(AccessType.get, Object.class),    // 6
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setOpaque VarHandle.setOpaque}
+         */
+        setOpaque(AccessType.set, void.class),      // 7
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndSet VarHandle.compareAndSet}
+         */
+        compareAndSet(AccessType.compareAndSwap, boolean.class),    // 8
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
+         */
+        compareAndExchangeVolatile(AccessType.compareAndExchange, Object.class), // 9
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
+         */
+        compareAndExchangeAcquire(AccessType.compareAndExchange, Object.class),  // 10
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
+         */
+        compareAndExchangeRelease(AccessType.compareAndExchange, Object.class),  // 11
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
+         */
+        weakCompareAndSet(AccessType.compareAndSwap, boolean.class),        // 12
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
+         */
+        weakCompareAndSetAcquire(AccessType.compareAndSwap, boolean.class), // 13
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
+         */
+        weakCompareAndSetRelease(AccessType.compareAndSwap, boolean.class), // 14
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAndSet VarHandle.getAndSet}
+         */
+        getAndSet(AccessType.getAndUpdate, Object.class),   // 15
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAndAdd VarHandle.getAndAdd}
+         */
+        getAndAdd(AccessType.getAndUpdate, Object.class),   // 16
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#addAndGet VarHandle.addAndGet}
+         */
+        addAndGet(AccessType.getAndUpdate, Object.class),   // 17
+        ;
+
+        final AccessType at;
+        final boolean isPolyMorphicInReturnType;
+        final Class<?> returnType;
+
+        AccessMode(AccessType at, Class<?> returnType) {
+            this.at = at;
+
+            // Assert that return type is correct
+            // Otherwise, when disabled avoid using reflection
+            assert returnType == getReturnType(name());
+
+            this.returnType = returnType;
+            isPolyMorphicInReturnType = returnType != Object.class;
+        }
+
+        private static Class<?> getReturnType(String name) {
+            try {
+                Method m = VarHandle.class.getMethod(name, Object[].class);
+                return m.getReturnType();
+            }
+            catch (Exception e) {
+                throw newInternalError(e);
+            }
+        }
+
+        @ForceInline
+        static MemberName getMemberName(int ordinal, VarForm vform) {
+            return vform.table[ordinal];
+        }
+    }
+
+    static final class AccessDescriptor {
+        final MethodType symbolicMethodType;
+        final int type;
+        final int mode;
+
+        public AccessDescriptor(MethodType symbolicMethodType, int type, int mode) {
+            this.symbolicMethodType = symbolicMethodType;
+            this.type = type;
+            this.mode = mode;
+        }
+    }
+
+    /**
+     * Returns the variable type of variables referenced by this VarHandle.
+     *
+     * @return the variable type of variables referenced by this VarHandle
+     */
+    public final Class<?> varType() {
+        return typeSet.parameterType(typeSet.parameterCount() - 1);
+    }
+
+    /**
+     * Returns the coordinate types for this VarHandle.
+     *
+     * @return the coordinate types for this VarHandle. The returned
+     * list is unmodifiable
+     */
+    public final List<Class<?>> coordinateTypes() {
+        return typeGet.parameterList();
+    }
+
+    /**
+     * Obtains the canonical access mode type for this VarHandle and a given
+     * access mode.
+     *
+     * <p>The access mode type's parameter types will consist of a prefix that
+     * is the coordinate types of this VarHandle followed by further
+     * types as defined by the access mode's method.
+     * The access mode type's return type is defined by the return type of the
+     * access mode's method.
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return the access mode type for the given access mode
+     */
+    public final MethodType accessModeType(AccessMode accessMode) {
+        return accessMode.at.getMethodType(this);
+    }
+
+
+    /**
+     * Returns {@code true} if the given access mode is supported, otherwise
+     * {@code false}.
+     *
+     * <p>The return of a {@code false} value for a given access mode indicates
+     * that an {@code UnsupportedOperationException} is thrown on invocation
+     * of the corresponding access mode's signature-polymorphic method.
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return {@code true} if the given access mode is supported, otherwise
+     * {@code false}.
+     */
+    public final boolean isAccessModeSupported(AccessMode accessMode) {
+        return AccessMode.getMemberName(accessMode.ordinal(), vform) != null;
+    }
+
+    /**
+     * Obtains a method handle bound to this VarHandle and the given access
+     * mode.
+     *
+     * @apiNote This method, for a VarHandle {@code vh} and access mode
+     * {@code {access-mode}}, returns a method handle that is equivalent to
+     * method handle {@code bhm} in the following code (though it may be more
+     * efficient):
+     * <pre>{@code
+     * MethodHandle mh = MethodHandles.varHandleExactInvoker(
+     *                       vh.accessModeType(VarHandle.AccessMode.{access-mode}));
+     *
+     * MethodHandle bmh = mh.bindTo(vh);
+     * }</pre>
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return a method handle bound to this VarHandle and the given access mode
+     */
+    public final MethodHandle toMethodHandle(AccessMode accessMode) {
+        MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
+        if (mn != null) {
+            return DirectMethodHandle.make(mn).
+                    bindTo(this).
+                    asType(accessMode.at.getMethodType(this));
+        }
+        else {
+            // Ensure an UnsupportedOperationException is thrown
+            return MethodHandles.varHandleInvoker(accessMode, accessModeType(accessMode)).
+                    bindTo(this);
+        }
+    }
+
+    /*non-public*/
+    final void updateVarForm(VarForm newVForm) {
+        if (vform == newVForm) return;
+        UNSAFE.putObject(this, VFORM_OFFSET, newVForm);
+        UNSAFE.fullFence();
+    }
+
+    static final BiFunction<Integer, Integer, ArrayIndexOutOfBoundsException> AIOOBE_SUPPLIER = new BiFunction<>() {
+        @Override
+        public ArrayIndexOutOfBoundsException apply(Integer a, Integer b) {
+            return new ArrayIndexOutOfBoundsException(a, b);
+        }
+    };
+
+    private static final long VFORM_OFFSET;
+
+    static {
+        try {
+            VFORM_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class.getDeclaredField("vform"));
+        }
+        catch (ReflectiveOperationException e) {
+            throw newInternalError(e);
+        }
+    }
+
+
+    // Fence methods
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered
+     * with
+     * loads and stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_seq_cst)}
+     */
+    @ForceInline
+    public static void fullFence() {
+        UNSAFE.fullFence();
+    }
+
+    /**
+     * Ensures that loads before the fence will not be reordered with loads and
+     * stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_acquire)}
+     */
+    @ForceInline
+    public static void acquireFence() {
+        UNSAFE.loadFence();
+    }
+
+    /**
+     * Ensures that loads and stores before the fence will not be
+     * reordered with stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_release)}
+     */
+    @ForceInline
+    public static void releaseFence() {
+        UNSAFE.storeFence();
+    }
+
+    /**
+     * Ensures that loads before the fence will not be reordered with
+     * loads after the fence.
+     */
+    @ForceInline
+    public static void loadLoadFence() {
+        UNSAFE.loadLoadFence();
+    }
+
+    /**
+     * Ensures that stores before the fence will not be reordered with
+     * stores after the fence.
+     */
+    @ForceInline
+    public static void storeStoreFence() {
+        UNSAFE.storeStoreFence();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandleByteArrayBase.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+/**
+ * The base class for generated byte array and byte buffer view
+ * implementations
+ */
+abstract class VarHandleByteArrayBase {
+    // Buffer.address
+    static final long BUFFER_ADDRESS;
+    // Buffer.limit
+    static final long BUFFER_LIMIT;
+    // ByteBuffer.hb
+    static final long BYTE_BUFFER_HB;
+    // ByteBuffer.isReadOnly
+    static final long BYTE_BUFFER_IS_READ_ONLY;
+
+    static {
+        try {
+            BUFFER_ADDRESS = UNSAFE.objectFieldOffset(
+                    Buffer.class.getDeclaredField("address"));
+
+            BUFFER_LIMIT = UNSAFE.objectFieldOffset(
+                    Buffer.class.getDeclaredField("limit"));
+
+            BYTE_BUFFER_HB = UNSAFE.objectFieldOffset(
+                    ByteBuffer.class.getDeclaredField("hb"));
+
+            BYTE_BUFFER_IS_READ_ONLY = UNSAFE.objectFieldOffset(
+                    ByteBuffer.class.getDeclaredField("isReadOnly"));
+        }
+        catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+    }
+
+    static final boolean BE = UNSAFE.isBigEndian();
+
+    static IllegalStateException newIllegalStateExceptionForMisalignedAccess(int index) {
+        return new IllegalStateException("Misaligned access at index: " + index);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import jdk.internal.vm.annotation.ForceInline;
+
+// This class is auto-generated by java.lang.invoke.VarHandles$GuardMethodGenerator. Do not edit.
+final class VarHandleGuards {
+
+    @ForceInline
+    final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
+        MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);
+        if (mn == null) {
+            throw handle.unsupported();
+        }
+        return mn;
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_L_L(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LL_V(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LL_L(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LLL_Z(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LLL_L(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_L_I(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LI_V(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LI_I(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LII_Z(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LII_I(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_L_J(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJ_V(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJ_J(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_L_F(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LF_V(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LF_F(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LFF_Z(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LFF_F(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_L_D(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LD_V(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LD_D(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LDD_Z(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LDD_D(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard__L(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_L_V(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LL_Z(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard__I(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_I_V(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_I_I(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_II_Z(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_II_I(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard__J(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_J_V(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_J_J(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_JJ_Z(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_JJ_J(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard__F(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_F_V(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_F_F(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_FF_Z(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_FF_F(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard__D(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_D_V(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_D_D(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_DD_Z(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_DD_D(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LI_L(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIL_V(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LIL_L(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LILL_Z(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LILL_L(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LII_V(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIII_Z(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LIII_I(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LI_J(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIJ_V(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LIJ_J(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIJJ_Z(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LIJJ_J(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LI_F(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIF_V(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LIF_F(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIFF_Z(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LIFF_F(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LI_D(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LID_V(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LID_D(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIDD_Z(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LIDD_D(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJ_I(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJI_V(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJI_I(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJII_Z(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJII_I(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJJ_V(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+final class VarHandles {
+
+    static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
+        if (!f.isStatic()) {
+            long foffset = MethodHandleNatives.objectFieldOffset(f);
+            if (!type.isPrimitive()) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
+                       : new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type);
+            }
+            else if (type == boolean.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == byte.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == short.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == char.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == int.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == long.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == float.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == double.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
+            }
+            else {
+                throw new UnsupportedOperationException();
+            }
+        }
+        else {
+            // TODO This is not lazy on first invocation
+            // and might cause some circular initialization issues
+
+            // Replace with something similar to direct method handles
+            // where a barrier is used then elided after use
+
+            if (UNSAFE.shouldBeInitialized(refc))
+                UNSAFE.ensureClassInitialized(refc);
+
+            Object base = MethodHandleNatives.staticFieldBase(f);
+            long foffset = MethodHandleNatives.staticFieldOffset(f);
+            if (!type.isPrimitive()) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
+                       : new VarHandleObjects.FieldStaticReadWrite(base, foffset, type);
+            }
+            else if (type == boolean.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == byte.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleBytes.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == short.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleShorts.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == char.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleChars.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleChars.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == int.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleInts.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleInts.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == long.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleLongs.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == float.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleFloats.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == double.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
+            }
+            else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
+        if (!arrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + arrayClass);
+
+        Class<?> componentType = arrayClass.getComponentType();
+
+        int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
+        int ascale = UNSAFE.arrayIndexScale(arrayClass);
+        int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
+
+        if (!componentType.isPrimitive()) {
+            return new VarHandleObjects.Array(aoffset, ashift, arrayClass);
+        }
+        else if (componentType == boolean.class) {
+            return new VarHandleBooleans.Array(aoffset, ashift);
+        }
+        else if (componentType == byte.class) {
+            return new VarHandleBytes.Array(aoffset, ashift);
+        }
+        else if (componentType == short.class) {
+            return new VarHandleShorts.Array(aoffset, ashift);
+        }
+        else if (componentType == char.class) {
+            return new VarHandleChars.Array(aoffset, ashift);
+        }
+        else if (componentType == int.class) {
+            return new VarHandleInts.Array(aoffset, ashift);
+        }
+        else if (componentType == long.class) {
+            return new VarHandleLongs.Array(aoffset, ashift);
+        }
+        else if (componentType == float.class) {
+            return new VarHandleFloats.Array(aoffset, ashift);
+        }
+        else if (componentType == double.class) {
+            return new VarHandleDoubles.Array(aoffset, ashift);
+        }
+        else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
+                                         boolean be) {
+        if (!viewArrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + viewArrayClass);
+
+        Class<?> viewComponentType = viewArrayClass.getComponentType();
+
+        if (viewComponentType == long.class) {
+            return new VarHandleByteArrayAsLongs.ArrayHandle(be);
+        }
+        else if (viewComponentType == int.class) {
+            return new VarHandleByteArrayAsInts.ArrayHandle(be);
+        }
+        else if (viewComponentType == short.class) {
+            return new VarHandleByteArrayAsShorts.ArrayHandle(be);
+        }
+        else if (viewComponentType == char.class) {
+            return new VarHandleByteArrayAsChars.ArrayHandle(be);
+        }
+        else if (viewComponentType == double.class) {
+            return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
+        }
+        else if (viewComponentType == float.class) {
+            return new VarHandleByteArrayAsFloats.ArrayHandle(be);
+        }
+
+        throw new UnsupportedOperationException();
+    }
+
+    static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
+                                              boolean be) {
+        if (!viewArrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + viewArrayClass);
+
+        Class<?> viewComponentType = viewArrayClass.getComponentType();
+
+        if (viewComponentType == long.class) {
+            return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == int.class) {
+            return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == short.class) {
+            return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == char.class) {
+            return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == double.class) {
+            return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == float.class) {
+            return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
+        }
+
+        throw new UnsupportedOperationException();
+    }
+
+//    /**
+//     * A helper program to generate the VarHandleGuards class with a set of
+//     * static guard methods each of which corresponds to a particular shape and
+//     * performs a type check of the symbolic type descriptor with the VarHandle
+//     * type descriptor before linking/invoking to the underlying operation as
+//     * characterized by the operation member name on the VarForm of the
+//     * VarHandle.
+//     * <p>
+//     * The generated class essentially encapsulates pre-compiled LambdaForms,
+//     * one for each method, for the most set of common method signatures.
+//     * This reduces static initialization costs, footprint costs, and circular
+//     * dependencies that may arise if a class is generated per LambdaForm.
+//     * <p>
+//     * A maximum of L*T*S methods will be generated where L is the number of
+//     * access modes kinds (or unique operation signatures) and T is the number
+//     * of variable types and S is the number of shapes (such as instance field,
+//     * static field, or array access).
+//     * If there are 4 unique operation signatures, 5 basic types (Object, int,
+//     * long, float, double), and 3 shapes then a maximum of 60 methods will be
+//     * generated.  However, the number is likely to be less since there
+//     * be duplicate signatures.
+//     * <p>
+//     * Each method is annotated with @LambdaForm.Compiled to inform the runtime
+//     * that such methods should be treated as if a method of a class that is the
+//     * result of compiling a LambdaForm.  Annotation of such methods is
+//     * important for correct evaluation of certain assertions and method return
+//     * type profiling in HotSpot.
+//     */
+//    public static class GuardMethodGenerator {
+//
+//        static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
+//
+//        static final String GUARD_METHOD_TEMPLATE =
+//                "@ForceInline\n" +
+//                "@LambdaForm.Compiled\n" +
+//                "final static <METHOD> throws Throwable {\n" +
+//                "    MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
+//                "    MethodType symbolic = ad.symbolicMethodType;\n" +
+//                "    if (target == symbolic) {\n" +
+//                "        <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
+//                "    }\n" +
+//                "    else if (target.erase() == symbolic.erase()) {\n" +
+//                "        <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
+//                "    }\n" +
+//                "    else {\n" +
+//                "        MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
+//                "        <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
+//                "    }\n" +
+//                "}";
+//
+//        static final String GET_MEMBER_NAME_METHOD =
+//                "@ForceInline\n" +
+//                "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
+//                "    MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
+//                "    if (mn == null) {\n" +
+//                "        throw handle.unsupported();\n" +
+//                "    }\n" +
+//                "    return mn;\n" +
+//                "}";
+//
+//        // A template for deriving the operations
+//        // could be supported by annotating VarHandle directly with the
+//        // operation kind and shape
+//        interface VarHandleTemplate {
+//            Object get();
+//
+//            void set(Object value);
+//
+//            boolean compareAndSwap(Object actualValue, Object expectedValue);
+//
+//            Object compareAndExchange(Object actualValue, Object expectedValue);
+//
+//            Object getAndUpdate(Object value);
+//        }
+//
+//        static class HandleType {
+//            final Class<?> receiver;
+//            final Class<?>[] intermediates;
+//            final Class<?> value;
+//
+//            HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
+//                this.receiver = receiver;
+//                this.intermediates = intermediates;
+//                this.value = value;
+//            }
+//        }
+//
+//        /**
+//         * @param args parameters
+//         */
+//        public static void main(String[] args) {
+//            System.out.println("package java.lang.invoke;");
+//            System.out.println();
+//            System.out.println("import jdk.internal.vm.annotation.ForceInline;");
+//            System.out.println();
+//            System.out.println("// This class is auto-generated by " +
+//                               GuardMethodGenerator.class.getName() +
+//                               ". Do not edit.");
+//            System.out.println("final class VarHandleGuards {");
+//
+//            System.out.println();
+//            System.out.println(GET_MEMBER_NAME_METHOD);
+//            System.out.println();
+//
+//            // Declare the stream of shapes
+//            Stream<HandleType> hts = Stream.of(
+//                    // Object->Object
+//                    new HandleType(Object.class, Object.class),
+//                    // Object->int
+//                    new HandleType(Object.class, int.class),
+//                    // Object->long
+//                    new HandleType(Object.class, long.class),
+//                    // Object->float
+//                    new HandleType(Object.class, float.class),
+//                    // Object->double
+//                    new HandleType(Object.class, double.class),
+//
+//                    // <static>->Object
+//                    new HandleType(null, Object.class),
+//                    // <static>->int
+//                    new HandleType(null, int.class),
+//                    // <static>->long
+//                    new HandleType(null, long.class),
+//                    // <static>->float
+//                    new HandleType(null, float.class),
+//                    // <static>->double
+//                    new HandleType(null, double.class),
+//
+//                    // Array[int]->Object
+//                    new HandleType(Object.class, Object.class, int.class),
+//                    // Array[int]->int
+//                    new HandleType(Object.class, int.class, int.class),
+//                    // Array[int]->long
+//                    new HandleType(Object.class, long.class, int.class),
+//                    // Array[int]->float
+//                    new HandleType(Object.class, float.class, int.class),
+//                    // Array[int]->double
+//                    new HandleType(Object.class, double.class, int.class),
+//
+//                    // Array[long]->int
+//                    new HandleType(Object.class, int.class, long.class),
+//                    // Array[long]->long
+//                    new HandleType(Object.class, long.class, long.class)
+//            );
+//
+//            hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
+//                    map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
+//                    distinct().
+//                    map(mt -> generateMethod(mt)).
+//                    forEach(s -> {
+//                        System.out.println(s);
+//                        System.out.println();
+//                    });
+//
+//            System.out.println("}");
+//        }
+//
+//        static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
+//            Class<?> returnType = m.getReturnType() == Object.class
+//                                  ? value : m.getReturnType();
+//
+//            List<Class<?>> params = new ArrayList<>();
+//            if (receiver != null)
+//                params.add(receiver);
+//            for (int i = 0; i < intermediates.length; i++) {
+//                params.add(intermediates[i]);
+//            }
+//            for (Parameter p : m.getParameters()) {
+//                params.add(value);
+//            }
+//            return MethodType.methodType(returnType, params);
+//        }
+//
+//        static String generateMethod(MethodType mt) {
+//            Class<?> returnType = mt.returnType();
+//
+//            LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
+//            params.put("handle", VarHandle.class);
+//            for (int i = 0; i < mt.parameterCount(); i++) {
+//                params.put("arg" + i, mt.parameterType(i));
+//            }
+//            params.put("ad", VarHandle.AccessDescriptor.class);
+//
+//            // Generate method signature line
+//            String RETURN = className(returnType);
+//            String NAME = "guard";
+//            String SIGNATURE = getSignature(mt);
+//            String PARAMS = params.entrySet().stream().
+//                    map(e -> className(e.getValue()) + " " + e.getKey()).
+//                    collect(joining(", "));
+//            String METHOD = GUARD_METHOD_SIG_TEMPLATE.
+//                    replace("<RETURN>", RETURN).
+//                    replace("<NAME>", NAME).
+//                    replace("<SIGNATURE>", SIGNATURE).
+//                    replace("<PARAMS>", PARAMS);
+//
+//            // Generate method
+//            params.remove("ad");
+//
+//            List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
+//                    collect(toList());
+//            LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
+//
+//            List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
+//                    collect(toList());
+//
+//            RETURN = returnType == void.class
+//                     ? ""
+//                     : returnType == Object.class
+//                       ? "return "
+//                       : "return (" + returnType.getName() + ") ";
+//
+//            String RESULT_ERASED = returnType == void.class
+//                                   ? ""
+//                                   : returnType != Object.class
+//                                     ? "return (" + returnType.getName() + ") "
+//                                     : "Object r = ";
+//
+//            String RETURN_ERASED = returnType != Object.class
+//                                   ? ""
+//                                   : " return symbolic.returnType().cast(r);";
+//
+//            return GUARD_METHOD_TEMPLATE.
+//                    replace("<METHOD>", METHOD).
+//                    replace("<NAME>", NAME).
+//                    replaceAll("<RETURN>", RETURN).
+//                    replace("<RESULT_ERASED>", RESULT_ERASED).
+//                    replace("<RETURN_ERASED>", RETURN_ERASED).
+//                    replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
+//                            collect(joining(", "))).
+//                    replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
+//                            collect(joining(", ")))
+//                    ;
+//        }
+//
+//        static String className(Class<?> c) {
+//            String n = c.getName();
+//            if (n.startsWith("java.lang.")) {
+//                n = n.replace("java.lang.", "");
+//                if (n.startsWith("invoke.")) {
+//                    n = n.replace("invoke.", "");
+//                }
+//            }
+//            return n.replace('$', '.');
+//        }
+//
+//        static String getSignature(MethodType m) {
+//            StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
+//
+//            for (int i = 0; i < m.parameterCount(); i++) {
+//                Class<?> pt = m.parameterType(i);
+//                sb.append(getCharType(pt));
+//            }
+//
+//            sb.append('_').append(getCharType(m.returnType()));
+//
+//            return sb.toString();
+//        }
+//
+//        static char getCharType(Class<?> pt) {
+//            if (pt == void.class) {
+//                return 'V';
+//            }
+//            else if (!pt.isPrimitive()) {
+//                return 'L';
+//            }
+//            else if (pt == boolean.class) {
+//                return 'Z';
+//            }
+//            else if (pt == int.class) {
+//                return 'I';
+//            }
+//            else if (pt == long.class) {
+//                return 'J';
+//            }
+//            else if (pt == float.class) {
+//                return 'F';
+//            }
+//            else if (pt == double.class) {
+//                return 'D';
+//            }
+//            else {
+//                throw new IllegalStateException(pt.getName());
+//            }
+//        }
+//    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.util.Objects;
+import jdk.internal.vm.annotation.ForceInline;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+#warn
+
+final class VarHandle$Type$s {
+
+    static class FieldInstanceReadOnly extends VarHandle {
+        final long fieldOffset;
+        final Class<?> receiverType;
+#if[Object]
+        final Class<?> fieldType;
+#end[Object]
+
+        FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
+        }
+
+        protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
+                                        Class<? extends FieldInstanceReadOnly> handle) {
+            super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
+            this.fieldOffset = fieldOffset;
+            this.receiverType = receiverType;
+#if[Object]
+            this.fieldType = fieldType;
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getVolatile(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getOpaque(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getAcquire(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+    }
+
+    static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
+
+        FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
+        }
+
+        @ForceInline
+        static void set(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                             handle.fieldOffset,
+                             {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setVolatile(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                     handle.fieldOffset,
+                                     {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setOpaque(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                   handle.fieldOffset,
+                                   {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setRelease(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                    handle.fieldOffset,
+                                    {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndSet$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                          handle.fieldOffset,
+                                          {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                       handle.fieldOffset,
+                                       value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                       handle.fieldOffset,
+                                       value) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static class FieldStaticReadOnly extends VarHandle {
+        final Object base;
+        final long fieldOffset;
+#if[Object]
+        final Class<?> fieldType;
+#end[Object]
+
+        FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
+        }
+
+        protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
+                                      Class<? extends FieldStaticReadOnly> handle) {
+            super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
+            this.base = base;
+            this.fieldOffset = fieldOffset;
+#if[Object]
+            this.fieldType = fieldType;
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getVolatile(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Volatile(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getOpaque(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Opaque(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getAcquire(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Acquire(handle.base,
+                                 handle.fieldOffset);
+        }
+    }
+
+    static class FieldStaticReadWrite extends FieldStaticReadOnly {
+
+        FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
+        }
+
+        @ForceInline
+        static void set(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$(handle.base,
+                             handle.fieldOffset,
+                             {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setVolatile(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Volatile(handle.base,
+                                     handle.fieldOffset,
+                                     {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setOpaque(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Opaque(handle.base,
+                                   handle.fieldOffset,
+                                   {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setRelease(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Release(handle.base,
+                                    handle.fieldOffset,
+                                    {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndSwap$Type$(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Acquire(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Release(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Release(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndSet$Type$(handle.base,
+                                          handle.fieldOffset,
+                                          {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(handle.base,
+                                       handle.fieldOffset,
+                                       value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(handle.base,
+                                       handle.fieldOffset,
+                                       value) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static final class Array extends VarHandle {
+        final int abase;
+        final int ashift;
+#if[Object]
+        final Class<{#if[Object]??:$type$[]}> arrayType;
+        final Class<?> componentType;
+#end[Object]
+
+        Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
+            super(VarForm.createFromStatic(Array.class),
+                  {#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
+            this.abase = abase;
+            this.ashift = ashift;
+#if[Object]
+            this.arrayType = {#if[Object]?arrayType:$type$[].class};
+            this.componentType = arrayType.getComponentType();
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return array[index];
+        }
+
+        @ForceInline
+        static void set(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            array[index] = {#if[Object]?handle.componentType.cast(value):value};
+        }
+
+        @ForceInline
+        static $type$ getVolatile(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setVolatile(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getOpaque(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Opaque(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setOpaque(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Opaque(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAcquire(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setRelease(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndSwap$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndSet$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndAdd$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndAdd$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    value) + value;
+        }
+#end[AtomicAdd]
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.ForceInline;
+
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+#warn
+
+final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
+
+    static final int ALIGN = $BoxType$.BYTES - 1;
+
+#if[floatingPoint]
+    @ForceInline
+    static $rawType$ convEndian(boolean big, $type$ v) {
+        $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
+        return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
+    }
+
+    @ForceInline
+    static $type$ convEndian(boolean big, $rawType$ rv) {
+        rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
+        return $Type$.$rawType$BitsTo$Type$(rv);
+    }
+#else[floatingPoint]
+    @ForceInline
+    static $type$ convEndian(boolean big, $type$ n) {
+        return big == BE ? n : $BoxType$.reverseBytes(n);
+    }
+#end[floatingPoint]
+
+
+    private static class ByteArrayViewVarHandle extends VarHandle {
+        final boolean be;
+
+        ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
+                               Class<?> arrayType, Class<?> component, boolean be) {
+            super(VarForm.createFromStatic(implSubType),
+                  arrayType, component, int.class);
+            this.be = be;
+        }
+    }
+
+    static final class ArrayHandle extends ByteArrayViewVarHandle {
+
+        ArrayHandle(boolean be) {
+            super(ArrayHandle.class, byte[].class, $type$.class, be);
+        }
+
+        @ForceInline
+        static int index(byte[] ba, int index) {
+            return Objects.checkIndex(index, ba.length - ALIGN, null);
+        }
+
+        @ForceInline
+        static long address(byte[] ba, int index) {
+            long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
+            if ((address & ALIGN) != 0)
+                throw newIllegalStateExceptionForMisalignedAccess(index);
+            return address;
+        }
+
+        @ForceInline
+        static $type$ get(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+#if[floatingPoint]
+            $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    handle.be);
+            return $Type$.$rawType$BitsTo$Type$(rawValue);
+#else[floatingPoint]
+            return UNSAFE.get$Type$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+#if[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    $Type$.$type$ToRaw$RawType$Bits(value),
+                    handle.be);
+#else[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    value,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Volatile(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Volatile(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Acquire(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Release(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Opaque(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Opaque(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.compareAndSwap$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Volatile(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Acquire(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Release(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$Acquire(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$Release(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.getAndSet$RawType$(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, value)));
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value))) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static final class ByteBufferHandle extends ByteArrayViewVarHandle {
+
+        ByteBufferHandle(boolean be) {
+            super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
+        }
+
+        @ForceInline
+        static int index(ByteBuffer bb, int index) {
+            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+        }
+
+        @ForceInline
+        static int indexRO(ByteBuffer bb, int index) {
+            if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
+                throw new ReadOnlyBufferException();
+            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+        }
+
+        @ForceInline
+        static long address(ByteBuffer bb, int index) {
+            long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
+            if ((address & ALIGN) != 0)
+                throw newIllegalStateExceptionForMisalignedAccess(index);
+            return address;
+        }
+
+        @ForceInline
+        static $type$ get(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+#if[floatingPoint]
+            $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    handle.be);
+            return $Type$.$rawType$BitsTo$Type$(rawValue);
+#else[floatingPoint]
+            return UNSAFE.get$Type$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+#if[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    $Type$.$type$ToRaw$RawType$Bits(value),
+                    handle.be);
+#else[floatingPoint]
+            UNSAFE.put$Type$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    value,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Volatile(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Volatile(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Acquire(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Release(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Opaque(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Opaque(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.compareAndSwap$RawType$(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Volatile(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Acquire(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Release(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$Acquire(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$Release(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndSet$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value)));
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value))) + value;
+        }
+#end[AtomicAdd]
+    }
+}
--- a/src/java.base/share/classes/java/lang/invoke/package-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/invoke/package-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,8 @@
  * certain types in this package have special relations to dynamic
  * language support in the virtual machine:
  * <ul>
- * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
+ * <li>The classes {@link java.lang.invoke.MethodHandle MethodHandle}
+ * {@link java.lang.invoke.VarHandle VarHandle} contain
  * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
  * which can be linked regardless of their type descriptor.
  * Normally, method linkage requires exact matching of type descriptors.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/AbstractClassLoaderValue.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+
+/**
+ * AbstractClassLoaderValue is a superclass of root-{@link ClassLoaderValue}
+ * and {@link Sub sub}-ClassLoaderValue.
+ *
+ * @param <CLV> the type of concrete ClassLoaderValue (this type)
+ * @param <V>   the type of values associated with ClassLoaderValue
+ */
+abstract class AbstractClassLoaderValue<CLV extends AbstractClassLoaderValue<CLV, V>, V> {
+
+    /**
+     * Sole constructor.
+     */
+    AbstractClassLoaderValue() {}
+
+    /**
+     * Returns the key component of this ClassLoaderValue. The key component of
+     * the root-{@link ClassLoaderValue} is the ClassLoaderValue itself,
+     * while the key component of a {@link #sub(Object) sub}-ClassLoaderValue
+     * is what was given to construct it.
+     *
+     * @return the key component of this ClassLoaderValue.
+     */
+    public abstract Object key();
+
+    /**
+     * Constructs new sub-ClassLoaderValue of this ClassLoaderValue with given
+     * key component.
+     *
+     * @param key the key component of the sub-ClassLoaderValue.
+     * @param <K> the type of the key component.
+     * @return a sub-ClassLoaderValue of this ClassLoaderValue for given key
+     */
+    public <K> Sub<K> sub(K key) {
+        return new Sub<>(key);
+    }
+
+    /**
+     * Returns {@code true} if this ClassLoaderValue is equal to given {@code clv}
+     * or if this ClassLoaderValue was derived from given {@code clv} by a chain
+     * of {@link #sub(Object)} invocations.
+     *
+     * @param clv the ClassLoaderValue to test this against
+     * @return if this ClassLoaderValue is equal to given {@code clv} or
+     * its descendant
+     */
+    public abstract boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv);
+
+    /**
+     * Returns the value associated with this ClassLoaderValue and given ClassLoader
+     * or {@code null} if there is none.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @return the value associated with this ClassLoaderValue and given ClassLoader
+     * or {@code null} if there is none.
+     */
+    public V get(ClassLoader cl) {
+        Object val = AbstractClassLoaderValue.<CLV>map(cl).get(this);
+        try {
+            return extractValue(val);
+        } catch (Memoizer.RecursiveInvocationException e) {
+            // propagate recursive get() for the same key that is just
+            // being calculated in computeIfAbsent()
+            throw e;
+        } catch (Throwable t) {
+            // don't propagate exceptions thrown from Memoizer - pretend
+            // that there was no entry
+            // (computeIfAbsent invocation will try to remove it anyway)
+            return null;
+        }
+    }
+
+    /**
+     * Associates given value {@code v} with this ClassLoaderValue and given
+     * ClassLoader and returns {@code null} if there was no previously associated
+     * value or does nothing and returns previously associated value if there
+     * was one.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @param v  the value to associate
+     * @return previously associated value or null if there was none
+     */
+    public V putIfAbsent(ClassLoader cl, V v) {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        @SuppressWarnings("unchecked")
+        CLV clv = (CLV) this;
+        while (true) {
+            try {
+                Object val = map.putIfAbsent(clv, v);
+                return extractValue(val);
+            } catch (Memoizer.RecursiveInvocationException e) {
+                // propagate RecursiveInvocationException for the same key that
+                // is just being calculated in computeIfAbsent
+                throw e;
+            } catch (Throwable t) {
+                // don't propagate exceptions thrown from foreign Memoizer -
+                // pretend that there was no entry and retry
+                // (foreign computeIfAbsent invocation will try to remove it anyway)
+            }
+            // TODO:
+            // Thread.onSpinLoop(); // when available
+        }
+    }
+
+    /**
+     * Removes the value associated with this ClassLoaderValue and given
+     * ClassLoader if the associated value is equal to given value {@code v} and
+     * returns {@code true} or does nothing and returns {@code false} if there is
+     * no currently associated value or it is not equal to given value {@code v}.
+     *
+     * @param cl the ClassLoader for the associated value
+     * @param v  the value to compare with currently associated value
+     * @return {@code true} if the association was removed or {@code false} if not
+     */
+    public boolean remove(ClassLoader cl, Object v) {
+        return AbstractClassLoaderValue.<CLV>map(cl).remove(this, v);
+    }
+
+    /**
+     * Returns the value associated with this ClassLoaderValue and given
+     * ClassLoader if there is one or computes the value by invoking given
+     * {@code mappingFunction}, associates it and returns it.
+     * <p>
+     * Computation and association of the computed value is performed atomically
+     * by the 1st thread that requests a particular association while holding a
+     * lock associated with this ClassLoaderValue and given ClassLoader.
+     * Nested calls from the {@code mappingFunction} to {@link #get},
+     * {@link #putIfAbsent} or {@link #computeIfAbsent} for the same association
+     * are not allowed and throw {@link IllegalStateException}. Nested call to
+     * {@link #remove} for the same association is allowed but will always return
+     * {@code false} regardless of passed-in comparison value. Nested calls for
+     * other association(s) are allowed, but care should be taken to avoid
+     * deadlocks. When two threads perform nested computations of the overlapping
+     * set of associations they should always request them in the same order.
+     *
+     * @param cl              the ClassLoader for the associated value
+     * @param mappingFunction the function to compute the value
+     * @return the value associated with this ClassLoaderValue and given
+     * ClassLoader.
+     * @throws IllegalStateException if a direct or indirect invocation from
+     *                               within given {@code mappingFunction} that
+     *                               computes the value of a particular association
+     *                               to {@link #get}, {@link #putIfAbsent} or
+     *                               {@link #computeIfAbsent}
+     *                               for the same association is attempted.
+     */
+    public V computeIfAbsent(ClassLoader cl,
+                             BiFunction<
+                                 ? super ClassLoader,
+                                 ? super CLV,
+                                 ? extends V
+                                 > mappingFunction) throws IllegalStateException {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        @SuppressWarnings("unchecked")
+        CLV clv = (CLV) this;
+        Memoizer<CLV, V> mv = null;
+        while (true) {
+            Object val = (mv == null) ? map.get(clv) : map.putIfAbsent(clv, mv);
+            if (val == null) {
+                if (mv == null) {
+                    // create Memoizer lazily when 1st needed and restart loop
+                    mv = new Memoizer<>(cl, clv, mappingFunction);
+                    continue;
+                }
+                // mv != null, therefore sv == null was a result of successful
+                // putIfAbsent
+                try {
+                    // trigger Memoizer to compute the value
+                    V v = mv.get();
+                    // attempt to replace our Memoizer with the value
+                    map.replace(clv, mv, v);
+                    // return computed value
+                    return v;
+                } catch (Throwable t) {
+                    // our Memoizer has thrown, attempt to remove it
+                    map.remove(clv, mv);
+                    // propagate exception because it's from our Memoizer
+                    throw t;
+                }
+            } else {
+                try {
+                    return extractValue(val);
+                } catch (Memoizer.RecursiveInvocationException e) {
+                    // propagate recursive attempts to calculate the same
+                    // value as being calculated at the moment
+                    throw e;
+                } catch (Throwable t) {
+                    // don't propagate exceptions thrown from foreign Memoizer -
+                    // pretend that there was no entry and retry
+                    // (foreign computeIfAbsent invocation will try to remove it anyway)
+                }
+            }
+            // TODO:
+            // Thread.onSpinLoop(); // when available
+        }
+    }
+
+    /**
+     * Removes all values associated with given ClassLoader {@code cl} and
+     * {@link #isEqualOrDescendantOf(AbstractClassLoaderValue) this or descendants}
+     * of this ClassLoaderValue.
+     * This is not an atomic operation. Other threads may see some associations
+     * be already removed and others still present while this method is executing.
+     * <p>
+     * The sole intention of this method is to cleanup after a unit test that
+     * tests ClassLoaderValue directly. It is not intended for use in
+     * actual algorithms.
+     *
+     * @param cl the associated ClassLoader of the values to be removed
+     */
+    public void removeAll(ClassLoader cl) {
+        ConcurrentHashMap<CLV, Object> map = map(cl);
+        for (Iterator<CLV> i = map.keySet().iterator(); i.hasNext(); ) {
+            if (i.next().isEqualOrDescendantOf(this)) {
+                i.remove();
+            }
+        }
+    }
+
+    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+    /**
+     * @return a ConcurrentHashMap for given ClassLoader
+     */
+    @SuppressWarnings("unchecked")
+    private static <CLV extends AbstractClassLoaderValue<CLV, ?>>
+    ConcurrentHashMap<CLV, Object> map(ClassLoader cl) {
+        return (ConcurrentHashMap<CLV, Object>)
+            (cl == null ? BootLoader.getClassLoaderValueMap()
+                        : JLA.createOrGetClassLoaderValueMap(cl));
+    }
+
+    /**
+     * @return value extracted from the {@link Memoizer} if given
+     * {@code memoizerOrValue} parameter is a {@code Memoizer} or
+     * just return given parameter.
+     */
+    @SuppressWarnings("unchecked")
+    private V extractValue(Object memoizerOrValue) {
+        if (memoizerOrValue instanceof Memoizer) {
+            return ((Memoizer<?, V>) memoizerOrValue).get();
+        } else {
+            return (V) memoizerOrValue;
+        }
+    }
+
+    /**
+     * A memoized supplier that invokes given {@code mappingFunction} just once
+     * and remembers the result or thrown exception for subsequent calls.
+     * If given mappingFunction returns null, it is converted to NullPointerException,
+     * thrown from the Memoizer's {@link #get()} method and remembered.
+     * If the Memoizer is invoked recursively from the given {@code mappingFunction},
+     * {@link RecursiveInvocationException} is thrown, but it is not remembered.
+     * The in-flight call to the {@link #get()} can still complete successfully if
+     * such exception is handled by the mappingFunction.
+     */
+    private static final class Memoizer<CLV extends AbstractClassLoaderValue<CLV, V>, V>
+        implements Supplier<V> {
+
+        private final ClassLoader cl;
+        private final CLV clv;
+        private final BiFunction<? super ClassLoader, ? super CLV, ? extends V>
+            mappingFunction;
+
+        private volatile V v;
+        private volatile Throwable t;
+        private boolean inCall;
+
+        Memoizer(ClassLoader cl,
+                 CLV clv,
+                 BiFunction<? super ClassLoader, ? super CLV, ? extends V>
+                     mappingFunction
+        ) {
+            this.cl = cl;
+            this.clv = clv;
+            this.mappingFunction = mappingFunction;
+        }
+
+        @Override
+        public V get() throws RecursiveInvocationException {
+            V v = this.v;
+            if (v != null) return v;
+            Throwable t = this.t;
+            if (t == null) {
+                synchronized (this) {
+                    if ((v = this.v) == null && (t = this.t) == null) {
+                        if (inCall) {
+                            throw new RecursiveInvocationException();
+                        }
+                        inCall = true;
+                        try {
+                            this.v = v = Objects.requireNonNull(
+                                mappingFunction.apply(cl, clv));
+                        } catch (Throwable x) {
+                            this.t = t = x;
+                        } finally {
+                            inCall = false;
+                        }
+                    }
+                }
+            }
+            if (v != null) return v;
+            if (t instanceof Error) {
+                throw (Error) t;
+            } else if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
+            } else {
+                throw new UndeclaredThrowableException(t);
+            }
+        }
+
+        static class RecursiveInvocationException extends IllegalStateException {
+            private static final long serialVersionUID = 1L;
+
+            RecursiveInvocationException() {
+                super("Recursive call");
+            }
+        }
+    }
+
+    /**
+     * sub-ClassLoaderValue is an inner class of {@link AbstractClassLoaderValue}
+     * and also a subclass of it. It can therefore be instantiated as an inner
+     * class of either an instance of root-{@link ClassLoaderValue} or another
+     * instance of itself. This enables composing type-safe compound keys of
+     * arbitrary length:
+     * <pre>{@code
+     * ClassLoaderValue<V> clv = new ClassLoaderValue<>();
+     * ClassLoaderValue<V>.Sub<K1>.Sub<K2>.Sub<K3> clv_k123 =
+     *     clv.sub(k1).sub(k2).sub(k3);
+     * }</pre>
+     * From which individual components are accessible in a type-safe way:
+     * <pre>{@code
+     * K1 k1 = clv_k123.parent().parent().key();
+     * K2 k2 = clv_k123.parent().key();
+     * K3 k3 = clv_k123.key();
+     * }</pre>
+     * This allows specifying non-capturing lambdas for the mapping function of
+     * {@link #computeIfAbsent(ClassLoader, BiFunction)} operation that can
+     * access individual key components from passed-in
+     * sub-[sub-...]ClassLoaderValue instance in a type-safe way.
+     *
+     * @param <K> the type of {@link #key()} component contained in the
+     *            sub-ClassLoaderValue.
+     */
+    final class Sub<K> extends AbstractClassLoaderValue<Sub<K>, V> {
+
+        private final K key;
+
+        Sub(K key) {
+            this.key = key;
+        }
+
+        /**
+         * @return the parent ClassLoaderValue this sub-ClassLoaderValue
+         * has been {@link #sub(Object) derived} from.
+         */
+        public AbstractClassLoaderValue<CLV, V> parent() {
+            return AbstractClassLoaderValue.this;
+        }
+
+        /**
+         * @return the key component of this sub-ClassLoaderValue.
+         */
+        @Override
+        public K key() {
+            return key;
+        }
+
+        /**
+         * sub-ClassLoaderValue is a descendant of given {@code clv} if it is
+         * either equal to it or if its {@link #parent() parent} is a
+         * descendant of given {@code clv}.
+         */
+        @Override
+        public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
+            return equals(Objects.requireNonNull(clv)) ||
+                   parent().isEqualOrDescendantOf(clv);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Sub)) return false;
+            @SuppressWarnings("unchecked")
+            Sub<?> that = (Sub<?>) o;
+            return this.parent().equals(that.parent()) &&
+                   Objects.equals(this.key, that.key);
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * parent().hashCode() +
+                   Objects.hashCode(key);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/ClassLoaderValue.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * root-ClassLoaderValue. Each instance defines a separate namespace for
+ * associated values.
+ * <p>
+ * ClassLoaderValue allows associating a
+ * {@link #computeIfAbsent(ClassLoader, BiFunction) computed} non-null value with
+ * a {@code (ClassLoader, keys...)} tuple. The associated value, as well as the
+ * keys are strongly reachable from the associated ClassLoader so care should be
+ * taken to use such keys and values that only reference types resolvable from
+ * the associated ClassLoader. Failing that, ClassLoader leaks are inevitable.
+ * <p>
+ * Example usage:
+ * <pre>{@code
+ * // create a root instance which represents a namespace and declares the type of
+ * // associated values (Class instances in this example)
+ * static final ClassLoaderValue<Class<?>> proxyClasses = new ClassLoaderValue<>();
+ *
+ * // create a compound key composed of a Module and a list of interfaces
+ * Module module = ...;
+ * List<Class<?>> interfaces = ...;
+ * ClassLoaderValue<Class<?>>.Sub<Module>.Sub<List<Class<?>>> key =
+ *     proxyClasses.sub(module).sub(interfaces);
+ *
+ * // use the compound key together with ClassLoader to lazily associate
+ * // the value with tuple (loader, module, interfaces) and return it
+ * ClassLoader loader = ...;
+ * Class<?> proxyClass = key.computeIfAbsent(loader, (ld, ky) -> {
+ *     List<Class<?>> intfcs = ky.key();
+ *     Module m = ky.parent().key();
+ *     Class<?> clazz = defineProxyClass(ld, m, intfcs);
+ *     return clazz;
+ * });
+ * }</pre>
+ * <p>
+ * {@code classLoaderValue.<operation>(classLoader, ...)} represents an operation
+ * to {@link #get}, {@link #putIfAbsent}, {@link #computeIfAbsent} or {@link #remove}
+ * a value associated with a (classLoader, classLoaderValue) tuple. ClassLoader
+ * instances and root-{@link ClassLoaderValue} instances are compared using
+ * identity equality while {@link Sub sub}-ClassLoaderValue instances define
+ * {@link #equals(Object) equality} in terms of equality of its
+ * {@link Sub#parent() parent} ClassLoaderValue and its
+ * {@link #key() key} component.
+ *
+ * @param <V> the type of value(s) associated with the root-ClassLoaderValue and
+ *            all its {@link #sub(Object) descendants}.
+ * @author Peter Levart
+ * @since 9
+ */
+final class ClassLoaderValue<V>
+    extends AbstractClassLoaderValue<ClassLoaderValue<V>, V> {
+
+    /**
+     * Constructs new root-ClassLoaderValue representing its own namespace.
+     */
+    public ClassLoaderValue() {}
+
+    /**
+     * @return the key component of this root-ClassLoaderValue (itself).
+     */
+    @Override
+    public ClassLoaderValue<V> key() {
+        return this;
+    }
+
+    /**
+     * root-ClassLoaderValue can only be equal to itself and has no predecessors.
+     */
+    @Override
+    public boolean isEqualOrDescendantOf(AbstractClassLoaderValue<?, V> clv) {
+        return equals(Objects.requireNonNull(clv));
+    }
+}
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,7 +25,6 @@
 
 package java.lang.reflect;
 
-import java.lang.ref.WeakReference;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
@@ -39,10 +38,8 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.WeakHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.BiFunction;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -284,6 +281,13 @@
         { InvocationHandler.class };
 
     /**
+     * a cache of proxy constructors with
+     * {@link Constructor#setAccessible(boolean) accessible} flag already set
+     */
+    private static final ClassLoaderValue<Constructor<?>> proxyCache =
+        new ClassLoaderValue<>();
+
+    /**
      * the invocation handler for this proxy instance.
      * @serial
      */
@@ -361,14 +365,55 @@
                                          Class<?>... interfaces)
         throws IllegalArgumentException
     {
-        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
-        final SecurityManager sm = System.getSecurityManager();
-        final Class<?> caller = Reflection.getCallerClass();
-        if (sm != null) {
-            checkProxyAccess(caller, loader, intfs);
+        Class<?> caller = System.getSecurityManager() == null
+                              ? null
+                              : Reflection.getCallerClass();
+
+        return getProxyConstructor(caller, loader, interfaces)
+            .getDeclaringClass();
+    }
+
+    /**
+     * Returns the {@code Constructor} object of a proxy class that takes a
+     * single argument of type {@link InvocationHandler}, given a class loader
+     * and an array of interfaces. The returned constructor will have the
+     * {@link Constructor#setAccessible(boolean) accessible} flag already set.
+     *
+     * @param   caller passed from a public-facing @CallerSensitive method if
+     *                 SecurityManager is set or {@code null} if there's no
+     *                 SecurityManager
+     * @param   loader the class loader to define the proxy class
+     * @param   interfaces the list of interfaces for the proxy class
+     *          to implement
+     * @return  a Constructor of the proxy class taking single
+     *          {@code InvocationHandler} parameter
+     */
+    private static Constructor<?> getProxyConstructor(Class<?> caller,
+                                                      ClassLoader loader,
+                                                      Class<?>... interfaces)
+    {
+        // optimization for single interface
+        if (interfaces.length == 1) {
+            Class<?> intf = interfaces[0];
+            if (caller != null) {
+                checkProxyAccess(caller, loader, intf);
+            }
+            return proxyCache.sub(intf).computeIfAbsent(
+                loader,
+                (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
+            );
+        } else {
+            // interfaces cloned
+            final Class<?>[] intfsArray = interfaces.clone();
+            if (caller != null) {
+                checkProxyAccess(caller, loader, intfsArray);
+            }
+            final List<Class<?>> intfs = Arrays.asList(intfsArray);
+            return proxyCache.sub(intfs).computeIfAbsent(
+                loader,
+                (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
+            );
         }
-
-        return new ProxyBuilder(loader, intfs).build();
     }
 
     /*
@@ -391,7 +436,7 @@
      */
     private static void checkProxyAccess(Class<?> caller,
                                          ClassLoader loader,
-                                         List<Class<?>> interfaces)
+                                         Class<?> ... interfaces)
     {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -399,147 +444,18 @@
             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
             }
-            ReflectUtil.checkProxyPackageAccess(ccl, interfaces.toArray(EMPTY_CLASS_ARRAY));
-        }
-    }
-
-    /*
-     * a key used for proxy class with 0 implemented interfaces
-     */
-    private static final Object key0 = new Object();
-
-    /*
-     * Key1 and Key2 are optimized for the common use of dynamic proxies
-     * that implement 1 or 2 interfaces.
-     */
-
-    /*
-     * a key used for proxy class with 1 implemented interface
-     */
-    private static final class Key1 extends WeakReference<Class<?>> {
-        private final int hash;
-
-        Key1(Class<?> intf) {
-            super(intf);
-            this.hash = intf.hashCode();
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            Class<?> intf;
-            return this == obj ||
-                   obj != null &&
-                   obj.getClass() == Key1.class &&
-                   (intf = get()) != null &&
-                   intf == ((Key1) obj).get();
-        }
-    }
-
-    /*
-     * a key used for proxy class with 2 implemented interfaces
-     */
-    private static final class Key2 extends WeakReference<Class<?>> {
-        private final int hash;
-        private final WeakReference<Class<?>> ref2;
-
-        Key2(Class<?> intf1, Class<?> intf2) {
-            super(intf1);
-            hash = 31 * intf1.hashCode() + intf2.hashCode();
-            ref2 = new WeakReference<>(intf2);
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            Class<?> intf1, intf2;
-            return this == obj ||
-                   obj != null &&
-                   obj.getClass() == Key2.class &&
-                   (intf1 = get()) != null &&
-                   intf1 == ((Key2) obj).get() &&
-                   (intf2 = ref2.get()) != null &&
-                   intf2 == ((Key2) obj).ref2.get();
-        }
-    }
-
-    /*
-     * a key used for proxy class with any number of implemented interfaces
-     * (used here for 3 or more only)
-     */
-    private static final class KeyX {
-        private final int hash;
-        private final WeakReference<Class<?>>[] refs;
-
-        @SuppressWarnings("unchecked")
-        KeyX(List<Class<?>> interfaces) {
-            hash = Arrays.hashCode(interfaces.toArray());
-            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.size()];
-            int i = 0;
-            for (Class<?> intf : interfaces) {
-                refs[i++] = new WeakReference<>(intf);
-            }
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return this == obj ||
-                   obj != null &&
-                   obj.getClass() == KeyX.class &&
-                   equals(refs, ((KeyX) obj).refs);
-        }
-
-        private static boolean equals(WeakReference<Class<?>>[] refs1,
-                                      WeakReference<Class<?>>[] refs2) {
-            if (refs1.length != refs2.length) {
-                return false;
-            }
-            for (int i = 0; i < refs1.length; i++) {
-                Class<?> intf = refs1[i].get();
-                if (intf == null || intf != refs2[i].get()) {
-                    return false;
-                }
-            }
-            return true;
+            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
         }
     }
 
     /**
-     * A function that maps an array of interfaces to an optimal key where
-     * Class objects representing interfaces are weakly referenced.
+     * Builder for a proxy class.
+     *
+     * If the module is not specified in this ProxyBuilder constructor,
+     * it will map from the given loader and interfaces to the module
+     * in which the proxy class will be defined.
      */
-    private static final class KeyFactory<T>
-        implements BiFunction<T, List<Class<?>>, Object>
-    {
-        @Override
-        public Object apply(T t, List<Class<?>> interfaces) {
-            switch (interfaces.size()) {
-                case 1: return new Key1(interfaces.get(0)); // the most frequent
-                case 2: return new Key2(interfaces.get(0), interfaces.get(1));
-                case 0: return key0;
-                default: return new KeyX(interfaces);
-            }
-        }
-    }
-
-    /**
-     * A factory function that generates, defines and returns the proxy class
-     * given the ClassLoader and array of interfaces.
-     */
-    private static final class ProxyClassFactory {
+    private static final class ProxyBuilder {
         private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
         // prefix for all proxy class names
@@ -548,6 +464,10 @@
         // next number to use for generation of unique proxy class names
         private static final AtomicLong nextUniqueNumber = new AtomicLong();
 
+        // a reverse cache of defined proxy classes
+        private static final ClassLoaderValue<Boolean> reverseProxyCache =
+            new ClassLoaderValue<>();
+
         private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
             String proxyPkg = null;     // package to define proxy class in
             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
@@ -601,8 +521,11 @@
             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                     proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
             try {
-                return UNSAFE.defineClass(proxyName, proxyClassFile, 0, proxyClassFile.length,
-                                          loader, null);
+                Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
+                                                 0, proxyClassFile.length,
+                                                 loader, null);
+                reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
+                return pc;
             } catch (ClassFormatError e) {
                 /*
                  * A ClassFormatError here means that (barring bugs in the
@@ -616,35 +539,14 @@
         }
 
         /**
-         * Test if the given class is a proxy class
+         * Test if given class is a class defined by
+         * {@link #defineProxyClass(Module, List)}
          */
         static boolean isProxyClass(Class<?> c) {
-            return proxyCache.containsValue(c);
-        }
-
-        /**
-         * Returns the proxy class.  It will return the cached proxy class
-         * if exists; otherwise, it will create the proxy class and store in
-         * the cache.
-         */
-        static Class<?> get(Module module, List<Class<?>> interfaces) {
-            return proxyCache.get(module, interfaces);
+            return Objects.equals(reverseProxyCache.sub(c).get(c.getClassLoader()),
+                                  Boolean.TRUE);
         }
 
-        /**
-         * a cache of proxy classes in the named and unnamed module
-         */
-        private static final WeakCache<Module, List<Class<?>>, Class<?>> proxyCache =
-            new WeakCache<>(new KeyFactory<Module>(),
-                new BiFunction<Module, List<Class<?>>, Class<?>>()  {
-                    @Override
-                    public Class<?> apply(Module m, List<Class<?>> interfaces) {
-                        Objects.requireNonNull(m);
-                        return defineProxyClass(m, interfaces);
-                    }
-            });
-
-
         private static boolean isExportedType(Class<?> c) {
             String pn = c.getPackageName();
             return Modifier.isPublic(c.getModifiers()) && c.getModule().isExported(pn);
@@ -685,25 +587,18 @@
                 }
             });
 
-        private static final boolean isDebug() {
+        private static boolean isDebug() {
             return !DEBUG.isEmpty();
         }
-        private static final boolean isDebug(String flag) {
+        private static boolean isDebug(String flag) {
             return DEBUG.equals(flag);
         }
-    }
+
+        // ProxyBuilder instance members start here....
 
-    /**
-     * Builder for a proxy class.
-     *
-     * If the module is not specified in this ProxyBuilder constructor,
-     * it will map from the given loader and interfaces to the module
-     * in which the proxy class will be defined.
-     */
-    private static final class ProxyBuilder {
-        final ClassLoader loader;
-        final List<Class<?>> interfaces;
-        final Module module;
+        private final ClassLoader loader;
+        private final List<Class<?>> interfaces;
+        private final Module module;
         ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
             if (!VM.isModuleSystemInited()) {
                 throw new InternalError("Proxy is not supported until module system is fully initialzed");
@@ -723,16 +618,34 @@
             assert getLoader(module) == loader;
         }
 
+        ProxyBuilder(ClassLoader loader, Class<?> intf) {
+            this(loader, Collections.singletonList(intf));
+        }
+
         /**
-         * Generate a proxy class.  If the target module does not have any
+         * Generate a proxy class and return its proxy Constructor with
+         * accessible flag already set. If the target module does not have access
          * to any interface types, IllegalAccessError will be thrown by the VM
          * at defineClass time.
          *
          * Must call the checkProxyAccess method to perform permission checks
          * before calling this.
          */
-        Class<?> build() {
-            return ProxyClassFactory.get(module, interfaces);
+        Constructor<?> build() {
+            Class<?> proxyClass = defineProxyClass(module, interfaces);
+            final Constructor<?> cons;
+            try {
+                cons = proxyClass.getConstructor(constructorParams);
+            } catch (NoSuchMethodException e) {
+                throw new InternalError(e.toString(), e);
+            }
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    cons.setAccessible(true);
+                    return null;
+                }
+            });
+            return cons;
         }
 
         /**
@@ -742,9 +655,9 @@
          * @throws IllegalArgumentException if it violates the restrictions specified
          *         in {@link Proxy#newProxyInstance}
          */
-        static void validateProxyInterfaces(ClassLoader loader,
-                                            List<Class<?>> interfaces,
-                                            Set<Class<?>> refTypes)
+        private static void validateProxyInterfaces(ClassLoader loader,
+                                                    List<Class<?>> interfaces,
+                                                    Set<Class<?>> refTypes)
         {
             Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.size());
             for (Class<?> intf : interfaces) {
@@ -779,10 +692,11 @@
          * Returns all types referenced by all public method signatures of
          * the proxy interfaces
          */
-        static Set<Class<?>> referencedTypes(ClassLoader loader, List<Class<?>> interfaces) {
+        private static Set<Class<?>> referencedTypes(ClassLoader loader,
+                                                     List<Class<?>> interfaces) {
             return interfaces.stream()
                  .flatMap(intf -> Stream.of(intf.getMethods())
-                                        .flatMap(m -> methodRefTypes(m))
+                                        .flatMap(ProxyBuilder::methodRefTypes)
                                         .map(ProxyBuilder::getElementType)
                                         .filter(t -> !t.isPrimitive()))
                  .collect(Collectors.toSet());
@@ -792,11 +706,11 @@
          * Extracts all types referenced on a method signature including
          * its return type, parameter types, and exception types.
          */
-        static Stream<Class<?>> methodRefTypes(Method m) {
+        private static Stream<Class<?>> methodRefTypes(Method m) {
             return Stream.of(new Class<?>[] { m.getReturnType() },
                              m.getParameterTypes(),
                              m.getExceptionTypes())
-                         .flatMap(a -> Stream.of(a));
+                         .flatMap(Stream::of);
         }
 
         /**
@@ -813,7 +727,9 @@
          * package.  Reads edge and qualified exports are added for
          * dynamic module to access.
          */
-        static Module mapToModule(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes) {
+        private static Module mapToModule(ClassLoader loader,
+                                          List<Class<?>> interfaces,
+                                          Set<Class<?>> refTypes) {
             Map<Class<?>, Module> modulePrivateTypes = new HashMap<>();
             Map<Class<?>, Module> packagePrivateTypes = new HashMap<>();
             for (Class<?> intf : interfaces) {
@@ -884,10 +800,9 @@
             Set<Class<?>> visited = new HashSet<>();
             while (!deque.isEmpty()) {
                 Class<?> c = deque.poll();
-                if (visited.contains(c)) {
+                if (!visited.add(c)) {
                     continue;
                 }
-                visited.add(c);
                 ensureAccess(target, c);
 
                 // add all superinterfaces
@@ -906,7 +821,7 @@
         /*
          * Ensure the given module can access the given class.
          */
-        static void ensureAccess(Module target, Class<?> c) {
+        private static void ensureAccess(Module target, Class<?> c) {
             Module m = c.getModule();
             // add read edge and qualified export for the target module to access
             if (!target.canRead(m)) {
@@ -921,7 +836,7 @@
         /*
          * Ensure the given class is visible to the class loader.
          */
-        static void ensureVisible(ClassLoader ld, Class<?> c) {
+        private static void ensureVisible(ClassLoader ld, Class<?> c) {
             Class<?> type = null;
             try {
                 type = Class.forName(c.getName(), false, ld);
@@ -933,7 +848,7 @@
             }
         }
 
-        static Class<?> getElementType(Class<?> type) {
+        private static Class<?> getElementType(Class<?> type) {
             Class<?> e = type;
             while (e.isArray()) {
                 e = e.getComponentType();
@@ -941,7 +856,8 @@
             return e;
         }
 
-        private static final WeakHashMap<ClassLoader, Module> dynProxyModules = new WeakHashMap<>();
+        private static final ClassLoaderValue<Module> dynProxyModules =
+            new ClassLoaderValue<>();
         private static final AtomicInteger counter = new AtomicInteger();
 
         /*
@@ -950,12 +866,12 @@
          *
          * Each class loader will have one dynamic module.
          */
-        static Module getDynamicModule(ClassLoader loader) {
-            return dynProxyModules.computeIfAbsent(loader, ld -> {
+        private static Module getDynamicModule(ClassLoader loader) {
+            return dynProxyModules.computeIfAbsent(loader, (ld, clv) -> {
                 // create a dynamic module and setup module access
                 String mn = "jdk.proxy" + counter.incrementAndGet();
                 String pn = PROXY_PACKAGE_PREFIX + "." + mn;
-                Module m = Modules.defineModule(loader, mn, Collections.singleton(pn));
+                Module m = Modules.defineModule(ld, mn, Collections.singleton(pn));
                 Modules.addReads(m, Proxy.class.getModule());
                 // java.base to create proxy instance
                 Modules.addExports(m, pn, Object.class.getModule());
@@ -1062,40 +978,31 @@
                                           InvocationHandler h) {
         Objects.requireNonNull(h);
 
-        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
-        final SecurityManager sm = System.getSecurityManager();
-        final Class<?> caller = Reflection.getCallerClass();
-        if (sm != null) {
-            checkProxyAccess(caller, loader, intfs);
-        }
+        final Class<?> caller = System.getSecurityManager() == null
+                                    ? null
+                                    : Reflection.getCallerClass();
 
         /*
-         * Look up or generate the designated proxy class.
+         * Look up or generate the designated proxy class and its constructor.
          */
-        Class<?> cl = new ProxyBuilder(loader, intfs).build();
+        Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
 
-        return newProxyInstance(cl, caller, h);
+        return newProxyInstance(caller, cons, h);
     }
 
-    private static Object newProxyInstance(Class<?> proxyClass, Class<?> caller, InvocationHandler h) {
+    private static Object newProxyInstance(Class<?> caller, // null if no SecurityManager
+                                           Constructor<?> cons,
+                                           InvocationHandler h) {
         /*
          * Invoke its constructor with the designated invocation handler.
          */
         try {
-            final SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                checkNewProxyPermission(caller, proxyClass);
+            if (caller != null) {
+                checkNewProxyPermission(caller, cons.getDeclaringClass());
             }
 
-            final Constructor<?> cons = proxyClass.getConstructor(constructorParams);
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    cons.setAccessible(true);
-                    return null;
-                }
-            });
             return cons.newInstance(new Object[]{h});
-        } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {
+        } catch (IllegalAccessException | InstantiationException e) {
             throw new InternalError(e.toString(), e);
         } catch (InvocationTargetException e) {
             Throwable t = e.getCause();
@@ -1150,7 +1057,7 @@
      * @throws  NullPointerException if {@code cl} is {@code null}
      */
     public static boolean isProxyClass(Class<?> cl) {
-        return Proxy.class.isAssignableFrom(cl) && ProxyClassFactory.isProxyClass(cl);
+        return Proxy.class.isAssignableFrom(cl) && ProxyBuilder.isProxyClass(cl);
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/reflect/WeakCache.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,381 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang.reflect;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.function.BiFunction;
-import java.util.function.Supplier;
-
-/**
- * Cache mapping pairs of {@code (key, sub-key) -> value}. Keys and values are
- * weakly but sub-keys are strongly referenced.  Keys are passed directly to
- * {@link #get} method which also takes a {@code parameter}. Sub-keys are
- * calculated from keys and parameters using the {@code subKeyFactory} function
- * passed to the constructor. Values are calculated from keys and parameters
- * using the {@code valueFactory} function passed to the constructor.
- * Keys can be {@code null} and are compared by identity while sub-keys returned by
- * {@code subKeyFactory} or values returned by {@code valueFactory}
- * can not be null. Sub-keys are compared using their {@link #equals} method.
- * Entries are expunged from cache lazily on each invocation to {@link #get},
- * {@link #containsValue} or {@link #size} methods when the WeakReferences to
- * keys are cleared. Cleared WeakReferences to individual values don't cause
- * expunging, but such entries are logically treated as non-existent and
- * trigger re-evaluation of {@code valueFactory} on request for their
- * key/subKey.
- *
- * @author Peter Levart
- * @param <K> type of keys
- * @param <P> type of parameters
- * @param <V> type of values
- */
-final class WeakCache<K, P, V> {
-
-    private final ReferenceQueue<K> refQueue
-        = new ReferenceQueue<>();
-    // the key type is Object for supporting null key
-    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
-        = new ConcurrentHashMap<>();
-    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
-        = new ConcurrentHashMap<>();
-    private final BiFunction<K, P, ?> subKeyFactory;
-    private final BiFunction<K, P, V> valueFactory;
-
-    /**
-     * Construct an instance of {@code WeakCache}
-     *
-     * @param subKeyFactory a function mapping a pair of
-     *                      {@code (key, parameter) -> sub-key}
-     * @param valueFactory  a function mapping a pair of
-     *                      {@code (key, parameter) -> value}
-     * @throws NullPointerException if {@code subKeyFactory} or
-     *                              {@code valueFactory} is null.
-     */
-    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
-                     BiFunction<K, P, V> valueFactory) {
-        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
-        this.valueFactory = Objects.requireNonNull(valueFactory);
-    }
-
-    /**
-     * Look-up the value through the cache. This always evaluates the
-     * {@code subKeyFactory} function and optionally evaluates
-     * {@code valueFactory} function if there is no entry in the cache for given
-     * pair of (key, subKey) or the entry has already been cleared.
-     *
-     * @param key       possibly null key
-     * @param parameter parameter used together with key to create sub-key and
-     *                  value (should not be null)
-     * @return the cached value (never null)
-     * @throws NullPointerException if {@code parameter} passed in or
-     *                              {@code sub-key} calculated by
-     *                              {@code subKeyFactory} or {@code value}
-     *                              calculated by {@code valueFactory} is null.
-     */
-    public V get(K key, P parameter) {
-        Objects.requireNonNull(parameter);
-
-        expungeStaleEntries();
-
-        Object cacheKey = CacheKey.valueOf(key, refQueue);
-
-        // lazily install the 2nd level valuesMap for the particular cacheKey
-        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
-        if (valuesMap == null) {
-            ConcurrentMap<Object, Supplier<V>> oldValuesMap
-                = map.putIfAbsent(cacheKey,
-                                  valuesMap = new ConcurrentHashMap<>());
-            if (oldValuesMap != null) {
-                valuesMap = oldValuesMap;
-            }
-        }
-
-        // create subKey and retrieve the possible Supplier<V> stored by that
-        // subKey from valuesMap
-        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
-        Supplier<V> supplier = valuesMap.get(subKey);
-        Factory factory = null;
-
-        while (true) {
-            if (supplier != null) {
-                // supplier might be a Factory or a CacheValue<V> instance
-                V value = supplier.get();
-                if (value != null) {
-                    return value;
-                }
-            }
-            // else no supplier in cache
-            // or a supplier that returned null (could be a cleared CacheValue
-            // or a Factory that wasn't successful in installing the CacheValue)
-
-            // lazily construct a Factory
-            if (factory == null) {
-                factory = new Factory(key, parameter, subKey, valuesMap);
-            }
-
-            if (supplier == null) {
-                supplier = valuesMap.putIfAbsent(subKey, factory);
-                if (supplier == null) {
-                    // successfully installed Factory
-                    supplier = factory;
-                }
-                // else retry with winning supplier
-            } else {
-                if (valuesMap.replace(subKey, supplier, factory)) {
-                    // successfully replaced
-                    // cleared CacheEntry / unsuccessful Factory
-                    // with our Factory
-                    supplier = factory;
-                } else {
-                    // retry with current supplier
-                    supplier = valuesMap.get(subKey);
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks whether the specified non-null value is already present in this
-     * {@code WeakCache}. The check is made using identity comparison regardless
-     * of whether value's class overrides {@link Object#equals} or not.
-     *
-     * @param value the non-null value to check
-     * @return true if given {@code value} is already cached
-     * @throws NullPointerException if value is null
-     */
-    public boolean containsValue(V value) {
-        Objects.requireNonNull(value);
-
-        expungeStaleEntries();
-        return reverseMap.containsKey(new LookupValue<>(value));
-    }
-
-    /**
-     * Returns the current number of cached entries that
-     * can decrease over time when keys/values are GC-ed.
-     */
-    public int size() {
-        expungeStaleEntries();
-        return reverseMap.size();
-    }
-
-    @SuppressWarnings("unchecked") // refQueue.poll actually returns CacheKey<K>
-    private void expungeStaleEntries() {
-        CacheKey<K> cacheKey;
-        while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) {
-            cacheKey.expungeFrom(map, reverseMap);
-        }
-    }
-
-    /**
-     * A factory {@link Supplier} that implements the lazy synchronized
-     * construction of the value and installment of it into the cache.
-     */
-    private final class Factory implements Supplier<V> {
-
-        private final K key;
-        private final P parameter;
-        private final Object subKey;
-        private final ConcurrentMap<Object, Supplier<V>> valuesMap;
-
-        Factory(K key, P parameter, Object subKey,
-                ConcurrentMap<Object, Supplier<V>> valuesMap) {
-            this.key = key;
-            this.parameter = parameter;
-            this.subKey = subKey;
-            this.valuesMap = valuesMap;
-        }
-
-        @Override
-        public synchronized V get() { // serialize access
-            // re-check
-            Supplier<V> supplier = valuesMap.get(subKey);
-            if (supplier != this) {
-                // something changed while we were waiting:
-                // might be that we were replaced by a CacheValue
-                // or were removed because of failure ->
-                // return null to signal WeakCache.get() to retry
-                // the loop
-                return null;
-            }
-            // else still us (supplier == this)
-
-            // create new value
-            V value = null;
-            try {
-                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
-            } finally {
-                if (value == null) { // remove us on failure
-                    valuesMap.remove(subKey, this);
-                }
-            }
-            // the only path to reach here is with non-null value
-            assert value != null;
-
-            // wrap value with CacheValue (WeakReference)
-            CacheValue<V> cacheValue = new CacheValue<>(value);
-
-            // try replacing us with CacheValue (this should always succeed)
-            if (valuesMap.replace(subKey, this, cacheValue)) {
-                // put also in reverseMap
-                reverseMap.put(cacheValue, Boolean.TRUE);
-            } else {
-                throw new AssertionError("Should not reach here");
-            }
-
-            // successfully replaced us with new CacheValue -> return the value
-            // wrapped by it
-            return value;
-        }
-    }
-
-    /**
-     * Common type of value suppliers that are holding a referent.
-     * The {@link #equals} and {@link #hashCode} of implementations is defined
-     * to compare the referent by identity.
-     */
-    private interface Value<V> extends Supplier<V> {}
-
-    /**
-     * An optimized {@link Value} used to look-up the value in
-     * {@link WeakCache#containsValue} method so that we are not
-     * constructing the whole {@link CacheValue} just to look-up the referent.
-     */
-    private static final class LookupValue<V> implements Value<V> {
-        private final V value;
-
-        LookupValue(V value) {
-            this.value = value;
-        }
-
-        @Override
-        public V get() {
-            return value;
-        }
-
-        @Override
-        public int hashCode() {
-            return System.identityHashCode(value); // compare by identity
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return obj == this ||
-                   obj instanceof Value &&
-                   this.value == ((Value<?>) obj).get();  // compare by identity
-        }
-    }
-
-    /**
-     * A {@link Value} that weakly references the referent.
-     */
-    private static final class CacheValue<V>
-        extends WeakReference<V> implements Value<V>
-    {
-        private final int hash;
-
-        CacheValue(V value) {
-            super(value);
-            this.hash = System.identityHashCode(value); // compare by identity
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            V value;
-            return obj == this ||
-                   obj instanceof Value &&
-                   // cleared CacheValue is only equal to itself
-                   (value = get()) != null &&
-                   value == ((Value<?>) obj).get(); // compare by identity
-        }
-    }
-
-    /**
-     * CacheKey containing a weakly referenced {@code key}. It registers
-     * itself with the {@code refQueue} so that it can be used to expunge
-     * the entry when the {@link WeakReference} is cleared.
-     */
-    private static final class CacheKey<K> extends WeakReference<K> {
-
-        // a replacement for null keys
-        private static final Object NULL_KEY = new Object();
-
-        static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
-            return key == null
-                   // null key means we can't weakly reference it,
-                   // so we use a NULL_KEY singleton as cache key
-                   ? NULL_KEY
-                   // non-null key requires wrapping with a WeakReference
-                   : new CacheKey<>(key, refQueue);
-        }
-
-        private final int hash;
-
-        private CacheKey(K key, ReferenceQueue<K> refQueue) {
-            super(key, refQueue);
-            this.hash = System.identityHashCode(key);  // compare by identity
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public boolean equals(Object obj) {
-            K key;
-            return obj == this ||
-                   obj != null &&
-                   obj.getClass() == this.getClass() &&
-                   // cleared CacheKey is only equal to itself
-                   (key = this.get()) != null &&
-                   // compare key by identity
-                   key == ((CacheKey<K>) obj).get(); // Cast is safe from getClass check
-        }
-
-        void expungeFrom(ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map,
-                         ConcurrentMap<?, Boolean> reverseMap) {
-            // removing just by key is always safe here because after a CacheKey
-            // is cleared and enqueue-ed it is only equal to itself
-            // (see equals method)...
-            ConcurrentMap<?, ?> valuesMap = map.remove(this);
-            // remove also from reverseMap if needed
-            if (valuesMap != null) {
-                for (Object cacheValue : valuesMap.values()) {
-                    reverseMap.remove(cacheValue);
-                }
-            }
-        }
-    }
-}
--- a/src/java.base/share/classes/java/net/InetAddress.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,10 @@
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Objects;
-import java.util.ServiceLoader;
+import java.util.Scanner;
 import java.security.AccessController;
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.ObjectStreamException;
 import java.io.ObjectStreamField;
 import java.io.IOException;
@@ -49,7 +51,6 @@
 import sun.security.action.*;
 import sun.net.InetAddressCachePolicy;
 import sun.net.util.IPAddressUtil;
-import sun.net.spi.nameservice.*;
 
 /**
  * This class represents an Internet Protocol (IP) address.
@@ -207,6 +208,7 @@
     /* Specify address family preference */
     static transient boolean preferIPv6Address = false;
 
+
     static class InetAddressHolder {
         /**
          * Reserve the original application specified hostname.
@@ -279,7 +281,7 @@
     }
 
     /* Used to store the name service provider */
-    private static List<NameService> nameServices = null;
+    private static transient NameService nameService = null;
 
     /* Used to store the best available hostname */
     private transient String canonicalHostName = null;
@@ -623,7 +625,6 @@
      */
     private static String getHostFromNameService(InetAddress addr, boolean check) {
         String host = null;
-        for (NameService nameService : nameServices) {
             try {
                 // first lookup the hostname
                 host = nameService.getHostByAddr(addr.getAddress());
@@ -657,18 +658,12 @@
                     host = addr.getHostAddress();
                     return host;
                 }
-
-                break;
-
             } catch (SecurityException e) {
                 host = addr.getHostAddress();
-                break;
             } catch (UnknownHostException e) {
                 host = addr.getHostAddress();
                 // let next provider resolve the hostname
             }
-        }
-
         return host;
     }
 
@@ -860,88 +855,287 @@
         }
     }
 
-    static InetAddressImpl  impl;
+    /**
+     * NameService provides host and address lookup service
+     *
+     * @since 9
+     */
+    private interface NameService {
+
+        /**
+         * Lookup a host mapping by name. Retrieve the IP addresses
+         * associated with a host
+         *
+         * @param host the specified hostname
+         * @return array of IP addresses for the requested host
+         * @throws UnknownHostException
+         *             if no IP address for the {@code host} could be found
+         */
+        InetAddress[] lookupAllHostAddr(String host)
+                throws UnknownHostException;
 
-    private static NameService createNSProvider(String provider) {
-        if (provider == null)
-            return null;
+        /**
+         * Lookup the host corresponding to the IP address provided
+         *
+         * @param addr byte array representing an IP address
+         * @return {@code String} representing the host name mapping
+         * @throws UnknownHostException
+         *             if no host found for the specified IP address
+         */
+        String getHostByAddr(byte[] addr) throws UnknownHostException;
 
-        NameService nameService = null;
-        if (provider.equals("default")) {
-            // initialize the default name service
-            nameService = new NameService() {
+    }
+
+    /**
+     * The default NameService implementation, which delegates to the underlying
+     * OS network libraries to resolve host address mappings.
+     *
+     * @since 9
+     */
+    private static final class PlatformNameService implements NameService {
+
                 public InetAddress[] lookupAllHostAddr(String host)
                     throws UnknownHostException {
+
                     return impl.lookupAllHostAddr(host);
-                }
-                public String getHostByAddr(byte[] addr)
-                    throws UnknownHostException {
-                    return impl.getHostByAddr(addr);
+
+                            }
+
+        public String getHostByAddr(byte[] addr) throws UnknownHostException {
+
+            return impl.getHostByAddr(addr);
+
+        }
+
+    }
+
+    /**
+     * The HostsFileNameService provides host address mapping
+     * by reading the entries in a hosts file, which is specified by
+     * {@code jdk.net.hosts.file} system property
+     *
+     * <p>The file format is that which corresponds with the /etc/hosts file
+     * IP Address host alias list.
+     *
+     * <p>When the file lookup is enabled it replaces the default NameService
+     * implementation
+     *
+     * @since 9
+     */
+    private static final class HostsFileNameService implements NameService {
+
+        private final String hostsFile;
+
+        public HostsFileNameService (String hostsFileName) {
+            this.hostsFile = hostsFileName;
+        }
+
+        private  String addrToString(byte addr[]) {
+          String stringifiedAddress = null;
+
+            if (addr.length == Inet4Address.INADDRSZ) {
+                stringifiedAddress = Inet4Address.numericToTextFormat(addr);
+            } else { // treat as an IPV6 jobby
+                byte[] newAddr
+                    = IPAddressUtil.convertFromIPv4MappedAddress(addr);
+                if (newAddr != null) {
+                   stringifiedAddress = Inet4Address.numericToTextFormat(addr);
+                } else {
+                    stringifiedAddress = Inet6Address.numericToTextFormat(addr);
                 }
-            };
-        } else {
-            final String providerName = provider;
-            try {
-                nameService = java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedExceptionAction<>() {
-                        public NameService run() {
-                            Iterator<NameServiceDescriptor> itr =
-                                ServiceLoader.load(NameServiceDescriptor.class)
-                                    .iterator();
-                            while (itr.hasNext()) {
-                                NameServiceDescriptor nsd = itr.next();
-                                if (providerName.
-                                    equalsIgnoreCase(nsd.getType()+","
-                                        +nsd.getProviderName())) {
-                                    try {
-                                        return nsd.createNameService();
-                                    } catch (Exception e) {
-                                        e.printStackTrace();
-                                        System.err.println(
-                                            "Cannot create name service:"
-                                             +providerName+": " + e);
-                                    }
+            }
+            return stringifiedAddress;
+        }
+
+        /**
+         * Lookup the host name  corresponding to the IP address provided.
+         * Search the configured host file a host name corresponding to
+         * the specified IP address.
+         *
+         * @param addr byte array representing an IP address
+         * @return {@code String} representing the host name mapping
+         * @throws UnknownHostException
+         *             if no host found for the specified IP address
+         */
+        @Override
+        public String getHostByAddr(byte[] addr) throws UnknownHostException {
+            String hostEntry;
+            String host = null;
+
+            String addrString = addrToString(addr);
+            try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) {
+                while (hostsFileScanner.hasNextLine()) {
+                    hostEntry = hostsFileScanner.nextLine();
+                    if (!hostEntry.startsWith("#")) {
+                        hostEntry = removeComments(hostEntry);
+                        if (hostEntry.contains(addrString)) {
+                            host = extractHost(hostEntry, addrString);
+                            if (host != null) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            } catch (FileNotFoundException e) {
+                throw new UnknownHostException("Unable to resolve address "
+                        + addrString + " as hosts file " + hostsFile
+                        + " not found ");
+            }
+
+            if ((host == null) || (host.equals("")) || (host.equals(" "))) {
+                throw new UnknownHostException("Requested address "
+                        + addrString
+                        + " resolves to an invalid entry in hosts file "
+                        + hostsFile);
+            }
+            return host;
+        }
+
+
+        /**
+         * <p>Lookup a host mapping by name. Retrieve the IP addresses
+         * associated with a host.
+         *
+         * <p>Search the configured hosts file for the addresses assocaited with
+         * with the specified host name.
+         *
+         * @param host the specified hostname
+         * @return array of IP addresses for the requested host
+         * @throws UnknownHostException
+         *             if no IP address for the {@code host} could be found
+         */
+
+        public InetAddress[] lookupAllHostAddr(String host)
+                throws UnknownHostException {
+            String hostEntry;
+            String addrStr = null;
+            InetAddress[] res = null;
+            byte addr[] = new byte[4];
+            ArrayList<InetAddress> inetAddresses = null;
+
+            // lookup the file and create a list InetAddress for the specfied host
+            try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) {
+                while (hostsFileScanner.hasNextLine()) {
+                    hostEntry = hostsFileScanner.nextLine();
+                    if (!hostEntry.startsWith("#")) {
+                        hostEntry = removeComments(hostEntry);
+                        if (hostEntry.contains(host)) {
+                            addrStr = extractHostAddr(hostEntry, host);
+                            if ((addrStr != null) && (!addrStr.equals(""))) {
+                                addr = createAddressByteArray(addrStr);
+                                if (inetAddresses == null) {
+                                    inetAddresses = new ArrayList<>(1);
+                                }
+                                if (addr != null) {
+                                    inetAddresses.add(InetAddress.getByAddress(host, addr));
                                 }
                             }
-
-                            return null;
                         }
                     }
-                );
-            } catch (java.security.PrivilegedActionException e) {
+                }
+            } catch (FileNotFoundException e) {
+                throw new UnknownHostException("Unable to resolve host " + host
+                        + " as hosts file " + hostsFile + " not found ");
+            }
+
+            if (inetAddresses != null) {
+                res = inetAddresses.toArray(new InetAddress[inetAddresses.size()]);
+            } else {
+                throw new UnknownHostException("Unable to resolve host " + host
+                        + " in hosts file " + hostsFile);
             }
+            return res;
+        }
+
+        private String removeComments(String hostsEntry) {
+            String filteredEntry = hostsEntry;
+            int hashIndex;
+
+            if ((hashIndex = hostsEntry.indexOf("#")) != -1) {
+                filteredEntry = hostsEntry.substring(0, hashIndex);
+            }
+            return filteredEntry;
+        }
+
+        private byte [] createAddressByteArray(String addrStr) {
+            byte[] addrArray;
+            // check if IPV4 address - most likely
+            addrArray = IPAddressUtil.textToNumericFormatV4(addrStr);
+            if (addrArray == null) {
+                addrArray = IPAddressUtil.textToNumericFormatV6(addrStr);
+            }
+            return addrArray;
         }
 
-        return nameService;
+        /** host to ip address mapping */
+        private String extractHostAddr(String hostEntry, String host) {
+            String[] mapping = hostEntry.split("\\s+");
+            String hostAddr = null;
+
+            if (mapping.length >= 2) {
+                // look at the host aliases
+                for (int i = 1; i < mapping.length; i++) {
+                    if (mapping[i].equalsIgnoreCase(host)) {
+                        hostAddr = mapping[0];
+                    }
+                }
+            }
+            return hostAddr;
+        }
+
+        /**
+         * IP Address to host mapping
+         * use first host alias in list
+         */
+        private String extractHost(String hostEntry, String addrString) {
+            String[] mapping = hostEntry.split("\\s+");
+            String host = null;
+
+            if (mapping.length >= 2) {
+                if (mapping[0].equalsIgnoreCase(addrString)) {
+                    host = mapping[1];
+                }
+            }
+            return host;
+        }
     }
 
+    static final InetAddressImpl  impl;
+
     static {
         // create the impl
         impl = InetAddressImplFactory.create();
 
-        // get name service if provided and requested
-        String provider = null;;
-        String propPrefix = "sun.net.spi.nameservice.provider.";
-        int n = 1;
-        nameServices = new ArrayList<>();
-        provider = AccessController.doPrivileged(
-                new GetPropertyAction(propPrefix + n));
-        while (provider != null) {
-            NameService ns = createNSProvider(provider);
-            if (ns != null)
-                nameServices.add(ns);
-
-            n++;
-            provider = AccessController.doPrivileged(
-                    new GetPropertyAction(propPrefix + n));
+        // create name service
+        nameService = createNameService();
         }
 
-        // if not designate any name services provider,
-        // create a default one
-        if (nameServices.size() == 0) {
-            NameService ns = createNSProvider("default");
-            nameServices.add(ns);
+    /**
+     * Create an instance of the NameService interface based on
+     * the setting of the {@codejdk.net.hosts.file} system property.
+     *
+     * <p>The default NameService is the PlatformNameService, which typically
+     * delegates name and address resolution calls to the underlying
+     * OS network libraries.
+     *
+     * <p> A HostsFileNameService is created if the {@code jdk.net.hosts.file}
+     * system property is set. If the specified file doesn't exist, the name or
+     * address lookup will result in an UnknownHostException. Thus, non existent
+     * hosts file is handled as if the file is empty.
+     *
+     * @return a NameService
+     */
+    private static NameService createNameService() {
+
+        String hostsFileName = AccessController
+                .doPrivileged(new GetPropertyAction("jdk.net.hosts.file"));
+        NameService theNameService;
+        if (hostsFileName != null) {
+            theNameService = new HostsFileNameService(hostsFileName);
+        } else {
+            theNameService = new PlatformNameService();
         }
+        return theNameService;
     }
 
     /**
@@ -1286,20 +1480,16 @@
         InetAddress[] addresses = null;
         UnknownHostException ex = null;
 
-        for (NameService nameService : nameServices) {
             try {
                 addresses = nameService.lookupAllHostAddr(host);
-                break;
             } catch (UnknownHostException uhe) {
                 if (host.equalsIgnoreCase("localhost")) {
                     addresses = new InetAddress[] { impl.loopbackAddress() };
-                    break;
                 }
                 else {
                     ex = uhe;
                 }
             }
-        }
 
         if (addresses == null) {
             throw ex == null ? new UnknownHostException(host) : ex;
--- a/src/java.base/share/classes/java/nio/Buffer.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/nio/Buffer.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,9 @@
 
 package java.nio;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 import java.util.Spliterator;
-import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * A container for data of a specific primitive type.
@@ -188,7 +189,15 @@
     private int limit;
     private int capacity;
 
-    // Used only by direct buffers
+    // Used by heap byte buffers or direct buffers with Unsafe access
+    // For heap byte buffers this field will be the address relative to the
+    // array base address and offset into that array. The address might
+    // not align on a word boundary for slices, nor align at a long word
+    // (8 byte) boundary for byte[] allocations on 32-bit systems.
+    // For direct buffers it is the start address of the memory region. The
+    // address might not align on a word boundary for slices, nor when created
+    // using JNI, see NewDirectByteBuffer(void*, long).
+    // Should ideally be declared final
     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
     long address;
 
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -140,6 +140,7 @@
         att = null;
 #else[rw]
         super(cap);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -180,6 +181,7 @@
         att = null;
 #else[rw]
         super(cap, addr, fd, unmapper);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -200,6 +202,7 @@
         att = db;
 #else[rw]
         super(db, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -213,6 +216,15 @@
         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
     }
 
+#if[byte]
+    public $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Direct$Type$Buffer$RW$$BO$(this,
                                               this.markValue(),
--- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,9 @@
         super(cap, lim);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
@@ -87,6 +90,9 @@
         super(buf, off, len);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     protected Heap$Type$Buffer$RW$($type$[] buf,
@@ -103,6 +109,9 @@
         super(buf, mark, pos, lim, cap, off);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset + off;
+#end[byte]
     }
 
     public $Type$Buffer slice() {
@@ -114,6 +123,20 @@
                                         this.position() + offset);
     }
 
+#if[byte]
+    $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        rem,
+                                        rem,
+                                        pos + offset);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Heap$Type$Buffer$RW$(hb,
                                         this.markValue(),
@@ -144,7 +167,7 @@
 
 #if[byte]
     private long byteOffset(long i) {
-        return arrayBaseOffset + i + offset;
+        return address + i;
     }
 #end[byte]
 
--- a/src/java.base/share/classes/java/nio/StringCharBuffer.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
         if ((start < 0) || (start > n) || (end < start) || (end > n))
             throw new IndexOutOfBoundsException();
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer slice() {
@@ -58,6 +59,7 @@
                              int offset) {
         super(mark, pos, limit, cap, null, offset);
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer duplicate() {
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -269,7 +269,7 @@
     //
     final $type$[] hb;                  // Non-null only for heap buffers
     final int offset;
-    boolean isReadOnly;                 // Valid only for heap buffers
+    boolean isReadOnly;
 
     // Creates a new buffer with the given mark, position, limit, capacity,
     // backing array, and array offset
@@ -530,6 +530,10 @@
      * it will be read-only if, and only if, this buffer is read-only.  </p>
      *
      * @return  The new $type$ buffer
+#if[byte]
+     *
+     * @see #alignedSlice(int)
+#end[byte]
      */
     public abstract $Type$Buffer slice();
 
@@ -1611,6 +1615,143 @@
         return this;
     }
 
+    /**
+     * Returns the memory address, pointing to the byte at the given index,
+     * modulus the given unit size.
+     *
+     * <p> A return value greater than zero indicates the address of the byte at
+     * the index is misaligned for the unit size, and the value's quantity
+     * indicates how much the index should be rounded up or down to locate a
+     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
+     * that the address of the byte at the index is aligned for the unit size.
+     *
+     * @apiNote
+     * This method may be utilized to determine if unit size bytes from an
+     * index can be accessed atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  index
+     *         The index to query for alignment offset, must be non-negative, no
+     *         upper bounds check is performed
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The indexed byte's memory address modulus the unit size
+     *
+     * @throws IllegalArgumentException
+     *         If the index is negative or the unit size is not a power of
+     *         {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable alignment offset
+     *         values for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignedSlice(int)
+     * @since 9
+     */
+    public final int alignmentOffset(int index, int unitSize) {
+        if (index < 0)
+            throw new IllegalArgumentException("Index less than zero: " + index);
+        if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+            throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+        if (unitSize > 8 && !isDirect())
+            throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+        return (int) ((address + index) % unitSize);
+    }
+
+    /**
+     * Creates a new byte buffer whose content is a shared and aligned
+     * subsequence of this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position rounded up to the index of the nearest aligned byte for the
+     * given unit size, and end at this buffer's limit rounded down to the index
+     * of the nearest aligned byte for the given unit size.
+     * If rounding results in out-of-bound values then the new buffer's capacity
+     * and limit will be zero.  If rounding is within bounds the following
+     * expressions will be true for a new buffer {@code nb} and unit size
+     * {@code unitSize}:
+     * <pre>{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }</pre>
+     *
+     * <p> Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer or fewer subject to
+     * alignment, its mark will be undefined, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @apiNote
+     * This method may be utilized to create a new buffer where unit size bytes
+     * from index, that is a multiple of the unit size, may be accessed
+     * atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The new byte buffer
+     *
+     * @throws IllegalArgumentException
+     *         If the unit size not a power of {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable aligned slices
+     *         for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignmentOffset(int, int)
+     * @see #slice()
+     * @since 9
+     */
+    public final ByteBuffer alignedSlice(int unitSize) {
+        int pos = position();
+        int lim = limit();
+
+        int pos_mod = alignmentOffset(pos, unitSize);
+        int lim_mod = alignmentOffset(lim, unitSize);
+
+        // Round up the position to align with unit size
+        int aligned_pos = (pos_mod > 0)
+            ? pos + (unitSize - pos_mod)
+            : pos;
+
+        // Round down the limit to align with unit size
+        int aligned_lim = lim - lim_mod;
+
+        if (aligned_pos > lim || aligned_lim < pos) {
+            aligned_pos = aligned_lim = pos;
+        }
+
+        return slice(aligned_pos, aligned_lim);
+    }
+
+    abstract ByteBuffer slice(int pos, int lim);
+
     // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
     //
     abstract byte _get(int i);                          // package-private
--- a/src/java.base/share/classes/java/text/DateFormatSymbols.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/text/DateFormatSymbols.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,6 @@
 import java.util.Locale;
 import java.util.Objects;
 import java.util.ResourceBundle;
-import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import sun.util.locale.provider.LocaleProviderAdapter;
@@ -147,6 +146,12 @@
     }
 
     /**
+     * Constructs an uninitialized DateFormatSymbols.
+     */
+    private DateFormatSymbols(boolean flag) {
+    }
+
+    /**
      * Era strings. For example: "AD" and "BC".  An array of 2 strings,
      * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
      * @serial
@@ -679,54 +684,80 @@
      */
     transient volatile int cachedHashCode;
 
-    private void initializeData(Locale desiredLocale) {
-        locale = desiredLocale;
-
-        // Copy values of a cached instance if any.
+    /**
+     * Initializes this DateFormatSymbols with the locale data. This method uses
+     * a cached DateFormatSymbols instance for the given locale if available. If
+     * there's no cached one, this method creates an uninitialized instance and
+     * populates its fields from the resource bundle for the locale, and caches
+     * the instance. Note: zoneStrings isn't initialized in this method.
+     */
+    private void initializeData(Locale locale) {
         SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
         DateFormatSymbols dfs;
-        if (ref != null && (dfs = ref.get()) != null) {
-            copyMembers(dfs, this);
-            return;
+        if (ref == null || (dfs = ref.get()) == null) {
+            if (ref != null) {
+                // Remove the empty SoftReference
+                cachedInstances.remove(locale, ref);
+            }
+            dfs = new DateFormatSymbols(false);
+
+            // Initialize the fields from the ResourceBundle for locale.
+            LocaleProviderAdapter adapter
+                = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
+            // Avoid any potential recursions
+            if (!(adapter instanceof ResourceBundleBasedAdapter)) {
+                adapter = LocaleProviderAdapter.getResourceBundleBased();
+            }
+            ResourceBundle resource
+                = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
+
+            dfs.locale = locale;
+            // JRE and CLDR use different keys
+            // JRE: Eras, short.Eras and narrow.Eras
+            // CLDR: long.Eras, Eras and narrow.Eras
+            if (resource.containsKey("Eras")) {
+                dfs.eras = resource.getStringArray("Eras");
+            } else if (resource.containsKey("long.Eras")) {
+                dfs.eras = resource.getStringArray("long.Eras");
+            } else if (resource.containsKey("short.Eras")) {
+                dfs.eras = resource.getStringArray("short.Eras");
+            }
+            dfs.months = resource.getStringArray("MonthNames");
+            dfs.shortMonths = resource.getStringArray("MonthAbbreviations");
+            dfs.ampms = resource.getStringArray("AmPmMarkers");
+            dfs.localPatternChars = resource.getString("DateTimePatternChars");
+
+            // Day of week names are stored in a 1-based array.
+            dfs.weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
+            dfs.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
+
+            // Put dfs in the cache
+            ref = new SoftReference<>(dfs);
+            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
+            if (x != null) {
+                DateFormatSymbols y = x.get();
+                if (y == null) {
+                    // Replace the empty SoftReference with ref.
+                    cachedInstances.replace(locale, x, ref);
+                } else {
+                    ref = x;
+                    dfs = y;
+                }
+            }
+            // If the bundle's locale isn't the target locale, put another cache
+            // entry for the bundle's locale.
+            Locale bundleLocale = resource.getLocale();
+            if (!bundleLocale.equals(locale)) {
+                SoftReference<DateFormatSymbols> z
+                    = cachedInstances.putIfAbsent(bundleLocale, ref);
+                if (z != null && z.get() == null) {
+                    cachedInstances.replace(bundleLocale, z, ref);
+                }
+            }
         }
 
-        // Initialize the fields from the ResourceBundle for locale.
-        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
-        // Avoid any potential recursions
-        if (!(adapter instanceof ResourceBundleBasedAdapter)) {
-            adapter = LocaleProviderAdapter.getResourceBundleBased();
-        }
-        ResourceBundle resource = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
-
-        // JRE and CLDR use different keys
-        // JRE: Eras, short.Eras and narrow.Eras
-        // CLDR: long.Eras, Eras and narrow.Eras
-        if (resource.containsKey("Eras")) {
-            eras = resource.getStringArray("Eras");
-        } else if (resource.containsKey("long.Eras")) {
-            eras = resource.getStringArray("long.Eras");
-        } else if (resource.containsKey("short.Eras")) {
-            eras = resource.getStringArray("short.Eras");
-        }
-        months = resource.getStringArray("MonthNames");
-        shortMonths = resource.getStringArray("MonthAbbreviations");
-        ampms = resource.getStringArray("AmPmMarkers");
-        localPatternChars = resource.getString("DateTimePatternChars");
-
-        // Day of week names are stored in a 1-based array.
-        weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
-        shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
-
-        // Put a clone in the cache
-        ref = new SoftReference<>((DateFormatSymbols)this.clone());
-        SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
-        if (x != null) {
-            DateFormatSymbols y = x.get();
-            if (y == null) {
-                // Replace the empty SoftReference with ref.
-                cachedInstances.put(locale, ref);
-            }
-        }
+        // Copy the field values from dfs to this instance.
+        copyMembers(dfs, this);
     }
 
     private static String[] toOneBasedArray(String[] src) {
@@ -808,12 +839,14 @@
 
     /**
      * Clones all the data members from the source DateFormatSymbols to
-     * the target DateFormatSymbols. This is only for subclasses.
+     * the target DateFormatSymbols.
+     *
      * @param src the source DateFormatSymbols.
      * @param dst the target DateFormatSymbols.
      */
     private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
     {
+        dst.locale = src.locale;
         dst.eras = Arrays.copyOf(src.eras, src.eras.length);
         dst.months = Arrays.copyOf(src.months, src.months.length);
         dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,12 +61,17 @@
  */
 package java.time.chrono;
 
+import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
+import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
+
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalTime;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.ResolverStyle;
 import java.time.format.TextStyle;
@@ -712,6 +717,59 @@
         return new ChronoPeriodImpl(this, years, months, days);
     }
 
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the proleptic-year,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param prolepticYear the chronology proleptic-year
+     * @param month the chronology month-of-year
+     * @param dayOfMonth the chronology day-of-month
+     * @param hour the hour-of-day, from 0 to 23
+     * @param minute the minute-of-hour, from 0 to 59
+     * @param second the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if any of the values are out of range
+     * @since 9
+     */
+     public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+        Objects.requireNonNull(zoneOffset, "zoneOffset");
+        HOUR_OF_DAY.checkValidValue(hour);
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        SECOND_OF_MINUTE.checkValidValue(second);
+        long daysInSec = Math.multiplyExact(date(prolepticYear, month, dayOfMonth).toEpochDay(), 86400);
+        long timeinSec = (hour * 60 + minute) * 60 + second;
+        return Math.addExact(daysInSec, timeinSec - zoneOffset.getTotalSeconds());
+    }
+
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the era, year-of-era,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param era  the era of the correct type for the chronology, not null
+     * @param yearOfEra the chronology year-of-era
+     * @param month the chronology month-of-year
+     * @param dayOfMonth the chronology day-of-month
+     * @param hour the hour-of-day, from 0 to 23
+     * @param minute the minute-of-hour, from 0 to 59
+     * @param second the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if any of the values are out of range
+     * @since 9
+     */
+     public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
+                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+        Objects.requireNonNull(era, "era");
+        return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
+    }
     //-----------------------------------------------------------------------
     /**
      * Compares this chronology to another chronology.
--- a/src/java.base/share/classes/java/time/chrono/IsoChronology.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/time/chrono/IsoChronology.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,14 +61,17 @@
  */
 package java.time.chrono;
 
-import java.io.InvalidObjectException;
 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
 import static java.time.temporal.ChronoField.ERA;
+import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
+import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
 import static java.time.temporal.ChronoField.YEAR;
 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
 
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.time.Clock;
@@ -79,8 +82,9 @@
 import java.time.Month;
 import java.time.Period;
 import java.time.Year;
+import java.time.ZonedDateTime;
 import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
 import java.time.format.ResolverStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalAccessor;
@@ -132,6 +136,8 @@
      */
     private static final long serialVersionUID = -1440403870442975015L;
 
+    private static final long DAYS_0000_TO_1970 = (146097 * 5L) - (30L * 365L + 7L); // taken from LocalDate
+
     /**
      * Restricted constructor.
      */
@@ -263,6 +269,94 @@
         return LocalDate.from(temporal);
     }
 
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the year,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param prolepticYear  the year, from MIN_YEAR to MAX_YEAR
+     * @param month  the month-of-year, from 1 to 12
+     * @param dayOfMonth  the day-of-month, from 1 to 31
+     * @param hour  the hour-of-day, from 0 to 23
+     * @param minute  the minute-of-hour, from 0 to 59
+     * @param second  the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if the value of any argument is out of range,
+     *         or if the day-of-month is invalid for the month-of-year
+     * @since 9
+     */
+     @Override
+     public long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                             int hour, int minute, int second, ZoneOffset zoneOffset) {
+        YEAR.checkValidValue(prolepticYear);
+        MONTH_OF_YEAR.checkValidValue(month);
+        DAY_OF_MONTH.checkValidValue(dayOfMonth);
+        HOUR_OF_DAY.checkValidValue(hour);
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        SECOND_OF_MINUTE.checkValidValue(second);
+        Objects.requireNonNull(zoneOffset, "zoneOffset");
+        if (dayOfMonth > 28) {
+            int dom = numberOfDaysOfMonth(prolepticYear, month);
+            if (dayOfMonth > dom) {
+                if (dayOfMonth == 29) {
+                    throw new DateTimeException("Invalid date 'February 29' as '" + prolepticYear + "' is not a leap year");
+                } else {
+                    throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
+                }
+            }
+        }
+
+        long totalDays = 0;
+        int timeinSec = 0;
+        totalDays += 365L * prolepticYear;
+        if (prolepticYear >= 0) {
+            totalDays += (prolepticYear + 3L) / 4 - (prolepticYear + 99L) / 100 + (prolepticYear + 399L) / 400;
+        } else {
+            totalDays -= prolepticYear / -4 - prolepticYear / -100 + prolepticYear / -400;
+        }
+        totalDays += (367 * month - 362) / 12;
+        totalDays += dayOfMonth - 1;
+        if (month > 2) {
+            totalDays--;
+            if (IsoChronology.INSTANCE.isLeapYear(prolepticYear) == false) {
+                totalDays--;
+            }
+        }
+        totalDays -= DAYS_0000_TO_1970;
+        timeinSec = (hour * 60 + minute ) * 60 + second;
+        return Math.addExact(Math.multiplyExact(totalDays, 86400L), timeinSec - zoneOffset.getTotalSeconds());
+     }
+
+    /**
+     * Gets the number of days for the given month in the given year.
+     *
+     * @param year the year to represent, from MIN_YEAR to MAX_YEAR
+     * @param month the month-of-year to represent, from 1 to 12
+     * @return the number of days for the given month in the given year
+     */
+    private int numberOfDaysOfMonth(int year, int month) {
+        int dom;
+        switch (month) {
+            case 2:
+                dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
+                break;
+            case 4:
+            case 6:
+            case 9:
+            case 11:
+                dom = 30;
+                break;
+            default:
+                dom = 31;
+                break;
+        }
+        return dom;
+    }
+
+
     /**
      * Obtains an ISO local date-time from another date-time object.
      * <p>
--- a/src/java.base/share/classes/java/time/temporal/ChronoField.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/time/temporal/ChronoField.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -270,6 +270,8 @@
      * In lenient mode the value is not validated. It is combined with
      * {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
      * the {AMPM_OF_DAY} value by 12.
+     * <p>
+     * See {@link #CLOCK_HOUR_OF_AMPM} for the related field that counts hours from 1 to 12.
      */
     HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
     /**
@@ -284,6 +286,8 @@
      * 0 to 12 in smart mode. In lenient mode the value is not validated.
      * The field is converted to an {@code HOUR_OF_AMPM} with the same value,
      * unless the value is 12, in which case it is converted to 0.
+     * <p>
+     * See {@link #HOUR_OF_AMPM} for the related field that counts hours from 0 to 11.
      */
     CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
     /**
@@ -299,12 +303,14 @@
      * {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
      * In lenient mode, any excess days are added to the parsed date, or
      * made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
+     * <p>
+     * See {@link #CLOCK_HOUR_OF_DAY} for the related field that counts hours from 1 to 24.
      */
     HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
     /**
      * The clock-hour-of-day.
      * <p>
-     * This counts the hour within the AM/PM, from 1 to 24.
+     * This counts the hour within the day, from 1 to 24.
      * This is the hour that would be observed on a 24-hour analog wall clock.
      * This field has the same meaning for all calendar systems.
      * <p>
@@ -313,6 +319,8 @@
      * 0 to 24 in smart mode. In lenient mode the value is not validated.
      * The field is converted to an {@code HOUR_OF_DAY} with the same value,
      * unless the value is 24, in which case it is converted to 0.
+     * <p>
+     * See {@link #HOUR_OF_DAY} for the related field that counts hours from 0 to 23.
      */
     CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
     /**
--- a/src/java.base/share/classes/java/util/Deque.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/Deque.java	Mon Apr 11 11:19:33 2016 -0700
@@ -174,7 +174,7 @@
  * that do allow null elements are strongly encouraged <i>not</i> to
  * take advantage of the ability to insert nulls.  This is so because
  * {@code null} is used as a special return value by various methods
- * to indicated that the deque is empty.
+ * to indicate that the deque is empty.
  *
  * <p>{@code Deque} implementations generally do not define
  * element-based versions of the {@code equals} and {@code hashCode}
--- a/src/java.base/share/classes/java/util/GregorianCalendar.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/GregorianCalendar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -424,7 +424,7 @@
      * DAY_OF_MONTH            1         1          28*         31
      * DAY_OF_YEAR             1         1         365*        366
      * DAY_OF_WEEK             1         1           7           7
-     * DAY_OF_WEEK_IN_MONTH   -1        -1           4*          6
+     * DAY_OF_WEEK_IN_MONTH    1         1           4*          6
      * AM_PM                   0         0           1           1
      * HOUR                    0         0          11          11
      * HOUR_OF_DAY             0         0          23          23
--- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Mon Apr 11 11:19:33 2016 -0700
@@ -480,7 +480,7 @@
     }
 
     static void lazySetNext(Completion c, Completion next) {
-        U.putOrderedObject(c, NEXT, next);
+        U.putObjectRelease(c, NEXT, next);
     }
 
     /**
@@ -583,9 +583,9 @@
      */
     final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
         if (a != null && a.stack != null) {
-            if (mode < 0 || a.result == null)
+            if (a.result == null)
                 a.cleanStack();
-            else
+            else if (mode >= 0)
                 a.postComplete();
         }
         if (result != null && stack != null) {
@@ -1107,9 +1107,9 @@
     final CompletableFuture<T> postFire(CompletableFuture<?> a,
                                         CompletableFuture<?> b, int mode) {
         if (b != null && b.stack != null) { // clean second source
-            if (mode < 0 || b.result == null)
+            if (b.result == null)
                 b.cleanStack();
-            else
+            else if (mode >= 0)
                 b.postComplete();
         }
         return postFire(a, mode);
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Mon Apr 11 11:19:33 2016 -0700
@@ -628,10 +628,14 @@
         volatile V val;
         volatile Node<K,V> next;
 
-        Node(int hash, K key, V val, Node<K,V> next) {
+        Node(int hash, K key, V val) {
             this.hash = hash;
             this.key = key;
             this.val = val;
+        }
+
+        Node(int hash, K key, V val, Node<K,V> next) {
+            this(hash, key, val);
             this.next = next;
         }
 
@@ -1024,8 +1028,7 @@
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
-                if (casTabAt(tab, i, null,
-                             new Node<K,V>(hash, key, value, null)))
+                if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
                     break;                   // no lock when adding to empty bin
             }
             else if ((fh = f.hash) == MOVED)
@@ -1048,8 +1051,7 @@
                                 }
                                 Node<K,V> pred = e;
                                 if ((e = e.next) == null) {
-                                    pred.next = new Node<K,V>(hash, key,
-                                                              value, null);
+                                    pred.next = new Node<K,V>(hash, key, value);
                                     break;
                                 }
                             }
@@ -1709,7 +1711,7 @@
                         Node<K,V> node = null;
                         try {
                             if ((val = mappingFunction.apply(key)) != null)
-                                node = new Node<K,V>(h, key, val, null);
+                                node = new Node<K,V>(h, key, val);
                         } finally {
                             setTabAt(tab, i, node);
                         }
@@ -1740,7 +1742,7 @@
                                         if (pred.next != null)
                                             throw new IllegalStateException("Recursive update");
                                         added = true;
-                                        pred.next = new Node<K,V>(h, key, val, null);
+                                        pred.next = new Node<K,V>(h, key, val);
                                     }
                                     break;
                                 }
@@ -1909,7 +1911,7 @@
                         try {
                             if ((val = remappingFunction.apply(key, null)) != null) {
                                 delta = 1;
-                                node = new Node<K,V>(h, key, val, null);
+                                node = new Node<K,V>(h, key, val);
                             }
                         } finally {
                             setTabAt(tab, i, node);
@@ -1951,8 +1953,7 @@
                                         if (pred.next != null)
                                             throw new IllegalStateException("Recursive update");
                                         delta = 1;
-                                        pred.next =
-                                            new Node<K,V>(h, key, val, null);
+                                        pred.next = new Node<K,V>(h, key, val);
                                     }
                                     break;
                                 }
@@ -2030,7 +2031,7 @@
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
-                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
+                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
                     delta = 1;
                     val = value;
                     break;
@@ -2065,8 +2066,7 @@
                                 if ((e = e.next) == null) {
                                     delta = 1;
                                     val = value;
-                                    pred.next =
-                                        new Node<K,V>(h, key, val, null);
+                                    pred.next = new Node<K,V>(h, key, val);
                                     break;
                                 }
                             }
@@ -2227,7 +2227,7 @@
     static final class ForwardingNode<K,V> extends Node<K,V> {
         final Node<K,V>[] nextTable;
         ForwardingNode(Node<K,V>[] tab) {
-            super(MOVED, null, null, null);
+            super(MOVED, null, null);
             this.nextTable = tab;
         }
 
@@ -2263,7 +2263,7 @@
      */
     static final class ReservationNode<K,V> extends Node<K,V> {
         ReservationNode() {
-            super(RESERVED, null, null, null);
+            super(RESERVED, null, null);
         }
 
         Node<K,V> find(int h, Object k) {
@@ -2690,12 +2690,12 @@
     }
 
     /**
-     * Returns a list on non-TreeNodes replacing those in given list.
+     * Returns a list of non-TreeNodes replacing those in given list.
      */
     static <K,V> Node<K,V> untreeify(Node<K,V> b) {
         Node<K,V> hd = null, tl = null;
         for (Node<K,V> q = b; q != null; q = q.next) {
-            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
+            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
             if (tl == null)
                 hd = p;
             else
@@ -2801,7 +2801,7 @@
          * Creates bin with initial set of nodes headed by b.
          */
         TreeBin(TreeNode<K,V> b) {
-            super(TREEBIN, null, null, null);
+            super(TREEBIN, null, null);
             this.first = b;
             TreeNode<K,V> r = null;
             for (TreeNode<K,V> x = b, next; x != null; x = next) {
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Mon Apr 11 11:19:33 2016 -0700
@@ -309,7 +309,7 @@
         }
 
         void lazySetNext(Node<E> val) {
-            U.putOrderedObject(this, NEXT, val);
+            U.putObjectRelease(this, NEXT, val);
         }
 
         boolean casNext(Node<E> cmp, Node<E> val) {
@@ -317,7 +317,7 @@
         }
 
         void lazySetPrev(Node<E> val) {
-            U.putOrderedObject(this, PREV, val);
+            U.putObjectRelease(this, PREV, val);
         }
 
         boolean casPrev(Node<E> cmp, Node<E> val) {
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Mon Apr 11 11:19:33 2016 -0700
@@ -198,7 +198,7 @@
     }
 
     static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putOrderedObject(node, NEXT, val);
+        U.putObjectRelease(node, NEXT, val);
     }
 
     static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
--- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Mon Apr 11 11:19:33 2016 -0700
@@ -239,7 +239,7 @@
      * 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
-     * putOrderedX to clear fields of the per-thread Nodes between
+     * putXRelease 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
@@ -376,7 +376,7 @@
                     for (int h = p.hash, spins = SPINS;;) {
                         Object v = p.match;
                         if (v != null) {
-                            U.putOrderedObject(p, MATCH, null);
+                            U.putObjectRelease(p, MATCH, null);
                             p.item = null;             // clear for next use
                             p.hash = h;
                             return v;
@@ -507,7 +507,7 @@
                 break;
             }
         }
-        U.putOrderedObject(p, MATCH, null);
+        U.putObjectRelease(p, MATCH, null);
         p.item = null;
         p.hash = h;
         return v;
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Mon Apr 11 11:19:33 2016 -0700
@@ -289,7 +289,7 @@
      * on to try or create other queues -- they block only when
      * creating and registering new queues. Because it is used only as
      * a spinlock, unlocking requires only a "releasing" store (using
-     * putOrderedInt).  The qlock is also used during termination
+     * putIntRelease).  The qlock is also used during termination
      * detection, in which case it is forced to a negative
      * non-lockable value.
      *
@@ -1071,7 +1071,7 @@
                         popped = true;
                         top = s;
                     }
-                    U.putOrderedInt(this, QLOCK, 0);
+                    U.putIntRelease(this, QLOCK, 0);
                 }
             }
             return popped;
@@ -1261,7 +1261,7 @@
                                         popped = true;
                                         top = s - 1;
                                     }
-                                    U.putOrderedInt(this, QLOCK, 0);
+                                    U.putIntRelease(this, QLOCK, 0);
                                     if (popped)
                                         return t;
                                 }
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Mon Apr 11 11:19:33 2016 -0700
@@ -92,7 +92,7 @@
     ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
                          AccessControlContext acc) {
         super(threadGroup, null, "aForkJoinWorkerThread");
-        U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
+        U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
         eraseThreadLocals(); // clear before registering
         this.pool = pool;
         this.workQueue = pool.registerWorker(this);
--- a/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Mon Apr 11 11:19:33 2016 -0700
@@ -174,7 +174,7 @@
                     if (t != null)
                         t.interrupt();
                 } finally { // final state
-                    U.putOrderedInt(this, STATE, INTERRUPTED);
+                    U.putIntRelease(this, STATE, INTERRUPTED);
                 }
             }
         } finally {
@@ -230,7 +230,7 @@
     protected void set(V v) {
         if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
             outcome = v;
-            U.putOrderedInt(this, STATE, NORMAL); // final state
+            U.putIntRelease(this, STATE, NORMAL); // final state
             finishCompletion();
         }
     }
@@ -248,7 +248,7 @@
     protected void setException(Throwable t) {
         if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
             outcome = t;
-            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
+            U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
             finishCompletion();
         }
     }
--- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1496,7 +1496,7 @@
                     else if (((c & CONSUME) != 0 ||
                               U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
                              U.compareAndSwapObject(a, i, x, null)) {
-                        U.putOrderedInt(this, HEAD, ++h);
+                        U.putIntRelease(this, HEAD, ++h);
                         U.getAndAddLong(this, DEMAND, -1L);
                         if ((w = waiter) != null)
                             signalWaiter(w);
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Mon Apr 11 11:19:33 2016 -0700
@@ -136,7 +136,7 @@
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
+        U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Mon Apr 11 11:19:33 2016 -0700
@@ -108,7 +108,7 @@
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putOrderedInt(this, VALUE, newValue);
+        U.putIntRelease(this, VALUE, newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Mon Apr 11 11:19:33 2016 -0700
@@ -136,7 +136,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putOrderedInt(array, checkedByteOffset(i), newValue);
+        U.putIntRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Mon Apr 11 11:19:33 2016 -0700
@@ -475,7 +475,7 @@
 
         public final void lazySet(T obj, int newValue) {
             accessCheck(obj);
-            U.putOrderedInt(obj, offset, newValue);
+            U.putIntRelease(obj, offset, newValue);
         }
 
         public final int get(T obj) {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -124,7 +124,7 @@
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putOrderedLong(this, VALUE, newValue);
+        U.putLongRelease(this, VALUE, newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Mon Apr 11 11:19:33 2016 -0700
@@ -135,7 +135,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putOrderedLong(array, checkedByteOffset(i), newValue);
+        U.putLongRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Mon Apr 11 11:19:33 2016 -0700
@@ -457,7 +457,7 @@
 
         public final void lazySet(T obj, long newValue) {
             accessCheck(obj);
-            U.putOrderedLong(obj, offset, newValue);
+            U.putLongRelease(obj, offset, newValue);
         }
 
         public final long get(T obj) {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Mon Apr 11 11:19:33 2016 -0700
@@ -103,7 +103,7 @@
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putOrderedObject(this, VALUE, newValue);
+        U.putObjectRelease(this, VALUE, newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Mon Apr 11 11:19:33 2016 -0700
@@ -147,7 +147,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putOrderedObject(array, checkedByteOffset(i), newValue);
+        U.putObjectRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Mon Apr 11 11:19:33 2016 -0700
@@ -426,7 +426,7 @@
         public final void lazySet(T obj, V newValue) {
             accessCheck(obj);
             valueCheck(newValue);
-            U.putOrderedObject(obj, offset, newValue);
+            U.putObjectRelease(obj, offset, newValue);
         }
 
         @SuppressWarnings("unchecked")
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java	Mon Apr 11 11:19:33 2016 -0700
@@ -39,6 +39,7 @@
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 import java.util.stream.Stream;
@@ -68,6 +69,10 @@
     // ServiceCatalog for the boot class loader
     private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog();
 
+    // ClassLoaderValue map for boot class loader
+    private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP =
+        new ConcurrentHashMap<>();
+
     /**
      * Returns the unnamed module for the boot loader.
      */
@@ -83,6 +88,13 @@
     }
 
     /**
+     * Returns the ClassLoaderValue map for the boot class loader.
+     */
+    public static ConcurrentHashMap<?, ?> getClassLoaderValueMap() {
+        return CLASS_LOADER_VALUE_MAP;
+    }
+
+    /**
      * Register a module with this class loader so that its classes (and
      * resources) become visible via this class loader.
      */
--- a/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java	Mon Apr 11 11:19:33 2016 -0700
@@ -86,8 +86,8 @@
 
     private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
         super(group, target, name, 0L, false);
-        UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
-        UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);
+        UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
+        UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
     }
 
     @Override
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Mon Apr 11 11:19:33 2016 -0700
@@ -33,6 +33,7 @@
 import java.net.URL;
 import java.security.AccessControlContext;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
 import jdk.internal.module.ServicesCatalog;
@@ -146,6 +147,12 @@
     ServicesCatalog createOrGetServicesCatalog(ClassLoader cl);
 
     /**
+     * Returns the ConcurrentHashMap used as a storage for ClassLoaderValue(s)
+     * associated with the given class loader, creating it if it doesn't already exist.
+     */
+    ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl);
+
+    /**
      * Returns a class loaded by the bootstrap class loader.
      */
     Class<?> findBootstrapClassOrNull(ClassLoader cl, String name);
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1457,25 +1457,7 @@
     @HotSpotIntrinsicCandidate
     public native void    putDoubleVolatile(Object o, long offset, double x);
 
-    /**
-     * Version of {@link #putObjectVolatile(Object, long, Object)}
-     * that does not guarantee immediate visibility of the store to
-     * other threads. This method is generally only useful if the
-     * underlying field is a Java volatile (or if an array cell, one
-     * that is otherwise only accessed using volatile accesses).
-     *
-     * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
-     */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedObject(Object o, long offset, Object x);
 
-    /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedInt(Object o, long offset, int x);
-
-    /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedLong(Object o, long offset, long x);
 
     /** Acquire version of {@link #getObjectVolatile(Object, long)} */
     @HotSpotIntrinsicCandidate
@@ -1531,6 +1513,16 @@
         return getDoubleVolatile(o, offset);
     }
 
+    /*
+      * Versions of {@link #putObjectVolatile(Object, long, Object)}
+      * that do not guarantee immediate visibility of the store to
+      * other threads. This method is generally only useful if the
+      * underlying field is a Java volatile (or if an array cell, one
+      * that is otherwise only accessed using volatile accesses).
+      *
+      * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
+      */
+
     /** Release version of {@link #putObjectVolatile(Object, long, Object)} */
     @HotSpotIntrinsicCandidate
     public final void putObjectRelease(Object o, long offset, Object x) {
--- a/src/java.base/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -86,8 +86,7 @@
     // see JDK-8044773
     exports jdk.net;
 
-    // These will move to a jdk.internal module via JEP-260
-    exports sun.misc;
+    // This will move to a jdk.internal module via JEP-260
     exports sun.reflect;
 
 
@@ -173,6 +172,7 @@
         java.xml,
         jdk.charsets,
         jdk.scripting.nashorn,
+        jdk.unsupported,
         jdk.vm.ci;
     exports jdk.internal.perf to
         java.desktop,
@@ -180,6 +180,8 @@
         jdk.jvmstat;
     exports jdk.internal.ref to
         java.desktop;
+    exports jdk.internal.vm.annotation to
+        jdk.unsupported;
     exports jdk.internal.util.jar to
         jdk.jartool;
     exports jdk.internal.vm to
@@ -190,8 +192,6 @@
     exports sun.net.dns to
         java.security.jgss,
         jdk.naming.dns;
-    exports sun.net.spi.nameservice to
-        jdk.naming.dns;
     exports sun.net.util to
         java.desktop,
         jdk.jconsole,
@@ -284,7 +284,6 @@
 
     // JDK-internal service types
     uses jdk.internal.logger.DefaultLoggerFinder;
-    uses sun.net.spi.nameservice.NameServiceDescriptor;
     uses sun.security.ssl.ClientKeyExchangeService;
     uses sun.util.spi.CalendarProvider;
     uses sun.util.locale.provider.LocaleDataMetaInfo;
--- a/src/java.base/share/classes/sun/misc/CRC16.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * The CRC-16 class calculates a 16 bit cyclic redundancy check of a set
- * of bytes. This error detecting code is used to determine if bit rot
- * has occurred in a byte stream.
- */
-
-public class CRC16 {
-
-    /** value contains the currently computed CRC, set it to 0 initally */
-    public int value;
-
-    public CRC16() {
-        value = 0;
-    }
-
-    /** update CRC with byte b */
-    public void update(byte aByte) {
-        int a, b;
-
-        a = (int) aByte;
-        for (int count = 7; count >=0; count--) {
-            a = a << 1;
-            b = (a >>> 8) & 1;
-            if ((value & 0x8000) != 0) {
-                value = ((value << 1) + b) ^ 0x1021;
-            } else {
-                value = (value << 1) + b;
-            }
-        }
-        value = value & 0xffff;
-        return;
-    }
-
-    /** reset CRC value to 0 */
-    public void reset() {
-        value = 0;
-    }
-}
--- a/src/java.base/share/classes/sun/misc/Cache.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.lang.ref.SoftReference;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-/**
- * Caches the collision list.
- */
-class CacheEntry {
-    int hash;
-    Object key;
-    CacheEntry next;
-    SoftReference<Object> value;
-
-    public CacheEntry() {
-        value = null;
-    }
-
-    public CacheEntry(Object o) {
-        value = new SoftReference<>(o);
-    }
-
-    public Object get() {
-        return value.get();
-    }
-
-    public void setThing(Object thing) {
-        value = new SoftReference<>(thing);
-    }
-}
-
-/**
- * The Cache class. Maps keys to values. Any object can be used as
- * a key and/or value.  This is very similar to the Hashtable
- * class, except that after putting an object into the Cache,
- * it is not guaranteed that a subsequent get will return it.
- * The Cache will automatically remove entries if memory is
- * getting tight and if the entry is not referenced from outside
- * the Cache.<p>
- *
- * To sucessfully store and retrieve objects from a hash table the
- * object used as the key must implement the hashCode() and equals()
- * methods.<p>
- *
- * This example creates a Cache of numbers. It uses the names of
- * the numbers as keys:
- * <pre>
- *      Cache numbers = new Cache();
- *      numbers.put("one", new Integer(1));
- *      numbers.put("two", new Integer(1));
- *      numbers.put("three", new Integer(1));
- * </pre>
- * To retrieve a number use:
- * <pre>
- *      Integer n = (Integer)numbers.get("two");
- *      if (n != null) {
- *          System.out.println("two = " + n);
- *      }
- * </pre>
- *
- * @see java.lang.Object#hashCode
- * @see java.lang.Object#equals
- * @deprecated Consider {@link java.util.LinkedHashMap} for LRU caches.
- */
-@Deprecated
-public
-    class Cache extends Dictionary<Object, Object> {
-    /**
-     * The hash table data.
-     */
-    private CacheEntry table[];
-
-    /**
-     * The total number of entries in the hash table.
-     */
-    private int count;
-
-    /**
-     * Rehashes the table when count exceeds this threshold.
-     */
-    private int threshold;
-
-    /**
-     * The load factor for the hashtable.
-     */
-    private float loadFactor;
-
-    private void init(int initialCapacity, float loadFactor) {
-        if ((initialCapacity <= 0) || (loadFactor <= 0.0)) {
-            throw new IllegalArgumentException();
-        }
-        this.loadFactor = loadFactor;
-        table = new CacheEntry[initialCapacity];
-        threshold = (int) (initialCapacity * loadFactor);
-    }
-
-    /**
-     * Constructs a new, empty Cache with the specified initial
-     * capacity and the specified load factor.
-     * @param initialCapacity the initial number of buckets
-     * @param loadFactor a number between 0.0 and 1.0, it defines
-     *          the threshold for rehashing the Cache into
-     *          a bigger one.
-     * @exception IllegalArgumentException If the initial capacity
-     * is less than or equal to zero.
-     * @exception IllegalArgumentException If the load factor is
-     * less than or equal to zero.
-     */
-    public Cache (int initialCapacity, float loadFactor) {
-        init(initialCapacity, loadFactor);
-    }
-
-    /**
-     * Constructs a new, empty Cache with the specified initial
-     * capacity.
-     * @param initialCapacity the initial number of buckets
-     */
-    public Cache (int initialCapacity) {
-        init(initialCapacity, 0.75f);
-    }
-
-    /**
-     * Constructs a new, empty Cache. A default capacity and load factor
-     * is used. Note that the Cache will automatically grow when it gets
-     * full.
-     */
-    public Cache () {
-        try {
-            init(101, 0.75f);
-        } catch (IllegalArgumentException ex) {
-            // This should never happen
-            throw new Error("panic");
-        }
-    }
-
-    /**
-     * Returns the number of elements contained within the Cache.
-     */
-    public int size() {
-        return count;
-    }
-
-    /**
-     * Returns true if the Cache contains no elements.
-     */
-    public boolean isEmpty() {
-        return count == 0;
-    }
-
-    /**
-     * Returns an enumeration of the Cache's keys.
-     * @see Cache#elements
-     * @see Enumeration
-     */
-    public synchronized Enumeration<Object> keys() {
-        return new CacheEnumerator(table, true);
-    }
-
-    /**
-     * Returns an enumeration of the elements. Use the Enumeration methods
-     * on the returned object to fetch the elements sequentially.
-     * @see Cache#keys
-     * @see Enumeration
-     */
-    public synchronized Enumeration<Object> elements() {
-        return new CacheEnumerator(table, false);
-    }
-
-    /**
-     * Gets the object associated with the specified key in the Cache.
-     * @param key the key in the hash table
-     * @return the element for the key or null if the key
-     *         is not defined in the hash table.
-     * @see Cache#put
-     */
-    public synchronized Object get(Object key) {
-        CacheEntry tab[] = table;
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (CacheEntry e = tab[index]; e != null; e = e.next) {
-            if ((e.hash == hash) && e.key.equals(key)) {
-                return e.get();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Rehashes the contents of the table into a bigger table.
-     * This is method is called automatically when the Cache's
-     * size exceeds the threshold.
-     */
-    protected void rehash() {
-        int oldCapacity = table.length;
-        CacheEntry oldTable[] = table;
-
-        int newCapacity = oldCapacity * 2 + 1;
-        CacheEntry newTable[] = new CacheEntry[newCapacity];
-
-        threshold = (int) (newCapacity * loadFactor);
-        table = newTable;
-
-        // System.out.println("rehash old=" + oldCapacity + ", new=" +
-        // newCapacity + ", thresh=" + threshold + ", count=" + count);
-
-        for (int i = oldCapacity; i-- > 0;) {
-            for (CacheEntry old = oldTable[i]; old != null;) {
-                CacheEntry e = old;
-                old = old.next;
-                if (e.get() != null) {
-                    int index = (e.hash & 0x7FFFFFFF) % newCapacity;
-                    e.next = newTable[index];
-                    newTable[index] = e;
-                } else
-                    count--;    /* remove entries that have disappeared */
-            }
-        }
-    }
-
-    /**
-     * Puts the specified element into the Cache, using the specified
-     * key.  The element may be retrieved by doing a get() with the same
-     * key.  The key and the element cannot be null.
-     * @param key the specified hashtable key
-     * @param value the specified element
-     * @return the old value of the key, or null if it did not have one.
-     * @exception NullPointerException If the value of the specified
-     * element is null.
-     * @see Cache#get
-     */
-    public synchronized Object put(Object key, Object value) {
-        // Make sure the value is not null
-        if (value == null) {
-            throw new NullPointerException();
-        }
-        // Makes sure the key is not already in the cache.
-        CacheEntry tab[] = table;
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        CacheEntry ne = null;
-        for (CacheEntry e = tab[index]; e != null; e = e.next) {
-            if ((e.hash == hash) && e.key.equals(key)) {
-                Object old = e.get();
-                e.setThing(value);
-                return old;
-            } else if (e.get() == null)
-                ne = e;         /* reuse old flushed value */
-        }
-
-        if (count >= threshold) {
-            // Rehash the table if the threshold is exceeded
-            rehash();
-            return put(key, value);
-        }
-        // Creates the new entry.
-        if (ne == null) {
-            ne = new CacheEntry ();
-            ne.next = tab[index];
-            tab[index] = ne;
-            count++;
-        }
-        ne.hash = hash;
-        ne.key = key;
-        ne.setThing(value);
-        return null;
-    }
-
-    /**
-     * Removes the element corresponding to the key. Does nothing if the
-     * key is not present.
-     * @param key the key that needs to be removed
-     * @return the value of key, or null if the key was not found.
-     */
-    public synchronized Object remove(Object key) {
-        CacheEntry tab[] = table;
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (CacheEntry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
-            if ((e.hash == hash) && e.key.equals(key)) {
-                if (prev != null) {
-                    prev.next = e.next;
-                } else {
-                    tab[index] = e.next;
-                }
-                count--;
-                return e.get();
-            }
-        }
-        return null;
-    }
-}
-
-/**
- * A Cache enumerator class.  This class should remain opaque
- * to the client. It will use the Enumeration interface.
- */
-class CacheEnumerator implements Enumeration<Object> {
-    boolean keys;
-    int index;
-    CacheEntry table[];
-    CacheEntry entry;
-
-    CacheEnumerator (CacheEntry table[], boolean keys) {
-        this.table = table;
-        this.keys = keys;
-        this.index = table.length;
-    }
-
-    public boolean hasMoreElements() {
-        while (index >= 0) {
-            while (entry != null)
-                if (entry.get() != null)
-                    return true;
-                else
-                    entry = entry.next;
-            while (--index >= 0 && (entry = table[index]) == null) ;
-        }
-        return false;
-    }
-
-    public Object nextElement() {
-        while (index >= 0) {
-            if (entry == null)
-                while (--index >= 0 && (entry = table[index]) == null) ;
-            if (entry != null) {
-                CacheEntry e = entry;
-                entry = e.next;
-                if (e.get() != null)
-                    return keys ? e.key : e.get();
-            }
-        }
-        throw new NoSuchElementException("CacheEnumerator");
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * A thread that has it's thread locals, and inheritable thread
- * locals erased on construction.
- */
-public class ManagedLocalsThread extends Thread {
-    private static final jdk.internal.misc.Unsafe UNSAFE;
-    private static final long THREAD_LOCALS;
-    private static final long INHERITABLE_THREAD_LOCALS;
-
-    public ManagedLocalsThread() {
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(Runnable target) {
-        super(target);
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(String name) {
-        super(name);
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(ThreadGroup group, Runnable target) {
-        super(group, target);
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(Runnable target, String name) {
-        super(target, name);
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(ThreadGroup group, String name) {
-        super(group, name);
-        eraseThreadLocals();
-    }
-
-    public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) {
-        super(group, target, name);
-        eraseThreadLocals();
-    }
-
-    /**
-     * Drops all thread locals (and inherited thread locals).
-     */
-    public final void eraseThreadLocals() {
-        UNSAFE.putObject(this, THREAD_LOCALS, null);
-        UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
-    }
-
-    static {
-        UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
-        Class<?> t = Thread.class;
-        try {
-            THREAD_LOCALS = UNSAFE.objectFieldOffset
-                (t.getDeclaredField("threadLocals"));
-            INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
-                (t.getDeclaredField("inheritableThreadLocals"));
-        } catch (Exception e) {
-            throw new Error(e);
-        }
-    }
-}
-
--- a/src/java.base/share/classes/sun/misc/Signal.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Objects;
-
-/**
- * This class provides ANSI/ISO C signal support. A Java program can register
- * signal handlers for the current process. There are two restrictions:
- * <ul>
- * <li>
- * Java code cannot register a handler for signals that are already used
- * by the Java VM implementation. The <code>Signal.handle</code>
- * function raises an <code>IllegalArgumentException</code> if such an attempt
- * is made.
- * <li>
- * When <code>Signal.handle</code> is called, the VM internally registers a
- * special C signal handler. There is no way to force the Java signal handler
- * to run synchronously before the C signal handler returns. Instead, when the
- * VM receives a signal, the special C signal handler creates a new thread
- * (at priority <code>Thread.MAX_PRIORITY</code>) to
- * run the registered Java signal handler. The C signal handler immediately
- * returns. Note that because the Java signal handler runs in a newly created
- * thread, it may not actually be executed until some time after the C signal
- * handler returns.
- * </ul>
- * <p>
- * Signal objects are created based on their names. For example:
- * <blockquote><pre>
- * new Signal("INT");
- * </pre></blockquote>
- * constructs a signal object corresponding to <code>SIGINT</code>, which is
- * typically produced when the user presses <code>Ctrl-C</code> at the command line.
- * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
- * when it is passed an unknown signal.
- * <p>
- * This is an example of how Java code handles <code>SIGINT</code>:
- * <blockquote><pre>
- * SignalHandler handler = new SignalHandler () {
- *     public void handle(Signal sig) {
- *       ... // handle SIGINT
- *     }
- * };
- * Signal.handle(new Signal("INT"), handler);
- * </pre></blockquote>
- *
- * @author   Sheng Liang
- * @author   Bill Shannon
- * @see     sun.misc.SignalHandler
- * @since    1.2
- */
-public final class Signal {
-
-    // Delegate to jdk.internal.misc.Signal.
-    private final jdk.internal.misc.Signal iSignal;
-
-    /* Returns the signal number */
-    public int getNumber() {
-        return iSignal.getNumber();
-    }
-
-    /**
-     * Returns the signal name.
-     *
-     * @return the name of the signal.
-     * @see sun.misc.Signal#Signal(String name)
-     */
-    public String getName() {
-        return iSignal.getName();
-    }
-
-    /**
-     * Compares the equality of two <code>Signal</code> objects.
-     *
-     * @param other the object to compare with.
-     * @return whether two <code>Signal</code> objects are equal.
-     */
-    public boolean equals(Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null || !(other instanceof Signal)) {
-            return false;
-        }
-        Signal other1 = (Signal)other;
-        return iSignal.equals(other1.iSignal);
-    }
-
-    /**
-     * Returns a hashcode for this Signal.
-     *
-     * @return  a hash code value for this object.
-     */
-    public int hashCode() {
-        return getNumber();
-    }
-
-    /**
-     * Returns a string representation of this signal. For example, "SIGINT"
-     * for an object constructed using <code>new Signal ("INT")</code>.
-     *
-     * @return a string representation of the signal
-     */
-    public String toString() {
-        return iSignal.toString();
-    }
-
-    /**
-     * Constructs a signal from its name.
-     *
-     * @param name the name of the signal.
-     * @exception IllegalArgumentException unknown signal
-     * @see sun.misc.Signal#getName()
-     */
-    public Signal(String name) {
-        iSignal = new jdk.internal.misc.Signal(name);
-    }
-
-    /**
-     * Registers a signal handler.
-     *
-     * @param sig a signal
-     * @param handler the handler to be registered with the given signal.
-     * @return the old handler
-     * @exception IllegalArgumentException the signal is in use by the VM
-     * @see sun.misc.Signal#raise(Signal sig)
-     * @see sun.misc.SignalHandler
-     * @see sun.misc.SignalHandler#SIG_DFL
-     * @see sun.misc.SignalHandler#SIG_IGN
-     */
-    public static synchronized SignalHandler handle(Signal sig,
-                                                    SignalHandler handler)
-        throws IllegalArgumentException {
-        jdk.internal.misc.Signal.Handler oldHandler = jdk.internal.misc.Signal.handle(sig.iSignal,
-                InternalMiscHandler.of(sig, handler));
-        return SunMiscHandler.of(sig.iSignal, oldHandler);
-    }
-
-    /**
-     * Raises a signal in the current process.
-     *
-     * @param sig a signal
-     * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
-     */
-    public static void raise(Signal sig) throws IllegalArgumentException {
-        jdk.internal.misc.Signal.raise(sig.iSignal);
-    }
-
-    /*
-     * Wrapper class to proxy a SignalHandler to a jdk.internal.misc.Signal.Handler.
-     */
-    static final class InternalMiscHandler implements jdk.internal.misc.Signal.Handler {
-        private final SignalHandler handler;
-        private final Signal signal;
-
-        static jdk.internal.misc.Signal.Handler of(Signal signal, SignalHandler handler) {
-            if (handler == SignalHandler.SIG_DFL) {
-                return jdk.internal.misc.Signal.Handler.SIG_DFL;
-            } else if (handler == SignalHandler.SIG_IGN) {
-                return jdk.internal.misc.Signal.Handler.SIG_IGN;
-            } else if (handler instanceof SunMiscHandler) {
-                return ((SunMiscHandler)handler).iHandler;
-            } else {
-                return new InternalMiscHandler(signal, handler);
-            }
-        }
-
-        private InternalMiscHandler(Signal signal, SignalHandler handler) {
-            this.handler = handler;
-            this.signal = signal;
-        }
-
-        @Override
-        public void handle(jdk.internal.misc.Signal ignore) {
-            handler.handle(signal);
-        }
-    }
-
-    /*
-     * Wrapper class to proxy a jdk.internal.misc.Signal.Handler to a SignalHandler.
-     */
-    static final class SunMiscHandler implements SignalHandler {
-        private final jdk.internal.misc.Signal iSignal;
-        private final jdk.internal.misc.Signal.Handler iHandler;
-
-        static SignalHandler of(jdk.internal.misc.Signal signal, jdk.internal.misc.Signal.Handler handler) {
-            if (handler == jdk.internal.misc.Signal.Handler.SIG_DFL) {
-                return SignalHandler.SIG_DFL;
-            } else if (handler == jdk.internal.misc.Signal.Handler.SIG_IGN) {
-                return SignalHandler.SIG_IGN;
-            } else if (handler instanceof InternalMiscHandler) {
-                return ((InternalMiscHandler) handler).handler;
-            } else {
-                return new SunMiscHandler(signal, handler);
-            }
-        }
-
-        SunMiscHandler(jdk.internal.misc.Signal iSignal, jdk.internal.misc.Signal.Handler iHandler) {
-            this.iSignal = iSignal;
-            this.iHandler = iHandler;
-        }
-
-        @Override
-        public void handle(Signal sig) {
-            iHandler.handle(iSignal);
-        }
-
-        public String toString() {
-            return iHandler.toString();
-        }
-    }
-}
--- a/src/java.base/share/classes/sun/misc/SignalHandler.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This is the signal handler interface expected in <code>Signal.handle</code>.
- *
- * @author   Sheng Liang
- * @author   Bill Shannon
- * @see      sun.misc.Signal
- * @since    1.2
- */
-
-public interface SignalHandler {
-
-    /**
-     * The default signal handler
-     */
-    public static final SignalHandler SIG_DFL =
-            new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_DFL);
-    /**
-     * Ignore the signal
-     */
-    public static final SignalHandler SIG_IGN =
-            new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_IGN);
-
-    /**
-     * Handle the given signal
-     *
-     * @param sig a signal object
-     */
-    public void handle(Signal sig);
-}
--- a/src/java.base/share/classes/sun/misc/SoftCache.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,462 +0,0 @@
-/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.lang.ref.SoftReference;
-import java.lang.ref.ReferenceQueue;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.AbstractSet;
-import java.util.NoSuchElementException;
-
-
-/**
- * A memory-sensitive implementation of the <code>Map</code> interface.
- *
- * <p> A <code>SoftCache</code> object uses {@link java.lang.ref.SoftReference
- * soft references} to implement a memory-sensitive hash map.  If the garbage
- * collector determines at a certain point in time that a value object in a
- * <code>SoftCache</code> entry is no longer strongly reachable, then it may
- * remove that entry in order to release the memory occupied by the value
- * object.  All <code>SoftCache</code> objects are guaranteed to be completely
- * cleared before the virtual machine will throw an
- * <code>OutOfMemoryError</code>.  Because of this automatic clearing feature,
- * the behavior of this class is somewhat different from that of other
- * <code>Map</code> implementations.
- *
- * <p> Both null values and the null key are supported.  This class has the
- * same performance characteristics as the <code>HashMap</code> class, and has
- * the same efficiency parameters of <em>initial capacity</em> and <em>load
- * factor</em>.
- *
- * <p> Like most collection classes, this class is not synchronized.  A
- * synchronized <code>SoftCache</code> may be constructed using the
- * <code>Collections.synchronizedMap</code> method.
- *
- * <p> In typical usage this class will be subclassed and the <code>fill</code>
- * method will be overridden.  When the <code>get</code> method is invoked on a
- * key for which there is no mapping in the cache, it will in turn invoke the
- * <code>fill</code> method on that key in an attempt to construct a
- * corresponding value.  If the <code>fill</code> method returns such a value
- * then the cache will be updated and the new value will be returned.  Thus,
- * for example, a simple URL-content cache can be constructed as follows:
- *
- * <pre>
- *     public class URLCache extends SoftCache {
- *         protected Object fill(Object key) {
- *             return ((URL)key).getContent();
- *         }
- *     }
- * </pre>
- *
- * <p> The behavior of the <code>SoftCache</code> class depends in part upon
- * the actions of the garbage collector, so several familiar (though not
- * required) <code>Map</code> invariants do not hold for this class.  <p>
- * Because entries are removed from a <code>SoftCache</code> in response to
- * dynamic advice from the garbage collector, a <code>SoftCache</code> may
- * behave as though an unknown thread is silently removing entries.  In
- * particular, even if you synchronize on a <code>SoftCache</code> instance and
- * invoke none of its mutator methods, it is possible for the <code>size</code>
- * method to return smaller values over time, for the <code>isEmpty</code>
- * method to return <code>false</code> and then <code>true</code>, for the
- * <code>containsKey</code> method to return <code>true</code> and later
- * <code>false</code> for a given key, for the <code>get</code> method to
- * return a value for a given key but later return <code>null</code>, for the
- * <code>put</code> method to return <code>null</code> and the
- * <code>remove</code> method to return <code>false</code> for a key that
- * previously appeared to be in the map, and for successive examinations of the
- * key set, the value set, and the entry set to yield successively smaller
- * numbers of elements.
- *
- * @author      Mark Reinhold
- * @since       1.2
- * @see         java.util.HashMap
- * @see         java.lang.ref.SoftReference
- * @deprecated No direct replacement; {@link java.util.WeakHashMap}
- * addresses a related by different use-case.
- */
-
-@Deprecated
-public class SoftCache extends AbstractMap<Object, Object> implements Map<Object, Object> {
-
-    /* The basic idea of this implementation is to maintain an internal HashMap
-       that maps keys to soft references whose referents are the keys' values;
-       the various accessor methods dereference these soft references before
-       returning values.  Because we don't have access to the innards of the
-       HashMap, each soft reference must contain the key that maps to it so
-       that the processQueue method can remove keys whose values have been
-       discarded.  Thus the HashMap actually maps keys to instances of the
-       ValueCell class, which is a simple extension of the SoftReference class.
-     */
-
-
-    private static class ValueCell extends SoftReference<Object> {
-        private static Object INVALID_KEY = new Object();
-        private static int dropped = 0;
-        private Object key;
-
-        private ValueCell(Object key, Object value, ReferenceQueue<Object> queue) {
-            super(value, queue);
-            this.key = key;
-        }
-
-        private static ValueCell create(Object key, Object value,
-                                        ReferenceQueue<Object> queue)
-        {
-            if (value == null) return null;
-            return new ValueCell(key, value, queue);
-        }
-
-        private static Object strip(Object val, boolean drop) {
-            if (val == null) return null;
-            ValueCell vc = (ValueCell)val;
-            Object o = vc.get();
-            if (drop) vc.drop();
-            return o;
-        }
-
-        private boolean isValid() {
-            return (key != INVALID_KEY);
-        }
-
-        private void drop() {
-            super.clear();
-            key = INVALID_KEY;
-            dropped++;
-        }
-
-    }
-
-
-    /* Hash table mapping keys to ValueCells */
-    private Map<Object, Object> hash;
-
-    /* Reference queue for cleared ValueCells */
-    private ReferenceQueue<Object> queue = new ReferenceQueue<>();
-
-
-    /* Process any ValueCells that have been cleared and enqueued by the
-       garbage collector.  This method should be invoked once by each public
-       mutator in this class.  We don't invoke this method in public accessors
-       because that can lead to surprising ConcurrentModificationExceptions.
-     */
-    private void processQueue() {
-        ValueCell vc;
-        while ((vc = (ValueCell)queue.poll()) != null) {
-            if (vc.isValid()) hash.remove(vc.key);
-            else ValueCell.dropped--;
-        }
-    }
-
-
-    /* -- Constructors -- */
-
-    /**
-     * Construct a new, empty <code>SoftCache</code> with the given
-     * initial capacity and the given load factor.
-     *
-     * @param  initialCapacity  The initial capacity of the cache
-     *
-     * @param  loadFactor       A number between 0.0 and 1.0
-     *
-     * @throws IllegalArgumentException  If the initial capacity is less than
-     *                                   or equal to zero, or if the load
-     *                                   factor is less than zero
-     */
-    public SoftCache(int initialCapacity, float loadFactor) {
-        hash = new HashMap<>(initialCapacity, loadFactor);
-    }
-
-    /**
-     * Construct a new, empty <code>SoftCache</code> with the given
-     * initial capacity and the default load factor.
-     *
-     * @param  initialCapacity  The initial capacity of the cache
-     *
-     * @throws IllegalArgumentException  If the initial capacity is less than
-     *                                   or equal to zero
-     */
-    public SoftCache(int initialCapacity) {
-        hash = new HashMap<>(initialCapacity);
-    }
-
-    /**
-     * Construct a new, empty <code>SoftCache</code> with the default
-     * capacity and the default load factor.
-     */
-    public SoftCache() {
-        hash = new HashMap<>();
-    }
-
-
-    /* -- Simple queries -- */
-
-    /**
-     * Return the number of key-value mappings in this cache.  The time
-     * required by this operation is linear in the size of the map.
-     */
-    public int size() {
-        return entrySet().size();
-    }
-
-    /**
-     * Return <code>true</code> if this cache contains no key-value mappings.
-     */
-    public boolean isEmpty() {
-        return entrySet().isEmpty();
-    }
-
-    /**
-     * Return <code>true</code> if this cache contains a mapping for the
-     * specified key.  If there is no mapping for the key, this method will not
-     * attempt to construct one by invoking the <code>fill</code> method.
-     *
-     * @param   key   The key whose presence in the cache is to be tested
-     */
-    public boolean containsKey(Object key) {
-        return ValueCell.strip(hash.get(key), false) != null;
-    }
-
-
-    /* -- Lookup and modification operations -- */
-
-    /**
-     * Create a value object for the given <code>key</code>.  This method is
-     * invoked by the <code>get</code> method when there is no entry for
-     * <code>key</code>.  If this method returns a non-<code>null</code> value,
-     * then the cache will be updated to map <code>key</code> to that value,
-     * and that value will be returned by the <code>get</code> method.
-     *
-     * <p> The default implementation of this method simply returns
-     * <code>null</code> for every <code>key</code> value.  A subclass may
-     * override this method to provide more useful behavior.
-     *
-     * @param  key  The key for which a value is to be computed
-     *
-     * @return      A value for <code>key</code>, or <code>null</code> if one
-     *              could not be computed
-     * @see #get
-     */
-    protected Object fill(Object key) {
-        return null;
-    }
-
-    /**
-     * Return the value to which this cache maps the specified
-     * <code>key</code>.  If the cache does not presently contain a value for
-     * this key, then invoke the <code>fill</code> method in an attempt to
-     * compute such a value.  If that method returns a non-<code>null</code>
-     * value, then update the cache and return the new value.  Otherwise,
-     * return <code>null</code>.
-     *
-     * <p> Note that because this method may update the cache, it is considered
-     * a mutator and may cause <code>ConcurrentModificationException</code>s to
-     * be thrown if invoked while an iterator is in use.
-     *
-     * @param  key  The key whose associated value, if any, is to be returned
-     *
-     * @see #fill
-     */
-    public Object get(Object key) {
-        processQueue();
-        Object v = hash.get(key);
-        if (v == null) {
-            v = fill(key);
-            if (v != null) {
-                hash.put(key, ValueCell.create(key, v, queue));
-                return v;
-            }
-        }
-        return ValueCell.strip(v, false);
-    }
-
-    /**
-     * Update this cache so that the given <code>key</code> maps to the given
-     * <code>value</code>.  If the cache previously contained a mapping for
-     * <code>key</code> then that mapping is replaced and the old value is
-     * returned.
-     *
-     * @param  key    The key that is to be mapped to the given
-     *                <code>value</code>
-     * @param  value  The value to which the given <code>key</code> is to be
-     *                mapped
-     *
-     * @return  The previous value to which this key was mapped, or
-     *          <code>null</code> if there was no mapping for the key
-     */
-    public Object put(Object key, Object value) {
-        processQueue();
-        ValueCell vc = ValueCell.create(key, value, queue);
-        return ValueCell.strip(hash.put(key, vc), true);
-    }
-
-    /**
-     * Remove the mapping for the given <code>key</code> from this cache, if
-     * present.
-     *
-     * @param  key  The key whose mapping is to be removed
-     *
-     * @return  The value to which this key was mapped, or <code>null</code> if
-     *          there was no mapping for the key
-     */
-    public Object remove(Object key) {
-        processQueue();
-        return ValueCell.strip(hash.remove(key), true);
-    }
-
-    /**
-     * Remove all mappings from this cache.
-     */
-    public void clear() {
-        processQueue();
-        hash.clear();
-    }
-
-
-    /* -- Views -- */
-
-    private static boolean valEquals(Object o1, Object o2) {
-        return (o1 == null) ? (o2 == null) : o1.equals(o2);
-    }
-
-
-    /* Internal class for entries.
-       Because it uses SoftCache.this.queue, this class cannot be static.
-     */
-    private class Entry implements Map.Entry<Object, Object> {
-        private Map.Entry<Object, Object> ent;
-        private Object value;   /* Strong reference to value, to prevent the GC
-                                   from flushing the value while this Entry
-                                   exists */
-
-        Entry(Map.Entry<Object, Object> ent, Object value) {
-            this.ent = ent;
-            this.value = value;
-        }
-
-        public Object getKey() {
-            return ent.getKey();
-        }
-
-        public Object getValue() {
-            return value;
-        }
-
-        public Object setValue(Object value) {
-            return ent.setValue(ValueCell.create(ent.getKey(), value, queue));
-        }
-
-        @SuppressWarnings("unchecked")
-        public boolean equals(Object o) {
-            if (! (o instanceof Map.Entry)) return false;
-            Map.Entry<Object, Object> e = (Map.Entry<Object, Object>)o;
-            return (valEquals(ent.getKey(), e.getKey())
-                    && valEquals(value, e.getValue()));
-        }
-
-        public int hashCode() {
-            Object k;
-            return ((((k = getKey()) == null) ? 0 : k.hashCode())
-                    ^ ((value == null) ? 0 : value.hashCode()));
-        }
-
-    }
-
-
-    /* Internal class for entry sets */
-    private class EntrySet extends AbstractSet<Map.Entry<Object, Object>> {
-        Set<Map.Entry<Object, Object>> hashEntries = hash.entrySet();
-
-        public Iterator<Map.Entry<Object, Object>> iterator() {
-
-            return new Iterator<Map.Entry<Object, Object>>() {
-                Iterator<Map.Entry<Object, Object>> hashIterator = hashEntries.iterator();
-                Entry next = null;
-
-                public boolean hasNext() {
-                    while (hashIterator.hasNext()) {
-                        Map.Entry<Object, Object> ent = hashIterator.next();
-                        ValueCell vc = (ValueCell)ent.getValue();
-                        Object v = null;
-                        if ((vc != null) && ((v = vc.get()) == null)) {
-                            /* Value has been flushed by GC */
-                            continue;
-                        }
-                        next = new Entry(ent, v);
-                        return true;
-                    }
-                    return false;
-                }
-
-                public Map.Entry<Object, Object> next() {
-                    if ((next == null) && !hasNext())
-                        throw new NoSuchElementException();
-                    Entry e = next;
-                    next = null;
-                    return e;
-                }
-
-                public void remove() {
-                    hashIterator.remove();
-                }
-
-            };
-        }
-
-        public boolean isEmpty() {
-            return !(iterator().hasNext());
-        }
-
-        public int size() {
-            int j = 0;
-            for (Iterator<Map.Entry<Object, Object>> i = iterator(); i.hasNext(); i.next()) j++;
-            return j;
-        }
-
-        public boolean remove(Object o) {
-            processQueue();
-            if (o instanceof Entry) return hashEntries.remove(((Entry)o).ent);
-            else return false;
-        }
-
-    }
-
-
-    private Set<Map.Entry<Object, Object>> entrySet = null;
-
-    /**
-     * Return a <code>Set</code> view of the mappings in this cache.
-     */
-    public Set<Map.Entry<Object, Object>> entrySet() {
-        if (entrySet == null) entrySet = new EntrySet();
-        return entrySet;
-    }
-
-}
--- a/src/java.base/share/classes/sun/misc/Unsafe.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1270 +0,0 @@
-/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import jdk.internal.vm.annotation.ForceInline;
-import jdk.internal.misc.VM;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
-
-import java.lang.reflect.Field;
-import java.security.ProtectionDomain;
-
-
-/**
- * A collection of methods for performing low-level, unsafe operations.
- * Although the class and all methods are public, use of this class is
- * limited because only trusted code can obtain instances of it.
- *
- * <em>Note:</em> It is the resposibility of the caller to make sure
- * arguments are checked before methods of this class are
- * called. While some rudimentary checks are performed on the input,
- * the checks are best effort and when performance is an overriding
- * priority, as when methods of this class are optimized by the
- * runtime compiler, some or all checks (if any) may be elided. Hence,
- * the caller must not rely on the checks and corresponding
- * exceptions!
- *
- * @author John R. Rose
- * @see #getUnsafe
- */
-
-public final class Unsafe {
-
-    static {
-        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
-    }
-
-    private Unsafe() {}
-
-    private static final Unsafe theUnsafe = new Unsafe();
-    private static final jdk.internal.misc.Unsafe theInternalUnsafe = jdk.internal.misc.Unsafe.getUnsafe();
-
-    /**
-     * Provides the caller with the capability of performing unsafe
-     * operations.
-     *
-     * <p>The returned {@code Unsafe} object should be carefully guarded
-     * by the caller, since it can be used to read and write data at arbitrary
-     * memory addresses.  It must never be passed to untrusted code.
-     *
-     * <p>Most methods in this class are very low-level, and correspond to a
-     * small number of hardware instructions (on typical machines).  Compilers
-     * are encouraged to optimize these methods accordingly.
-     *
-     * <p>Here is a suggested idiom for using unsafe operations:
-     *
-     * <pre> {@code
-     * class MyTrustedClass {
-     *   private static final Unsafe unsafe = Unsafe.getUnsafe();
-     *   ...
-     *   private long myCountAddress = ...;
-     *   public int getCount() { return unsafe.getByte(myCountAddress); }
-     * }}</pre>
-     *
-     * (It may assist compilers to make the local variable {@code final}.)
-     *
-     * @throws  SecurityException  if a security manager exists and its
-     *          {@code checkPropertiesAccess} method doesn't allow
-     *          access to the system properties.
-     */
-    @CallerSensitive
-    public static Unsafe getUnsafe() {
-        Class<?> caller = Reflection.getCallerClass();
-        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
-            throw new SecurityException("Unsafe");
-        return theUnsafe;
-    }
-
-    /// peek and poke operations
-    /// (compilers should optimize these to memory ops)
-
-    // These work on object fields in the Java heap.
-    // They will not work on elements of packed arrays.
-
-    /**
-     * Fetches a value from a given Java variable.
-     * More specifically, fetches a field or array element within the given
-     * object {@code o} at the given offset, or (if {@code o} is null)
-     * from the memory address whose numerical value is the given offset.
-     * <p>
-     * The results are undefined unless one of the following cases is true:
-     * <ul>
-     * <li>The offset was obtained from {@link #objectFieldOffset} on
-     * the {@link java.lang.reflect.Field} of some Java field and the object
-     * referred to by {@code o} is of a class compatible with that
-     * field's class.
-     *
-     * <li>The offset and object reference {@code o} (either null or
-     * non-null) were both obtained via {@link #staticFieldOffset}
-     * and {@link #staticFieldBase} (respectively) from the
-     * reflective {@link Field} representation of some Java field.
-     *
-     * <li>The object referred to by {@code o} is an array, and the offset
-     * is an integer of the form {@code B+N*S}, where {@code N} is
-     * a valid index into the array, and {@code B} and {@code S} are
-     * the values obtained by {@link #arrayBaseOffset} and {@link
-     * #arrayIndexScale} (respectively) from the array's class.  The value
-     * referred to is the {@code N}<em>th</em> element of the array.
-     *
-     * </ul>
-     * <p>
-     * If one of the above cases is true, the call references a specific Java
-     * variable (field or array element).  However, the results are undefined
-     * if that variable is not in fact of the type returned by this method.
-     * <p>
-     * This method refers to a variable by means of two parameters, and so
-     * it provides (in effect) a <em>double-register</em> addressing mode
-     * for Java variables.  When the object reference is null, this method
-     * uses its offset as an absolute address.  This is similar in operation
-     * to methods such as {@link #getInt(long)}, which provide (in effect) a
-     * <em>single-register</em> addressing mode for non-Java variables.
-     * However, because Java variables may have a different layout in memory
-     * from non-Java variables, programmers should not assume that these
-     * two addressing modes are ever equivalent.  Also, programmers should
-     * remember that offsets from the double-register addressing mode cannot
-     * be portably confused with longs used in the single-register addressing
-     * mode.
-     *
-     * @param o Java heap object in which the variable resides, if any, else
-     *        null
-     * @param offset indication of where the variable resides in a Java heap
-     *        object, if any, else a memory address locating the variable
-     *        statically
-     * @return the value fetched from the indicated Java variable
-     * @throws RuntimeException No defined exceptions are thrown, not even
-     *         {@link NullPointerException}
-     */
-    @ForceInline
-    public int getInt(Object o, long offset) {
-        return theInternalUnsafe.getInt(o, offset);
-    }
-
-    /**
-     * Stores a value into a given Java variable.
-     * <p>
-     * The first two parameters are interpreted exactly as with
-     * {@link #getInt(Object, long)} to refer to a specific
-     * Java variable (field or array element).  The given value
-     * is stored into that variable.
-     * <p>
-     * The variable must be of the same type as the method
-     * parameter {@code x}.
-     *
-     * @param o Java heap object in which the variable resides, if any, else
-     *        null
-     * @param offset indication of where the variable resides in a Java heap
-     *        object, if any, else a memory address locating the variable
-     *        statically
-     * @param x the value to store into the indicated Java variable
-     * @throws RuntimeException No defined exceptions are thrown, not even
-     *         {@link NullPointerException}
-     */
-    @ForceInline
-    public void putInt(Object o, long offset, int x) {
-        theInternalUnsafe.putInt(o, offset, x);
-    }
-
-    /**
-     * Fetches a reference value from a given Java variable.
-     * @see #getInt(Object, long)
-     */
-    @ForceInline
-    public Object getObject(Object o, long offset) {
-        return theInternalUnsafe.getObject(o, offset);
-    }
-
-    /**
-     * Stores a reference value into a given Java variable.
-     * <p>
-     * Unless the reference {@code x} being stored is either null
-     * or matches the field type, the results are undefined.
-     * If the reference {@code o} is non-null, card marks or
-     * other store barriers for that object (if the VM requires them)
-     * are updated.
-     * @see #putInt(Object, long, int)
-     */
-    @ForceInline
-    public void putObject(Object o, long offset, Object x) {
-        theInternalUnsafe.putObject(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public boolean getBoolean(Object o, long offset) {
-        return theInternalUnsafe.getBoolean(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putBoolean(Object o, long offset, boolean x) {
-        theInternalUnsafe.putBoolean(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public byte getByte(Object o, long offset) {
-        return theInternalUnsafe.getByte(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putByte(Object o, long offset, byte x) {
-        theInternalUnsafe.putByte(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public short getShort(Object o, long offset) {
-        return theInternalUnsafe.getShort(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putShort(Object o, long offset, short x) {
-        theInternalUnsafe.putShort(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public char getChar(Object o, long offset) {
-        return theInternalUnsafe.getChar(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putChar(Object o, long offset, char x) {
-        theInternalUnsafe.putChar(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public long getLong(Object o, long offset) {
-        return theInternalUnsafe.getLong(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putLong(Object o, long offset, long x) {
-        theInternalUnsafe.putLong(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public float getFloat(Object o, long offset) {
-        return theInternalUnsafe.getFloat(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putFloat(Object o, long offset, float x) {
-        theInternalUnsafe.putFloat(o, offset, x);
-    }
-
-    /** @see #getInt(Object, long) */
-    @ForceInline
-    public double getDouble(Object o, long offset) {
-        return theInternalUnsafe.getDouble(o, offset);
-    }
-
-    /** @see #putInt(Object, long, int) */
-    @ForceInline
-    public void putDouble(Object o, long offset, double x) {
-        theInternalUnsafe.putDouble(o, offset, x);
-    }
-
-
-    // These read VM internal data.
-
-    /**
-     * Fetches an uncompressed reference value from a given native variable
-     * ignoring the VM's compressed references mode.
-     *
-     * @param address a memory address locating the variable
-     * @return the value fetched from the indicated native variable
-     */
-    @ForceInline
-    public Object getUncompressedObject(long address) {
-        return theInternalUnsafe.getUncompressedObject(address);
-    }
-
-    /**
-     * Fetches the {@link java.lang.Class} Java mirror for the given native
-     * metaspace {@code Klass} pointer.
-     *
-     * @param metaspaceKlass a native metaspace {@code Klass} pointer
-     * @return the {@link java.lang.Class} Java mirror
-     */
-    @ForceInline
-    public Class<?> getJavaMirror(long metaspaceKlass) {
-        return theInternalUnsafe.getJavaMirror(metaspaceKlass);
-    }
-
-    /**
-     * Fetches a native metaspace {@code Klass} pointer for the given Java
-     * object.
-     *
-     * @param o Java heap object for which to fetch the class pointer
-     * @return a native metaspace {@code Klass} pointer
-     */
-    @ForceInline
-    public long getKlassPointer(Object o) {
-        return theInternalUnsafe.getKlassPointer(o);
-    }
-
-    // These work on values in the C heap.
-
-    /**
-     * Fetches a value from a given memory address.  If the address is zero, or
-     * does not point into a block obtained from {@link #allocateMemory}, the
-     * results are undefined.
-     *
-     * @see #allocateMemory
-     */
-    @ForceInline
-    public byte getByte(long address) {
-        return theInternalUnsafe.getByte(address);
-    }
-
-    /**
-     * Stores a value into a given memory address.  If the address is zero, or
-     * does not point into a block obtained from {@link #allocateMemory}, the
-     * results are undefined.
-     *
-     * @see #getByte(long)
-     */
-    @ForceInline
-    public void putByte(long address, byte x) {
-        theInternalUnsafe.putByte(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public short getShort(long address) {
-        return theInternalUnsafe.getShort(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putShort(long address, short x) {
-        theInternalUnsafe.putShort(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public char getChar(long address) {
-        return theInternalUnsafe.getChar(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putChar(long address, char x) {
-        theInternalUnsafe.putChar(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public int getInt(long address) {
-        return theInternalUnsafe.getInt(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putInt(long address, int x) {
-        theInternalUnsafe.putInt(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public long getLong(long address) {
-        return theInternalUnsafe.getLong(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putLong(long address, long x) {
-        theInternalUnsafe.putLong(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public float getFloat(long address) {
-        return theInternalUnsafe.getFloat(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putFloat(long address, float x) {
-        theInternalUnsafe.putFloat(address, x);
-    }
-
-    /** @see #getByte(long) */
-    @ForceInline
-    public double getDouble(long address) {
-        return theInternalUnsafe.getDouble(address);
-    }
-
-    /** @see #putByte(long, byte) */
-    @ForceInline
-    public void putDouble(long address, double x) {
-        theInternalUnsafe.putDouble(address, x);
-    }
-
-
-    /**
-     * Fetches a native pointer from a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>If the native pointer is less than 64 bits wide, it is extended as
-     * an unsigned number to a Java long.  The pointer may be indexed by any
-     * given byte offset, simply by adding that offset (as a simple integer) to
-     * the long representing the pointer.  The number of bytes actually read
-     * from the target address may be determined by consulting {@link
-     * #addressSize}.
-     *
-     * @see #allocateMemory
-     */
-    @ForceInline
-    public long getAddress(long address) {
-        return theInternalUnsafe.getAddress(address);
-    }
-
-    /**
-     * Stores a native pointer into a given memory address.  If the address is
-     * zero, or does not point into a block obtained from {@link
-     * #allocateMemory}, the results are undefined.
-     *
-     * <p>The number of bytes actually written at the target address may be
-     * determined by consulting {@link #addressSize}.
-     *
-     * @see #getAddress(long)
-     */
-    @ForceInline
-    public void putAddress(long address, long x) {
-        theInternalUnsafe.putAddress(address, x);
-    }
-
-
-    /// wrappers for malloc, realloc, free:
-
-    /**
-     * Allocates a new block of native memory, of the given size in bytes.  The
-     * contents of the memory are uninitialized; they will generally be
-     * garbage.  The resulting native pointer will never be zero, and will be
-     * aligned for all value types.  Dispose of this memory by calling {@link
-     * #freeMemory}, or resize it with {@link #reallocateMemory}.
-     *
-     * <em>Note:</em> It is the resposibility of the caller to make
-     * sure arguments are checked before the methods are called. While
-     * some rudimentary checks are performed on the input, the checks
-     * are best effort and when performance is an overriding priority,
-     * as when methods of this class are optimized by the runtime
-     * compiler, some or all checks (if any) may be elided. Hence, the
-     * caller must not rely on the checks and corresponding
-     * exceptions!
-     *
-     * @throws RuntimeException if the size is negative or too large
-     *         for the native size_t type
-     *
-     * @throws OutOfMemoryError if the allocation is refused by the system
-     *
-     * @see #getByte(long)
-     * @see #putByte(long, byte)
-     */
-    @ForceInline
-    public long allocateMemory(long bytes) {
-        return theInternalUnsafe.allocateMemory(bytes);
-    }
-
-    /**
-     * Resizes a new block of native memory, to the given size in bytes.  The
-     * contents of the new block past the size of the old block are
-     * uninitialized; they will generally be garbage.  The resulting native
-     * pointer will be zero if and only if the requested size is zero.  The
-     * resulting native pointer will be aligned for all value types.  Dispose
-     * of this memory by calling {@link #freeMemory}, or resize it with {@link
-     * #reallocateMemory}.  The address passed to this method may be null, in
-     * which case an allocation will be performed.
-     *
-     * <em>Note:</em> It is the resposibility of the caller to make
-     * sure arguments are checked before the methods are called. While
-     * some rudimentary checks are performed on the input, the checks
-     * are best effort and when performance is an overriding priority,
-     * as when methods of this class are optimized by the runtime
-     * compiler, some or all checks (if any) may be elided. Hence, the
-     * caller must not rely on the checks and corresponding
-     * exceptions!
-     *
-     * @throws RuntimeException if the size is negative or too large
-     *         for the native size_t type
-     *
-     * @throws OutOfMemoryError if the allocation is refused by the system
-     *
-     * @see #allocateMemory
-     */
-    @ForceInline
-    public long reallocateMemory(long address, long bytes) {
-        return theInternalUnsafe.reallocateMemory(address, bytes);
-    }
-
-    /**
-     * Sets all bytes in a given block of memory to a fixed value
-     * (usually zero).
-     *
-     * <p>This method determines a block's base address by means of two parameters,
-     * and so it provides (in effect) a <em>double-register</em> addressing mode,
-     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
-     * the offset supplies an absolute base address.
-     *
-     * <p>The stores are in coherent (atomic) units of a size determined
-     * by the address and length parameters.  If the effective address and
-     * length are all even modulo 8, the stores take place in 'long' units.
-     * If the effective address and length are (resp.) even modulo 4 or 2,
-     * the stores take place in units of 'int' or 'short'.
-     *
-     * <em>Note:</em> It is the resposibility of the caller to make
-     * sure arguments are checked before the methods are called. While
-     * some rudimentary checks are performed on the input, the checks
-     * are best effort and when performance is an overriding priority,
-     * as when methods of this class are optimized by the runtime
-     * compiler, some or all checks (if any) may be elided. Hence, the
-     * caller must not rely on the checks and corresponding
-     * exceptions!
-     *
-     * @throws RuntimeException if any of the arguments is invalid
-     *
-     * @since 1.7
-     */
-    @ForceInline
-    public void setMemory(Object o, long offset, long bytes, byte value) {
-        theInternalUnsafe.setMemory(o, offset, bytes, value);
-    }
-
-    /**
-     * Sets all bytes in a given block of memory to a fixed value
-     * (usually zero).  This provides a <em>single-register</em> addressing mode,
-     * as discussed in {@link #getInt(Object,long)}.
-     *
-     * <p>Equivalent to {@code setMemory(null, address, bytes, value)}.
-     */
-    @ForceInline
-    public void setMemory(long address, long bytes, byte value) {
-        theInternalUnsafe.setMemory(address, bytes, value);
-    }
-
-    /**
-     * Sets all bytes in a given block of memory to a copy of another
-     * block.
-     *
-     * <p>This method determines each block's base address by means of two parameters,
-     * and so it provides (in effect) a <em>double-register</em> addressing mode,
-     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
-     * the offset supplies an absolute base address.
-     *
-     * <p>The transfers are in coherent (atomic) units of a size determined
-     * by the address and length parameters.  If the effective addresses and
-     * length are all even modulo 8, the transfer takes place in 'long' units.
-     * If the effective addresses and length are (resp.) even modulo 4 or 2,
-     * the transfer takes place in units of 'int' or 'short'.
-     *
-     * <em>Note:</em> It is the resposibility of the caller to make
-     * sure arguments are checked before the methods are called. While
-     * some rudimentary checks are performed on the input, the checks
-     * are best effort and when performance is an overriding priority,
-     * as when methods of this class are optimized by the runtime
-     * compiler, some or all checks (if any) may be elided. Hence, the
-     * caller must not rely on the checks and corresponding
-     * exceptions!
-     *
-     * @throws RuntimeException if any of the arguments is invalid
-     *
-     * @since 1.7
-     */
-    @ForceInline
-    public void copyMemory(Object srcBase, long srcOffset,
-                           Object destBase, long destOffset,
-                           long bytes) {
-        theInternalUnsafe.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes);
-    }
-
-    /**
-     * Sets all bytes in a given block of memory to a copy of another
-     * block.  This provides a <em>single-register</em> addressing mode,
-     * as discussed in {@link #getInt(Object,long)}.
-     *
-     * Equivalent to {@code copyMemory(null, srcAddress, null, destAddress, bytes)}.
-     */
-    @ForceInline
-    public void copyMemory(long srcAddress, long destAddress, long bytes) {
-        theInternalUnsafe.copyMemory(srcAddress, destAddress, bytes);
-    }
-
-    /**
-     * Disposes of a block of native memory, as obtained from {@link
-     * #allocateMemory} or {@link #reallocateMemory}.  The address passed to
-     * this method may be null, in which case no action is taken.
-     *
-     * <em>Note:</em> It is the resposibility of the caller to make
-     * sure arguments are checked before the methods are called. While
-     * some rudimentary checks are performed on the input, the checks
-     * are best effort and when performance is an overriding priority,
-     * as when methods of this class are optimized by the runtime
-     * compiler, some or all checks (if any) may be elided. Hence, the
-     * caller must not rely on the checks and corresponding
-     * exceptions!
-     *
-     * @throws RuntimeException if any of the arguments is invalid
-     *
-     * @see #allocateMemory
-     */
-    @ForceInline
-    public void freeMemory(long address) {
-        theInternalUnsafe.freeMemory(address);
-    }
-
-    /// random queries
-
-    /**
-     * This constant differs from all results that will ever be returned from
-     * {@link #staticFieldOffset}, {@link #objectFieldOffset},
-     * or {@link #arrayBaseOffset}.
-     */
-    public static final int INVALID_FIELD_OFFSET = jdk.internal.misc.Unsafe.INVALID_FIELD_OFFSET;
-
-    /**
-     * Reports the location of a given field in the storage allocation of its
-     * class.  Do not expect to perform any sort of arithmetic on this offset;
-     * it is just a cookie which is passed to the unsafe heap memory accessors.
-     *
-     * <p>Any given field will always have the same offset and base, and no
-     * two distinct fields of the same class will ever have the same offset
-     * and base.
-     *
-     * <p>As of 1.4.1, offsets for fields are represented as long values,
-     * although the Sun JVM does not use the most significant 32 bits.
-     * However, JVM implementations which store static fields at absolute
-     * addresses can use long offsets and null base pointers to express
-     * the field locations in a form usable by {@link #getInt(Object,long)}.
-     * Therefore, code which will be ported to such JVMs on 64-bit platforms
-     * must preserve all bits of static field offsets.
-     * @see #getInt(Object, long)
-     */
-    @ForceInline
-    public long objectFieldOffset(Field f) {
-        return theInternalUnsafe.objectFieldOffset(f);
-    }
-
-    /**
-     * Reports the location of a given static field, in conjunction with {@link
-     * #staticFieldBase}.
-     * <p>Do not expect to perform any sort of arithmetic on this offset;
-     * it is just a cookie which is passed to the unsafe heap memory accessors.
-     *
-     * <p>Any given field will always have the same offset, and no two distinct
-     * fields of the same class will ever have the same offset.
-     *
-     * <p>As of 1.4.1, offsets for fields are represented as long values,
-     * although the Sun JVM does not use the most significant 32 bits.
-     * It is hard to imagine a JVM technology which needs more than
-     * a few bits to encode an offset within a non-array object,
-     * However, for consistency with other methods in this class,
-     * this method reports its result as a long value.
-     * @see #getInt(Object, long)
-     */
-    @ForceInline
-    public long staticFieldOffset(Field f) {
-        return theInternalUnsafe.staticFieldOffset(f);
-    }
-
-    /**
-     * Reports the location of a given static field, in conjunction with {@link
-     * #staticFieldOffset}.
-     * <p>Fetch the base "Object", if any, with which static fields of the
-     * given class can be accessed via methods like {@link #getInt(Object,
-     * long)}.  This value may be null.  This value may refer to an object
-     * which is a "cookie", not guaranteed to be a real Object, and it should
-     * not be used in any way except as argument to the get and put routines in
-     * this class.
-     */
-    @ForceInline
-    public Object staticFieldBase(Field f) {
-        return theInternalUnsafe.staticFieldBase(f);
-    }
-
-    /**
-     * Detects if the given class may need to be initialized. This is often
-     * needed in conjunction with obtaining the static field base of a
-     * class.
-     * @return false only if a call to {@code ensureClassInitialized} would have no effect
-     */
-    @ForceInline
-    public boolean shouldBeInitialized(Class<?> c) {
-        return theInternalUnsafe.shouldBeInitialized(c);
-    }
-
-    /**
-     * Ensures the given class has been initialized. This is often
-     * needed in conjunction with obtaining the static field base of a
-     * class.
-     */
-    @ForceInline
-    public void ensureClassInitialized(Class<?> c) {
-        theInternalUnsafe.ensureClassInitialized(c);
-    }
-
-    /**
-     * Reports the offset of the first element in the storage allocation of a
-     * given array class.  If {@link #arrayIndexScale} returns a non-zero value
-     * for the same class, you may use that scale factor, together with this
-     * base offset, to form new offsets to access elements of arrays of the
-     * given class.
-     *
-     * @see #getInt(Object, long)
-     * @see #putInt(Object, long, int)
-     */
-    @ForceInline
-    public int arrayBaseOffset(Class<?> arrayClass) {
-        return theInternalUnsafe.arrayBaseOffset(arrayClass);
-    }
-
-    /** The value of {@code arrayBaseOffset(boolean[].class)} */
-    public static final int ARRAY_BOOLEAN_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(byte[].class)} */
-    public static final int ARRAY_BYTE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(short[].class)} */
-    public static final int ARRAY_SHORT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(char[].class)} */
-    public static final int ARRAY_CHAR_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_CHAR_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(int[].class)} */
-    public static final int ARRAY_INT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_INT_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(long[].class)} */
-    public static final int ARRAY_LONG_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_LONG_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(float[].class)} */
-    public static final int ARRAY_FLOAT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_FLOAT_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(double[].class)} */
-    public static final int ARRAY_DOUBLE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
-
-    /** The value of {@code arrayBaseOffset(Object[].class)} */
-    public static final int ARRAY_OBJECT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_OBJECT_BASE_OFFSET;
-
-    /**
-     * Reports the scale factor for addressing elements in the storage
-     * allocation of a given array class.  However, arrays of "narrow" types
-     * will generally not work properly with accessors like {@link
-     * #getByte(Object, long)}, so the scale factor for such classes is reported
-     * as zero.
-     *
-     * @see #arrayBaseOffset
-     * @see #getInt(Object, long)
-     * @see #putInt(Object, long, int)
-     */
-    @ForceInline
-    public int arrayIndexScale(Class<?> arrayClass) {
-        return theInternalUnsafe.arrayIndexScale(arrayClass);
-    }
-
-    /** The value of {@code arrayIndexScale(boolean[].class)} */
-    public static final int ARRAY_BOOLEAN_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(byte[].class)} */
-    public static final int ARRAY_BYTE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(short[].class)} */
-    public static final int ARRAY_SHORT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(char[].class)} */
-    public static final int ARRAY_CHAR_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_CHAR_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(int[].class)} */
-    public static final int ARRAY_INT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_INT_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(long[].class)} */
-    public static final int ARRAY_LONG_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_LONG_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(float[].class)} */
-    public static final int ARRAY_FLOAT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_FLOAT_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(double[].class)} */
-    public static final int ARRAY_DOUBLE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
-
-    /** The value of {@code arrayIndexScale(Object[].class)} */
-    public static final int ARRAY_OBJECT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_OBJECT_INDEX_SCALE;
-
-    /**
-     * Reports the size in bytes of a native pointer, as stored via {@link
-     * #putAddress}.  This value will be either 4 or 8.  Note that the sizes of
-     * other primitive types (as stored in native memory blocks) is determined
-     * fully by their information content.
-     */
-    @ForceInline
-    public int addressSize() {
-        return theInternalUnsafe.addressSize();
-    }
-
-    /** The value of {@code addressSize()} */
-    public static final int ADDRESS_SIZE = theInternalUnsafe.addressSize();
-
-    /**
-     * Reports the size in bytes of a native memory page (whatever that is).
-     * This value will always be a power of two.
-     */
-    @ForceInline
-    public int pageSize() {
-        return theInternalUnsafe.pageSize();
-    }
-
-
-    /// random trusted operations from JNI:
-
-    /**
-     * Tells the VM to define a class, without security checks.  By default, the
-     * class loader and protection domain come from the caller's class.
-     */
-    @ForceInline
-    public Class<?> defineClass(String name, byte[] b, int off, int len,
-                                ClassLoader loader,
-                                ProtectionDomain protectionDomain) {
-        return theInternalUnsafe.defineClass(name, b, off, len, loader, protectionDomain);
-    }
-
-    /**
-     * Defines a class but does not make it known to the class loader or system dictionary.
-     * <p>
-     * For each CP entry, the corresponding CP patch must either be null or have
-     * the a format that matches its tag:
-     * <ul>
-     * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang
-     * <li>Utf8: a string (must have suitable syntax if used as signature or name)
-     * <li>Class: any java.lang.Class object
-     * <li>String: any object (not just a java.lang.String)
-     * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments
-     * </ul>
-     * @param hostClass context for linkage, access control, protection domain, and class loader
-     * @param data      bytes of a class file
-     * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data
-     */
-    @ForceInline
-    public Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches) {
-        return theInternalUnsafe.defineAnonymousClass(hostClass, data, cpPatches);
-    }
-
-    /**
-     * Allocates an instance but does not run any constructor.
-     * Initializes the class if it has not yet been.
-     */
-    @ForceInline
-    public Object allocateInstance(Class<?> cls)
-        throws InstantiationException {
-        return theInternalUnsafe.allocateInstance(cls);
-    }
-
-    /** Throws the exception without telling the verifier. */
-    @ForceInline
-    public void throwException(Throwable ee) {
-        theInternalUnsafe.throwException(ee);
-    }
-
-    /**
-     * Atomically updates Java variable to {@code x} if it is currently
-     * holding {@code expected}.
-     *
-     * <p>This operation has memory semantics of a {@code volatile} read
-     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
-     *
-     * @return {@code true} if successful
-     */
-    @ForceInline
-    public final boolean compareAndSwapObject(Object o, long offset,
-                                              Object expected,
-                                              Object x) {
-        return theInternalUnsafe.compareAndSwapObject(o, offset, expected, x);
-    }
-
-    /**
-     * Atomically updates Java variable to {@code x} if it is currently
-     * holding {@code expected}.
-     *
-     * <p>This operation has memory semantics of a {@code volatile} read
-     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
-     *
-     * @return {@code true} if successful
-     */
-    @ForceInline
-    public final boolean compareAndSwapInt(Object o, long offset,
-                                           int expected,
-                                           int x) {
-        return theInternalUnsafe.compareAndSwapInt(o, offset, expected, x);
-    }
-
-    /**
-     * Atomically updates Java variable to {@code x} if it is currently
-     * holding {@code expected}.
-     *
-     * <p>This operation has memory semantics of a {@code volatile} read
-     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
-     *
-     * @return {@code true} if successful
-     */
-    @ForceInline
-    public final boolean compareAndSwapLong(Object o, long offset,
-                                            long expected,
-                                            long x) {
-        return theInternalUnsafe.compareAndSwapLong(o, offset, expected, x);
-    }
-
-    /**
-     * Fetches a reference value from a given Java variable, with volatile
-     * load semantics. Otherwise identical to {@link #getObject(Object, long)}
-     */
-    @ForceInline
-    public Object getObjectVolatile(Object o, long offset) {
-        return theInternalUnsafe.getObjectVolatile(o, offset);
-    }
-
-    /**
-     * Stores a reference value into a given Java variable, with
-     * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
-     */
-    @ForceInline
-    public void putObjectVolatile(Object o, long offset, Object x) {
-        theInternalUnsafe.putObjectVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getInt(Object, long)}  */
-    @ForceInline
-    public int getIntVolatile(Object o, long offset) {
-        return theInternalUnsafe.getIntVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putInt(Object, long, int)}  */
-    @ForceInline
-    public void putIntVolatile(Object o, long offset, int x) {
-        theInternalUnsafe.putIntVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getBoolean(Object, long)}  */
-    @ForceInline
-    public boolean getBooleanVolatile(Object o, long offset) {
-        return theInternalUnsafe.getBooleanVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putBoolean(Object, long, boolean)}  */
-    @ForceInline
-    public void putBooleanVolatile(Object o, long offset, boolean x) {
-        theInternalUnsafe.putBooleanVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getByte(Object, long)}  */
-    @ForceInline
-    public byte getByteVolatile(Object o, long offset) {
-        return theInternalUnsafe.getByteVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putByte(Object, long, byte)}  */
-    @ForceInline
-    public void putByteVolatile(Object o, long offset, byte x) {
-        theInternalUnsafe.putByteVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getShort(Object, long)}  */
-    @ForceInline
-    public short getShortVolatile(Object o, long offset) {
-        return theInternalUnsafe.getShortVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putShort(Object, long, short)}  */
-    @ForceInline
-    public void putShortVolatile(Object o, long offset, short x) {
-        theInternalUnsafe.putShortVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getChar(Object, long)}  */
-    @ForceInline
-    public char getCharVolatile(Object o, long offset) {
-        return theInternalUnsafe.getCharVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putChar(Object, long, char)}  */
-    @ForceInline
-    public void putCharVolatile(Object o, long offset, char x) {
-        theInternalUnsafe.putCharVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getLong(Object, long)}  */
-    @ForceInline
-    public long getLongVolatile(Object o, long offset) {
-        return theInternalUnsafe.getLongVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putLong(Object, long, long)}  */
-    @ForceInline
-    public void putLongVolatile(Object o, long offset, long x) {
-        theInternalUnsafe.putLongVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getFloat(Object, long)}  */
-    @ForceInline
-    public float getFloatVolatile(Object o, long offset) {
-        return theInternalUnsafe.getFloatVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putFloat(Object, long, float)}  */
-    @ForceInline
-    public void putFloatVolatile(Object o, long offset, float x) {
-        theInternalUnsafe.putFloatVolatile(o, offset, x);
-    }
-
-    /** Volatile version of {@link #getDouble(Object, long)}  */
-    @ForceInline
-    public double getDoubleVolatile(Object o, long offset) {
-        return theInternalUnsafe.getDoubleVolatile(o, offset);
-    }
-
-    /** Volatile version of {@link #putDouble(Object, long, double)}  */
-    @ForceInline
-    public void putDoubleVolatile(Object o, long offset, double x) {
-        theInternalUnsafe.putDoubleVolatile(o, offset, x);
-    }
-
-    /**
-     * Version of {@link #putObjectVolatile(Object, long, Object)}
-     * that does not guarantee immediate visibility of the store to
-     * other threads. This method is generally only useful if the
-     * underlying field is a Java volatile (or if an array cell, one
-     * that is otherwise only accessed using volatile accesses).
-     *
-     * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
-     */
-    @ForceInline
-    public void putOrderedObject(Object o, long offset, Object x) {
-        theInternalUnsafe.putOrderedObject(o, offset, x);
-    }
-
-    /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
-    @ForceInline
-    public void putOrderedInt(Object o, long offset, int x) {
-        theInternalUnsafe.putOrderedInt(o, offset, x);
-    }
-
-    /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
-    @ForceInline
-    public void putOrderedLong(Object o, long offset, long x) {
-        theInternalUnsafe.putOrderedLong(o, offset, x);
-    }
-
-    /**
-     * Unblocks the given thread blocked on {@code park}, or, if it is
-     * not blocked, causes the subsequent call to {@code park} not to
-     * block.  Note: this operation is "unsafe" solely because the
-     * caller must somehow ensure that the thread has not been
-     * destroyed. Nothing special is usually required to ensure this
-     * when called from Java (in which there will ordinarily be a live
-     * reference to the thread) but this is not nearly-automatically
-     * so when calling from native code.
-     *
-     * @param thread the thread to unpark.
-     */
-    @ForceInline
-    public void unpark(Object thread) {
-        theInternalUnsafe.unpark(thread);
-    }
-
-    /**
-     * Blocks current thread, returning when a balancing
-     * {@code unpark} occurs, or a balancing {@code unpark} has
-     * already occurred, or the thread is interrupted, or, if not
-     * absolute and time is not zero, the given time nanoseconds have
-     * elapsed, or if absolute, the given deadline in milliseconds
-     * since Epoch has passed, or spuriously (i.e., returning for no
-     * "reason"). Note: This operation is in the Unsafe class only
-     * because {@code unpark} is, so it would be strange to place it
-     * elsewhere.
-     */
-    @ForceInline
-    public void park(boolean isAbsolute, long time) {
-        theInternalUnsafe.park(isAbsolute, time);
-    }
-
-    /**
-     * Gets the load average in the system run queue assigned
-     * to the available processors averaged over various periods of time.
-     * This method retrieves the given {@code nelem} samples and
-     * assigns to the elements of the given {@code loadavg} array.
-     * The system imposes a maximum of 3 samples, representing
-     * averages over the last 1,  5,  and  15 minutes, respectively.
-     *
-     * @param loadavg an array of double of size nelems
-     * @param nelems the number of samples to be retrieved and
-     *        must be 1 to 3.
-     *
-     * @return the number of samples actually retrieved; or -1
-     *         if the load average is unobtainable.
-     */
-    @ForceInline
-    public int getLoadAverage(double[] loadavg, int nelems) {
-        return theInternalUnsafe.getLoadAverage(loadavg, nelems);
-    }
-
-    // The following contain CAS-based Java implementations used on
-    // platforms not supporting native instructions
-
-    /**
-     * Atomically adds the given value to the current value of a field
-     * or array element within the given object {@code o}
-     * at the given {@code offset}.
-     *
-     * @param o object/array to update the field/element in
-     * @param offset field/element offset
-     * @param delta the value to add
-     * @return the previous value
-     * @since 1.8
-     */
-    @ForceInline
-    public final int getAndAddInt(Object o, long offset, int delta) {
-        return theInternalUnsafe.getAndAddInt(o, offset, delta);
-    }
-
-    /**
-     * Atomically adds the given value to the current value of a field
-     * or array element within the given object {@code o}
-     * at the given {@code offset}.
-     *
-     * @param o object/array to update the field/element in
-     * @param offset field/element offset
-     * @param delta the value to add
-     * @return the previous value
-     * @since 1.8
-     */
-    @ForceInline
-    public final long getAndAddLong(Object o, long offset, long delta) {
-        return theInternalUnsafe.getAndAddLong(o, offset, delta);
-    }
-
-    /**
-     * Atomically exchanges the given value with the current value of
-     * a field or array element within the given object {@code o}
-     * at the given {@code offset}.
-     *
-     * @param o object/array to update the field/element in
-     * @param offset field/element offset
-     * @param newValue new value
-     * @return the previous value
-     * @since 1.8
-     */
-    @ForceInline
-    public final int getAndSetInt(Object o, long offset, int newValue) {
-        return theInternalUnsafe.getAndSetInt(o, offset, newValue);
-    }
-
-    /**
-     * Atomically exchanges the given value with the current value of
-     * a field or array element within the given object {@code o}
-     * at the given {@code offset}.
-     *
-     * @param o object/array to update the field/element in
-     * @param offset field/element offset
-     * @param newValue new value
-     * @return the previous value
-     * @since 1.8
-     */
-    @ForceInline
-    public final long getAndSetLong(Object o, long offset, long newValue) {
-        return theInternalUnsafe.getAndSetLong(o, offset, newValue);
-    }
-
-    /**
-     * Atomically exchanges the given reference value with the current
-     * reference value of a field or array element within the given
-     * object {@code o} at the given {@code offset}.
-     *
-     * @param o object/array to update the field/element in
-     * @param offset field/element offset
-     * @param newValue new value
-     * @return the previous value
-     * @since 1.8
-     */
-    @ForceInline
-    public final Object getAndSetObject(Object o, long offset, Object newValue) {
-        return theInternalUnsafe.getAndSetObject(o, offset, newValue);
-    }
-
-
-    /**
-     * Ensures that loads before the fence will not be reordered with loads and
-     * stores after the fence; a "LoadLoad plus LoadStore barrier".
-     *
-     * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
-     * (an "acquire fence").
-     *
-     * A pure LoadLoad fence is not provided, since the addition of LoadStore
-     * is almost always desired, and most current hardware instructions that
-     * provide a LoadLoad barrier also provide a LoadStore barrier for free.
-     * @since 1.8
-     */
-    @ForceInline
-    public void loadFence() {
-        theInternalUnsafe.loadFence();
-    }
-
-    /**
-     * Ensures that loads and stores before the fence will not be reordered with
-     * stores after the fence; a "StoreStore plus LoadStore barrier".
-     *
-     * Corresponds to C11 atomic_thread_fence(memory_order_release)
-     * (a "release fence").
-     *
-     * A pure StoreStore fence is not provided, since the addition of LoadStore
-     * is almost always desired, and most current hardware instructions that
-     * provide a StoreStore barrier also provide a LoadStore barrier for free.
-     * @since 1.8
-     */
-    @ForceInline
-    public void storeFence() {
-        theInternalUnsafe.storeFence();
-    }
-
-    /**
-     * Ensures that loads and stores before the fence will not be reordered
-     * with loads and stores after the fence.  Implies the effects of both
-     * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
-     * barrier.
-     *
-     * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
-     * @since 1.8
-     */
-    @ForceInline
-    public void fullFence() {
-        theInternalUnsafe.fullFence();
-    }
-}
--- a/src/java.base/share/classes/sun/net/TransferProtocolClient.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/sun/net/TransferProtocolClient.java	Mon Apr 11 11:19:33 2016 -0700
@@ -83,7 +83,7 @@
                     code = Integer.parseInt(response, 0, 3, 10);
                 } catch (NumberFormatException e) {
                     code = -1;
-                } catch (StringIndexOutOfBoundsException e) {
+                } catch (IndexOutOfBoundsException e) {
                     /* this line doesn't contain a response code, so
                        we just completely ignore it */
                     continue;
--- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java	Mon Apr 11 11:19:33 2016 -0700
@@ -440,7 +440,7 @@
                     code = Integer.parseInt(response, 0, 3, 10);
                 } catch (NumberFormatException e) {
                     code = -1;
-                } catch (StringIndexOutOfBoundsException e) {
+                } catch (IndexOutOfBoundsException e) {
                     /* this line doesn't contain a response code, so
                     we just completely ignore it */
                     continue;
--- a/src/java.base/share/classes/sun/net/spi/nameservice/NameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.spi.nameservice;
-
-import java.net.UnknownHostException;
-
-public interface NameService {
-    public java.net.InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException;
-    public String getHostByAddr(byte[] addr) throws UnknownHostException;
-}
--- a/src/java.base/share/classes/sun/net/spi/nameservice/NameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.spi.nameservice;
-
-public interface NameServiceDescriptor {
-    /**
-     * Create a new instance of the corresponding name service.
-     */
-    public NameService createNameService () throws Exception ;
-
-    /**
-     * Returns this service provider's name
-     *
-     */
-    public String getProviderName();
-
-    /**
-     * Returns this name service type
-     * "dns" "nis" etc
-     */
-    public String getType();
-}
--- a/src/java.base/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,8 +25,6 @@
 
 package sun.nio.ch;
 
-import sun.misc.*;
-
 
 /**
  * Manipulates a native array of pollfd structs.
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1198,8 +1198,9 @@
             if (!localSupportedSignAlgs.contains(
                     preferableSignatureAlgorithm)) {
                 throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message");
+                    "Unsupported SignatureAndHashAlgorithm in " +
+                    "ServerKeyExchange message: " +
+                    preferableSignatureAlgorithm);
             }
         } else {
             this.preferableSignatureAlgorithm = null;
@@ -1232,7 +1233,8 @@
                         sig = RSASignature.getInstance();
                         break;
                     default:
-                        throw new SSLKeyException("neither an RSA or a DSA key");
+                        throw new SSLKeyException(
+                            "neither an RSA or a DSA key: " + algorithm);
                 }
         }
 
@@ -1482,7 +1484,8 @@
                     preferableSignatureAlgorithm)) {
                 throw new SSLHandshakeException(
                         "Unsupported SignatureAndHashAlgorithm in " +
-                        "ServerKeyExchange message");
+                        "ServerKeyExchange message: " +
+                        preferableSignatureAlgorithm);
             }
         }
 
@@ -1522,7 +1525,8 @@
                 case "RSA":
                     return RSASignature.getInstance();
                 default:
-                    throw new NoSuchAlgorithmException("neither an RSA or a EC key");
+                    throw new NoSuchAlgorithmException(
+                        "neither an RSA or a EC key : " + keyAlgorithm);
             }
     }
 
@@ -1729,7 +1733,8 @@
             algorithmsLen = input.getInt16();
             if (algorithmsLen < 2) {
                 throw new SSLProtocolException(
-                        "Invalid supported_signature_algorithms field");
+                    "Invalid supported_signature_algorithms field: " +
+                    algorithmsLen);
             }
 
             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
@@ -1748,7 +1753,8 @@
 
             if (remains != 0) {
                 throw new SSLProtocolException(
-                        "Invalid supported_signature_algorithms field");
+                    "Invalid supported_signature_algorithms field. remains: " +
+                    remains);
             }
         } else {
             algorithms = new ArrayList<SignatureAndHashAlgorithm>();
@@ -1765,7 +1771,8 @@
         }
 
         if (len != 0) {
-            throw new SSLProtocolException("Bad CertificateRequest DN length");
+            throw new SSLProtocolException(
+                "Bad CertificateRequest DN length: " + len);
         }
 
         authorities = v.toArray(new DistinguishedName[v.size()]);
@@ -1995,8 +2002,8 @@
             if (!localSupportedSignAlgs.contains(
                     preferableSignatureAlgorithm)) {
                 throw new SSLHandshakeException(
-                        "Unsupported SignatureAndHashAlgorithm in " +
-                        "CertificateVerify message");
+                    "Unsupported SignatureAndHashAlgorithm in " +
+                    "CertificateVerify message: " + preferableSignatureAlgorithm);
             }
         }
 
@@ -2364,7 +2371,8 @@
                 SecretKey prfKey = kg.generateKey();
                 if ("RAW".equals(prfKey.getFormat()) == false) {
                     throw new ProviderException(
-                        "Invalid PRF output, format must be RAW");
+                        "Invalid PRF output, format must be RAW. " +
+                        "Format received: " + prfKey.getFormat());
                 }
                 byte[] finished = prfKey.getEncoded();
                 return finished;
--- a/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java	Mon Apr 11 11:19:33 2016 -0700
@@ -68,7 +68,8 @@
             ProtocolVersion maxVersion,
             SecureRandom generator, PublicKey publicKey) throws IOException {
         if (publicKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Public key not of type RSA");
+            throw new SSLKeyException("Public key not of type RSA: " +
+                publicKey.getAlgorithm());
         }
         this.protocolVersion = protocolVersion;
 
@@ -100,7 +101,8 @@
             int messageSize, PrivateKey privateKey) throws IOException {
 
         if (privateKey.getAlgorithm().equals("RSA") == false) {
-            throw new SSLKeyException("Private key not of type RSA");
+            throw new SSLKeyException("Private key not of type RSA: " +
+                 privateKey.getAlgorithm());
         }
 
         if (currentVersion.useTLS10PlusSpec()) {
@@ -161,8 +163,8 @@
             }
         } catch (InvalidKeyException ibk) {
             // the message is too big to process with RSA
-            throw new SSLProtocolException(
-                "Unable to process PreMasterSecret, may be too big");
+            throw new SSLException(
+                "Unable to process PreMasterSecret", ibk);
         } catch (Exception e) {
             // unlikely to happen, otherwise, must be a provider exception
             if (debug != null && Debug.isOn("handshake")) {
--- a/src/java.base/share/native/libjava/jdk_util.c	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/share/native/libjava/jdk_util.c	Mon Apr 11 11:19:33 2016 -0700
@@ -47,7 +47,7 @@
                         (version_build & 0xFF);
     info->patch_version = version_patch;
     info->thread_park_blocker = 1;
-    // Advertise presence of sun.misc.PostVMInitHook:
+    // Advertise presence of PostVMInitHook:
     // future optimization: detect if this is enabled.
     info->post_vm_init_hook_enabled = 1;
     info->pending_list_uses_discovered_field = 1;
--- a/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Mon Apr 11 11:19:33 2016 -0700
@@ -29,7 +29,6 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
-import sun.misc.*;
 
 
 /**
--- a/src/java.base/unix/classes/sun/misc/GThreadHelper.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * This class is used to prevent multiple calling of g_thread_init ()
- * and gdk_thread_init ().
- *
- * Since version 2.24 of GLib, calling g_thread_init () multiple times is
- * allowed, but it will crash for older versions. There are two ways to
- * find out if g_thread_init () has been called:
- * g_thread_get_initialized (), but it was introduced in 2.20
- * g_thread_supported (), but it is a macro and cannot be loaded with dlsym.
- *
- * usage:
- * <pre>
- * lock();
- * try {
- *    if (!getAndSetInitializationNeededFlag()) {
- *        //call to g_thread_init();
- *        //call to gdk_thread_init();
- *    }
- * } finally {
- *    unlock();
- * }
- * </pre>
- */
-public final class GThreadHelper {
-
-    private static final ReentrantLock LOCK = new ReentrantLock();
-    private static boolean isGThreadInitialized = false;
-
-    /**
-     * Acquires the lock.
-     */
-    public static void lock() {
-        LOCK.lock();
-    }
-
-    /**
-     * Releases the lock.
-     */
-    public static void unlock() {
-        LOCK.unlock();
-    }
-
-    /**
-     * Gets current value of initialization flag and sets it to {@code true}.
-     * MUST be called under the lock.
-     *
-     * A return value of {@code false} indicates that the calling code
-     * should call the g_thread_init() and gdk_thread_init() functions
-     * before releasing the lock.
-     *
-     * @return {@code true} if initialization has been completed.
-     */
-    public static boolean getAndSetInitializationNeededFlag() {
-        boolean ret = isGThreadInitialized;
-        isGThreadInitialized = true;
-        return ret;
-    }
-}
--- a/src/java.base/unix/classes/sun/nio/ch/PollArrayWrapper.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/unix/classes/sun/nio/ch/PollArrayWrapper.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,8 +25,6 @@
 
 package sun.nio.ch;
 
-import sun.misc.*;
-
 
 /**
  * Manipulates a native array of pollfd structs on Solaris:
--- a/src/java.base/unix/classes/sun/nio/fs/UnixException.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixException.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,6 +70,12 @@
         return errorString();
     }
 
+    @Override
+    public Throwable fillInStackTrace() {
+        // This is an internal exception; the stack trace is irrelevant.
+        return this;
+    }
+
     /**
      * Map well known errors to specific exceptions where possible; otherwise
      * return more general FileSystemException.
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsException.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsException.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,12 @@
         return errorString();
     }
 
+    @Override
+    public Throwable fillInStackTrace() {
+        // This is an internal exception; the stack trace is irrelevant.
+        return this;
+    }
+
     private IOException translateToIOException(String file, String other) {
         // not created with last error
         if (lastError() == 0)
--- a/src/java.compact3/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.compact3/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,7 +26,6 @@
 module java.compact3 {
     requires public java.compact2;
     requires public java.compiler;
-    requires public java.httpclient;
     requires public java.instrument;
     requires public java.management;
     requires public java.naming;
--- a/src/java.desktop/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.desktop/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -27,6 +27,8 @@
     requires public java.datatransfer;
     requires public java.xml;
     requires java.prefs;
+    // 8147544
+    requires jdk.unsupported;
 
     exports java.applet;
     exports java.awt;
--- a/src/java.logging/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.logging/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,6 +24,8 @@
  */
 
 module java.logging {
+    // 8153158
+    requires jdk.unsupported;
     exports java.util.logging;
     provides jdk.internal.logger.DefaultLoggerFinder with
         sun.util.logging.internal.LoggingProviderImpl;
--- a/src/java.management/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.management/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -27,6 +27,8 @@
     requires public java.rmi;
     requires java.logging;
     requires java.naming;
+    // 8147553
+    requires jdk.unsupported;
 
     exports java.lang.management;
     exports javax.management;
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Mon Apr 11 11:19:33 2016 -0700
@@ -2978,7 +2978,8 @@
             r = new LdapReferralException(resolvedName, resolvedObj, remainName,
                 msg, envprops, fullDN, handleReferrals, reqCtls);
             // only one set of URLs is present
-            r.setReferralInfo(res.referrals.elementAt(0), false);
+            r.setReferralInfo(res.referrals == null ? null :
+                    res.referrals.elementAt(0), false);
 
             if (hopCount > 1) {
                 r.setHopCount(hopCount);
@@ -3047,7 +3048,7 @@
              *     assume name resolution has not yet completed.
              */
             if (((res.entries == null) || (res.entries.isEmpty())) &&
-                (res.referrals.size() == 1)) {
+                ((res.referrals != null) && (res.referrals.size() == 1))) {
 
                 r.setReferralInfo(res.referrals, false);
 
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralException.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralException.java	Mon Apr 11 11:19:33 2016 -0700
@@ -217,13 +217,15 @@
             System.out.println("LdapReferralException.setReferralInfo");
 
         this.referrals = referrals;
-        if (referrals != null) {
-            referralCount = referrals.size();
-        }
+        referralCount = (referrals == null) ? 0 : referrals.size();
 
         if (debug) {
-            for (int i = 0; i < referralCount; i++) {
-                System.out.println("  [" + i + "] " + referrals.elementAt(i));
+            if (referrals != null) {
+                for (int i = 0; i < referralCount; i++) {
+                    System.out.println("  [" + i + "] " + referrals.elementAt(i));
+                }
+            } else {
+                System.out.println("setReferralInfo : referrals == null");
             }
         }
     }
--- a/src/java.se/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/java.se/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -27,4 +27,5 @@
     requires public java.compact3;
     requires public java.datatransfer;
     requires public java.desktop;
+    requires public java.httpclient;
 }
--- a/src/jdk.crypto.pkcs11/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.crypto.pkcs11/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,6 +26,8 @@
 module jdk.crypto.pkcs11 {
     // Depends on SunEC provider for EC related functionality
     requires jdk.crypto.ec;
+    // 8153371
+    requires jdk.unsupported;
     provides java.security.Provider with sun.security.pkcs11.SunPKCS11;
 }
 
--- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Key.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Key.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
+import sun.security.util.Debug;
 import sun.security.util.DerValue;
 import sun.security.util.Length;
 import sun.security.util.ECUtil;
@@ -1110,11 +1111,41 @@
     }
 
     private static void drainRefQueueBounded() {
+        Session sess = null;
+        Token tkn = null;
         while (true) {
             SessionKeyRef next = (SessionKeyRef) refQueue.poll();
-            if (next == null) break;
+            if (next == null) {
+                break;
+            }
+
+            // If the token is still valid, try to remove the object
+            if (next.session.token.isValid()) {
+                // If this key's token is the same as the previous key, the
+                // same session can be used for C_DestroyObject.
+                try {
+                    if (next.session.token != tkn || sess == null) {
+                        // Release session if not using previous token
+                        if (tkn != null && sess != null) {
+                            tkn.releaseSession(sess);
+                            sess = null;
+                        }
+
+                        tkn = next.session.token;
+                        sess = tkn.getOpSession();
+                    }
+                    next.disposeNative(sess);
+                } catch (PKCS11Exception e) {
+                    // ignore
+                }
+            }
+            // Regardless of native results, dispose of java references
             next.dispose();
         }
+
+        if (tkn != null && sess != null) {
+            tkn.releaseSession(sess);
+        }
     }
 
     // handle to the native key
@@ -1127,25 +1158,17 @@
         this.session = session;
         this.session.addObject();
         refList.add(this);
-        // TBD: run at some interval and not every time?
         drainRefQueueBounded();
     }
 
+    private void disposeNative(Session s) throws PKCS11Exception {
+        session.token.p11.C_DestroyObject(s.id(), keyID);
+    }
+
     private void dispose() {
         refList.remove(this);
-        if (session.token.isValid()) {
-            Session newSession = null;
-            try {
-                newSession = session.token.getOpSession();
-                session.token.p11.C_DestroyObject(newSession.id(), keyID);
-            } catch (PKCS11Exception e) {
-                // ignore
-            } finally {
-                this.clear();
-                session.token.releaseSession(newSession);
-                session.removeObject();
-            }
-        }
+        this.clear();
+        session.removeObject();
     }
 
     public int compareTo(SessionKeyRef other) {
--- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SessionManager.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SessionManager.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
-import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -112,8 +112,8 @@
         }
         maxSessions = (int)Math.min(n, Integer.MAX_VALUE);
         this.token = token;
-        this.objSessions = new Pool(this);
-        this.opSessions = new Pool(this);
+        this.objSessions = new Pool(this, true);
+        this.opSessions = new Pool(this, false);
         if (debug != null) {
             maxActiveSessionsLock = new Object();
         }
@@ -236,12 +236,18 @@
     public static final class Pool {
 
         private final SessionManager mgr;
-
-        private final ConcurrentLinkedDeque<Session> pool;
+        private final AbstractQueue<Session> pool;
+        private final int SESSION_MAX = 5;
 
-        Pool(SessionManager mgr) {
-           this.mgr = mgr;
-           pool = new ConcurrentLinkedDeque<Session>();
+        // Object session pools can contain unlimited sessions.
+        // Operation session pools are limited and enforced by the queue.
+        Pool(SessionManager mgr, boolean obj) {
+            this.mgr = mgr;
+            if (obj) {
+                pool = new LinkedBlockingQueue<Session>();
+            } else {
+                pool = new LinkedBlockingQueue<Session>(SESSION_MAX);
+            }
         }
 
         boolean remove(Session session) {
@@ -249,24 +255,24 @@
         }
 
         Session poll() {
-            return pool.pollLast();
+            return pool.poll();
         }
 
         void release(Session session) {
-            pool.offer(session);
-            if (session.hasObjects()) {
-                return;
+            // Object session pools never return false, only Operation ones
+            if (!pool.offer(session)) {
+                mgr.closeSession(session);
+                free();
             }
+        }
 
-            int n = pool.size();
-            if (n < 5) {
-                return;
-            }
-
+        // Free any old operation session if this queue is full
+        void free() {
+            int n = SESSION_MAX;
+            int i = 0;
             Session oldestSession;
             long time = System.currentTimeMillis();
-            int i = 0;
-            // Check if the session head is too old and continue through queue
+            // Check if the session head is too old and continue through pool
             // until only one is left.
             do {
                 oldestSession = pool.peek();
--- a/src/jdk.httpserver/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.httpserver/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,6 +25,8 @@
 
 module jdk.httpserver {
     requires java.logging;
+    // 8153372
+    requires jdk.unsupported;
     exports com.sun.net.httpserver;
     exports com.sun.net.httpserver.spi;
     uses com.sun.net.httpserver.spi.HttpServerProvider;
--- a/src/jdk.naming.dns/share/classes/module-info.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.naming.dns/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,5 @@
 
     provides javax.naming.spi.InitialContextFactory
         with com.sun.jndi.dns.DnsContextFactory;
-    provides sun.net.spi.nameservice.NameServiceDescriptor
-        with sun.net.spi.nameservice.dns.DNSNameServiceDescriptor;
 }
 
--- a/src/jdk.naming.dns/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,501 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.spi.nameservice.dns;
-
-import java.lang.ref.SoftReference;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import javax.naming.*;
-import javax.naming.directory.*;
-import javax.naming.spi.NamingManager;
-import java.util.*;
-import sun.net.util.IPAddressUtil;
-import sun.net.dns.ResolverConfiguration;
-import sun.net.spi.nameservice.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/*
- * A name service provider based on JNDI-DNS.
- */
-
-public final class DNSNameService implements NameService {
-
-    // List of domains specified by property
-    private LinkedList<String> domainList = null;
-
-    // JNDI-DNS URL for name servers specified via property
-    private String nameProviderUrl = null;
-
-    // Per-thread soft cache of the last temporary context
-    private static ThreadLocal<SoftReference<ThreadContext>> contextRef =
-            new ThreadLocal<>();
-
-    // Simple class to encapsulate the temporary context
-    private static class ThreadContext {
-        private DirContext dirCtxt;
-        private List<String> nsList;
-
-        public ThreadContext(DirContext dirCtxt, List<String> nsList) {
-            this.dirCtxt = dirCtxt;
-            this.nsList = nsList;
-        }
-
-        public DirContext dirContext() {
-            return dirCtxt;
-        }
-
-        public List<String> nameservers() {
-            return nsList;
-        }
-    }
-
-    // Returns a per-thread DirContext
-    private DirContext getTemporaryContext() throws NamingException {
-        SoftReference<ThreadContext> ref = contextRef.get();
-        ThreadContext thrCtxt = null;
-        List<String> nsList = null;
-
-        // if no property specified we need to obtain the list of servers
-        //
-        if (nameProviderUrl == null)
-            nsList = ResolverConfiguration.open().nameservers();
-
-        // if soft reference hasn't been gc'ed no property has been
-        // specified then we need to check if the DNS configuration
-        // has changed.
-        //
-        if ((ref != null) && ((thrCtxt = ref.get()) != null)) {
-            if (nameProviderUrl == null) {
-                if (!thrCtxt.nameservers().equals(nsList)) {
-                    // DNS configuration has changed
-                    thrCtxt = null;
-                }
-            }
-        }
-
-        // new thread context needs to be created
-        if (thrCtxt == null) {
-            final Hashtable<String,Object> env = new Hashtable<>();
-            env.put("java.naming.factory.initial",
-                    "com.sun.jndi.dns.DnsContextFactory");
-
-            // If no nameservers property specified we create provider URL
-            // based on system configured name servers
-            //
-            String provUrl = nameProviderUrl;
-            if (provUrl == null) {
-                provUrl = createProviderURL(nsList);
-                if (provUrl.length() == 0) {
-                    throw new RuntimeException("bad nameserver configuration");
-                }
-            }
-            env.put("java.naming.provider.url", provUrl);
-
-            // Need to create directory context in privileged block
-            // as JNDI-DNS needs to resolve the name servers.
-            //
-            DirContext dirCtxt;
-            try {
-                dirCtxt = java.security.AccessController.doPrivileged(
-                        new java.security.PrivilegedExceptionAction<DirContext>() {
-                            public DirContext run() throws NamingException {
-                                // Create the DNS context using NamingManager rather than using
-                                // the initial context constructor. This avoids having the initial
-                                // context constructor call itself.
-                                Context ctx = NamingManager.getInitialContext(env);
-                                if (!(ctx instanceof DirContext)) {
-                                    return null; // cannot create a DNS context
-                                }
-                                return (DirContext)ctx;
-                            }
-                    });
-            } catch (java.security.PrivilegedActionException pae) {
-                throw (NamingException)pae.getException();
-            }
-
-            // create new soft reference to our thread context
-            //
-            thrCtxt = new ThreadContext(dirCtxt, nsList);
-            contextRef.set(new SoftReference<ThreadContext>(thrCtxt));
-        }
-
-        return thrCtxt.dirContext();
-    }
-
-    /**
-     * Resolves the specified entry in DNS.
-     *
-     * Canonical name records are recursively resolved (to a maximum
-     * of 5 to avoid performance hit and potential CNAME loops).
-     *
-     * @param   ctx     JNDI directory context
-     * @param   name    name to resolve
-     * @param   ids     record types to search
-     * @param   depth   call depth - pass as 0.
-     *
-     * @return  array list with results (will have at least on entry)
-     *
-     * @throws  UnknownHostException if lookup fails or other error.
-     */
-    private ArrayList<String> resolve(final DirContext ctx, final String name,
-                                      final String[] ids, int depth)
-            throws UnknownHostException
-    {
-        ArrayList<String> results = new ArrayList<>();
-        Attributes attrs;
-
-        // do the query
-        try {
-            attrs = java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedExceptionAction<Attributes>() {
-                        public Attributes run() throws NamingException {
-                            return ctx.getAttributes(name, ids);
-                        }
-                });
-        } catch (java.security.PrivilegedActionException pae) {
-            throw new UnknownHostException(pae.getException().getMessage());
-        }
-
-        // non-requested type returned so enumeration is empty
-        NamingEnumeration<? extends Attribute> ne = attrs.getAll();
-        if (!ne.hasMoreElements()) {
-            throw new UnknownHostException("DNS record not found");
-        }
-
-        // iterate through the returned attributes
-        UnknownHostException uhe = null;
-        try {
-            while (ne.hasMoreElements()) {
-                Attribute attr = ne.next();
-                String attrID = attr.getID();
-
-                for (NamingEnumeration<?> e = attr.getAll(); e.hasMoreElements();) {
-                    String addr = (String)e.next();
-
-                    // for canoncical name records do recursive lookup
-                    // - also check for CNAME loops to avoid stack overflow
-
-                    if (attrID.equals("CNAME")) {
-                        if (depth > 4) {
-                            throw new UnknownHostException(name + ": possible CNAME loop");
-                        }
-                        try {
-                            results.addAll(resolve(ctx, addr, ids, depth+1));
-                        } catch (UnknownHostException x) {
-                            // canonical name can't be resolved.
-                            if (uhe == null)
-                                uhe = x;
-                        }
-                    } else {
-                        results.add(addr);
-                    }
-                }
-            }
-        } catch (NamingException nx) {
-            throw new UnknownHostException(nx.getMessage());
-        }
-
-        // pending exception as canonical name could not be resolved.
-        if (results.isEmpty() && uhe != null) {
-            throw uhe;
-        }
-
-        return results;
-    }
-
-    public DNSNameService() throws Exception {
-
-        // default domain
-        String domain = AccessController.doPrivileged(
-            (PrivilegedAction<String>) () -> System.getProperty("sun.net.spi.nameservice.domain"));
-        if (domain != null && domain.length() > 0) {
-            domainList = new LinkedList<String>();
-            domainList.add(domain);
-        }
-
-        // name servers
-        String nameservers = AccessController.doPrivileged(
-            (PrivilegedAction<String>) () -> System.getProperty("sun.net.spi.nameservice.nameservers"));
-        if (nameservers != null && nameservers.length() > 0) {
-            nameProviderUrl = createProviderURL(nameservers);
-            if (nameProviderUrl.length() == 0) {
-                throw new RuntimeException("malformed nameservers property");
-            }
-
-        } else {
-
-            // no property specified so check host DNS resolver configured
-            // with at least one nameserver in dotted notation.
-            //
-            List<String> nsList = ResolverConfiguration.open().nameservers();
-            if (nsList.isEmpty()) {
-                throw new RuntimeException("no nameservers provided");
-            }
-            boolean found = false;
-            for (String addr: nsList) {
-                if (IPAddressUtil.isIPv4LiteralAddress(addr) ||
-                    IPAddressUtil.isIPv6LiteralAddress(addr)) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                throw new RuntimeException("bad nameserver configuration");
-            }
-        }
-    }
-
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-
-        // DNS records that we search for
-        String[] ids = {"A", "AAAA", "CNAME"};
-
-        // first get directory context
-        DirContext ctx;
-        try {
-            ctx = getTemporaryContext();
-        } catch (NamingException nx) {
-            throw new Error(nx);
-        }
-
-        ArrayList<String> results = null;
-        UnknownHostException uhe = null;
-
-        // If host already contains a domain name then just look it up
-        if (host.indexOf('.') >= 0) {
-            try {
-                results = resolve(ctx, host, ids, 0);
-            } catch (UnknownHostException x) {
-                uhe = x;
-            }
-        }
-
-        // Here we try to resolve the host using the domain suffix or
-        // the domain suffix search list. If the host cannot be resolved
-        // using the domain suffix then we attempt devolution of
-        // the suffix - eg: if we are searching for "foo" and our
-        // domain suffix is "eng.sun.com" we will try to resolve
-        // "foo.eng.sun.com" and "foo.sun.com".
-        // It's not normal to attempt devolation with domains on the
-        // domain suffix search list - however as ResolverConfiguration
-        // doesn't distinguish domain or search list in the list it
-        // returns we approximate by doing devolution on the domain
-        // suffix if the list has one entry.
-
-        if (results == null) {
-            List<String> searchList = null;
-            Iterator<String> i;
-            boolean usingSearchList = false;
-
-            if (domainList != null) {
-                i = domainList.iterator();
-            } else {
-                searchList = ResolverConfiguration.open().searchlist();
-                if (searchList.size() > 1) {
-                    usingSearchList = true;
-                }
-                i = searchList.iterator();
-            }
-
-            // iterator through each domain suffix
-            while (i.hasNext()) {
-                String parentDomain = i.next();
-                int start = 0;
-                while ((start = parentDomain.indexOf('.')) != -1
-                       && start < parentDomain.length() -1) {
-                    try {
-                        results = resolve(ctx, host+"."+parentDomain, ids, 0);
-                        break;
-                    } catch (UnknownHostException x) {
-                        uhe = x;
-                        if (usingSearchList) {
-                            break;
-                        }
-
-                        // devolve
-                        parentDomain = parentDomain.substring(start+1);
-                    }
-                }
-                if (results != null) {
-                    break;
-                }
-            }
-        }
-
-        // finally try the host if it doesn't have a domain name
-        if (results == null && (host.indexOf('.') < 0)) {
-            results = resolve(ctx, host, ids, 0);
-        }
-
-        // if not found then throw the (last) exception thrown.
-        if (results == null) {
-            assert uhe != null;
-            throw uhe;
-        }
-
-        /**
-         * Convert the array list into a byte aray list - this
-         * filters out any invalid IPv4/IPv6 addresses.
-         */
-        assert results.size() > 0;
-        InetAddress[] addrs = new InetAddress[results.size()];
-        int count = 0;
-        for (int i=0; i<results.size(); i++) {
-            String addrString = results.get(i);
-            byte addr[] = IPAddressUtil.textToNumericFormatV4(addrString);
-            if (addr == null) {
-                addr = IPAddressUtil.textToNumericFormatV6(addrString);
-            }
-            if (addr != null) {
-                addrs[count++] = InetAddress.getByAddress(host, addr);
-            }
-        }
-
-        /**
-         * If addresses are filtered then we need to resize the
-         * array. Additionally if all addresses are filtered then
-         * we throw an exception.
-         */
-        if (count == 0) {
-            throw new UnknownHostException(host + ": no valid DNS records");
-        }
-        if (count < results.size()) {
-            InetAddress[] tmp = new InetAddress[count];
-            for (int i=0; i<count; i++) {
-                tmp[i] = addrs[i];
-            }
-            addrs = tmp;
-        }
-
-        return addrs;
-    }
-
-    /**
-     * Reverse lookup code. I.E: find a host name from an IP address.
-     * IPv4 addresses are mapped in the IN-ADDR.ARPA. top domain, while
-     * IPv6 addresses can be in IP6.ARPA or IP6.INT.
-     * In both cases the address has to be converted into a dotted form.
-     */
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        String host = null;
-        try {
-            String literalip = "";
-            String[] ids = { "PTR" };
-            DirContext ctx;
-            ArrayList<String> results = null;
-            try {
-                ctx = getTemporaryContext();
-            } catch (NamingException nx) {
-                throw new Error(nx);
-            }
-            if (addr.length == 4) { // IPv4 Address
-                for (int i = addr.length-1; i >= 0; i--) {
-                    literalip += (addr[i] & 0xff) +".";
-                }
-                literalip += "IN-ADDR.ARPA.";
-
-                results = resolve(ctx, literalip, ids, 0);
-                host = results.get(0);
-            } else if (addr.length == 16) { // IPv6 Address
-                /**
-                 * Because RFC 3152 changed the root domain name for reverse
-                 * lookups from IP6.INT. to IP6.ARPA., we need to check
-                 * both. I.E. first the new one, IP6.ARPA, then if it fails
-                 * the older one, IP6.INT
-                 */
-
-                for (int i = addr.length-1; i >= 0; i--) {
-                    literalip += Integer.toHexString((addr[i] & 0x0f)) +"."
-                        +Integer.toHexString((addr[i] & 0xf0) >> 4) +".";
-                }
-                String ip6lit = literalip + "IP6.ARPA.";
-
-                try {
-                    results = resolve(ctx, ip6lit, ids, 0);
-                    host = results.get(0);
-                } catch (UnknownHostException e) {
-                    host = null;
-                }
-                if (host == null) {
-                    // IP6.ARPA lookup failed, let's try the older IP6.INT
-                    ip6lit = literalip + "IP6.INT.";
-                    results = resolve(ctx, ip6lit, ids, 0);
-                    host = results.get(0);
-                }
-            }
-        } catch (Exception e) {
-            throw new UnknownHostException(e.getMessage());
-        }
-        // Either we couldn't find it or the address was neither IPv4 or IPv6
-        if (host == null)
-            throw new UnknownHostException();
-        // remove trailing dot
-        if (host.endsWith(".")) {
-            host = host.substring(0, host.length() - 1);
-        }
-        return host;
-    }
-
-
-    // ---------
-
-    private static void appendIfLiteralAddress(String addr, StringBuilder sb) {
-        if (IPAddressUtil.isIPv4LiteralAddress(addr)) {
-            sb.append("dns://").append(addr).append(' ');
-        } else {
-            if (IPAddressUtil.isIPv6LiteralAddress(addr)) {
-                sb.append("dns://[").append(addr).append("] ");
-            }
-        }
-    }
-
-    /*
-     * @return String containing the JNDI-DNS provider URL
-     *         corresponding to the supplied List of nameservers.
-     */
-    private static String createProviderURL(List<String> nsList) {
-        StringBuilder sb = new StringBuilder();
-        for (String s: nsList) {
-            appendIfLiteralAddress(s, sb);
-        }
-        return sb.toString();
-    }
-
-    /*
-     * @return String containing the JNDI-DNS provider URL
-     *         corresponding to the list of nameservers
-     *         contained in the provided str.
-     */
-    private static String createProviderURL(String str) {
-        StringBuilder sb = new StringBuilder();
-        StringTokenizer st = new StringTokenizer(str, ",");
-        while (st.hasMoreTokens()) {
-            appendIfLiteralAddress(st.nextToken(), sb);
-        }
-        return sb.toString();
-    }
-}
--- a/src/jdk.naming.dns/share/classes/sun/net/spi/nameservice/dns/DNSNameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.spi.nameservice.dns;
-
-import sun.net.spi.nameservice.*;
-
-public final class DNSNameServiceDescriptor implements NameServiceDescriptor {
-    /**
-     * Create a new instance of the corresponding name service.
-     */
-    public NameService createNameService() throws Exception {
-        return new DNSNameService();
-    }
-
-    /**
-     * Returns this service provider's name
-     *
-     */
-    public String getProviderName() {
-        return "sun";
-    }
-
-    /**
-     * Returns this name service type
-     * "dns" "nis" etc
-     */
-    public String getType() {
-        return "dns";
-    }
-}
--- a/src/jdk.pack200/share/native/common-unpack/defines.h	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.pack200/share/native/common-unpack/defines.h	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,6 +90,12 @@
 #define U_NEW(T, n)  (T*) u->alloc(scale_size(n, sizeof(T)))
 #define T_NEW(T, n)  (T*) u->temp_alloc(scale_size(n, sizeof(T)))
 
+// Dealing with big-endian arch
+#ifdef _BIG_ENDIAN
+#define SWAP_INT(a) (((a>>24)&0xff) | ((a<<8)&0xff0000) | ((a>>8)&0xff00) | ((a<<24)&0xff000000))
+#else
+#define SWAP_INT(a) (a)
+#endif
 
 // bytes and byte arrays
 
--- a/src/jdk.pack200/share/native/common-unpack/unpack.h	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.pack200/share/native/common-unpack/unpack.h	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -171,7 +171,6 @@
   bytes inbytes;    // direct
   gunzip* gzin;     // gunzip filter, if any
   jar*  jarout;     // output JAR file
-  uint  gzcrc;      // CRC gathered from gzip content
 
 #ifndef PRODUCT
   int   nowrite;
--- a/src/jdk.pack200/share/native/common-unpack/zip.cpp	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.pack200/share/native/common-unpack/zip.cpp	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -341,6 +341,7 @@
 void jar::openJarFile(const char* fname) {
   if (!jarfp) {
     PRINTCR((1, "jar::openJarFile: opening %s\n",fname));
+    jarname = fname;
     jarfp = fopen(fname, "wb");
     if (!jarfp) {
       fprintf(u->errstrm, "Error: Could not open jar file: %s\n",fname);
@@ -551,7 +552,8 @@
       break;
     }
     int nr = readlen - zs.avail_out;
-    u->gzcrc = crc32(u->gzcrc, (const unsigned char *)bufptr, nr);
+    u->gzin->gzlen += nr;
+    u->gzin->gzcrc = crc32(u->gzin->gzcrc, (const unsigned char *)bufptr, nr);
     numread += nr;
     bufptr += nr;
     assert(numread <= maxlen);
@@ -562,15 +564,44 @@
         zs.avail_in -= TRAILER_LEN;
       } else {
         // Bug: 5023768,we read past the TRAILER_LEN to see if there is
-        // any extraneous data, as we don't support concatenated .gz
-        // files just yet.
+        // any extraneous data, as we don't support concatenated .gz files.
         int extra = (int) read_gzin_fn(u, inbuf, 1, inbuflen);
         zs.avail_in += extra - TRAILER_LEN;
       }
-      // %%% should check final CRC and length here
       // %%% should check for concatenated *.gz files here
       if (zs.avail_in > 0)
         u->abort("garbage after end of deflated input stream");
+
+      // at this point we know there are no trailing bytes,
+      // we are safe to get the crc and len.
+      if (u->gzin->gzcrc != 0) {
+        // Read the CRC information from the gzip container
+        fseek(u->infileptr, -TRAILER_LEN, SEEK_END);
+        uint filecrc;
+        uint filelen;
+        fread(&filecrc, sizeof(filecrc), 1, u->infileptr);
+        fread(&filelen, sizeof(filelen), 1, u->infileptr);
+        filecrc = SWAP_INT(filecrc);
+        filelen = SWAP_INT(filelen);
+        if (u->gzin->gzcrc != filecrc ||
+                // rfc1952; ISIZE is the input size modulo 2^32
+                u->gzin->gzlen != (filelen & 0xffffffff)) { // CRC error
+
+          PRINTCR((1, "crc: 0x%x 0x%x\n", u->gzin->gzcrc,  filecrc));
+          PRINTCR((1, "len: 0x%x 0x%x\n", u->gzin->gzlen,  filelen));
+
+          if (u->jarout != null) {
+            // save the file name first, if any
+            const char* outfile = u->jarout->jarname;
+            u->jarout->closeJarFile(false);
+            if (outfile != null) {
+              remove(outfile);
+            }
+          }
+          // Print out the error and exit with return code != 0
+          u->abort("CRC error, invalid compressed data.");
+        }
+      }
       // pop this filter off:
       u->gzin->free();
       break;
@@ -590,7 +621,8 @@
   zstream = NEW(z_stream, 1);
   u->gzin = this;
   u->read_input_fn = read_input_via_gzip;
-  u->gzcrc = crc32(0, Z_NULL, 0);
+  u->gzin->gzcrc = crc32(0, Z_NULL, 0);
+  u->gzin->gzlen = 0;
 }
 
 void gunzip::start(int magic) {
--- a/src/jdk.pack200/share/native/common-unpack/zip.h	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.pack200/share/native/common-unpack/zip.h	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
   FILE*       jarfp;
   int         default_modtime;
 
+  const char* jarname;
+
   // Used by unix2dostime:
   int         modtime_cache;
   uLong       dostime_cache;
@@ -98,6 +100,9 @@
   void* zstream;        // inflater state
   char inbuf[1 << 14];   // input buffer
 
+  uint  gzcrc;      // CRC gathered from gzip *container* content
+  uint  gzlen;      // CRC gathered length
+
   void init(unpacker* u_);  // pushes new value on u->read_input_fn
 
   void free();
--- a/src/jdk.pack200/share/native/unpack200/main.cpp	Mon Apr 11 21:07:34 2016 +0300
+++ b/src/jdk.pack200/share/native/unpack200/main.cpp	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,13 +62,6 @@
     return unpacker::run(argc, argv);
 }
 
-// Dealing with big-endian arch
-#ifdef _BIG_ENDIAN
-#define SWAP_INT(a) (((a>>24)&0xff) | ((a<<8)&0xff0000) | ((a>>8)&0xff00) | ((a<<24)&0xff000000))
-#else
-#define SWAP_INT(a) (a)
-#endif
-
 // Single-threaded, implementation, not reentrant.
 // Includes a weak error check against MT access.
 #ifndef THREAD_SELF
@@ -366,6 +359,7 @@
 
   if (strcmp(destination_file, "-") == 0) {
     jarout.jarfp = stdout;
+    jarout.jarname = null;
     if (u.errstrm == stdout) // do not mix output
       u.set_option(UNPACK_LOG_FILE, LOGFILE_STDERR);
   } else {
@@ -385,11 +379,12 @@
     // Oops; must slap an input filter on this data.
     setup_gzin(&u);
     u.gzin->start(magic);
+    u.gzin->gzcrc = 0;
+    u.gzin->gzlen = 0;
     if (!u.aborting()) {
       u.start();
     }
   } else {
-    u.gzcrc = 0;
     u.start(peek, sizeof(peek));
   }
 
@@ -422,31 +417,13 @@
     u.start(peek, sizeof(peek));
   }
 
-
-
   int status = 0;
   if (u.aborting()) {
     fprintf(u.errstrm, "Error: %s\n", u.get_abort_message());
     status = 1;
   }
 
-  if (!u.aborting() && u.infileptr != null) {
-    if (u.gzcrc != 0) {
-      // Read the CRC information from the gzip container
-      fseek(u.infileptr, -8, SEEK_END);
-      uint filecrc;
-      fread(&filecrc, sizeof(filecrc), 1, u.infileptr);
-      if (u.gzcrc != SWAP_INT(filecrc)) { // CRC error
-        if (strcmp(destination_file, "-") != 0) {
-          // Output is not stdout, remove it, it's broken
-          if (u.jarout != null)
-            u.jarout->closeJarFile(false);
-          remove(destination_file);
-        }
-        // Print out the error and exit with return code != 0
-        u.abort("CRC error, invalid compressed data.");
-      }
-    }
+  if (u.infileptr != null) {
     fclose(u.infileptr);
     u.infileptr = null;
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/module-info.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.unsupported {
+    exports sun.misc;
+    //exports sun.reflect;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+/**
+ * A thread that has it's thread locals, and inheritable thread
+ * locals erased on construction.
+ */
+public class ManagedLocalsThread extends Thread {
+    private static final jdk.internal.misc.Unsafe UNSAFE;
+    private static final long THREAD_LOCALS;
+    private static final long INHERITABLE_THREAD_LOCALS;
+
+    public ManagedLocalsThread() {
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(Runnable target) {
+        super(target);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(String name) {
+        super(name);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(ThreadGroup group, Runnable target) {
+        super(group, target);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(Runnable target, String name) {
+        super(target, name);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(ThreadGroup group, String name) {
+        super(group, name);
+        eraseThreadLocals();
+    }
+
+    public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) {
+        super(group, target, name);
+        eraseThreadLocals();
+    }
+
+    /**
+     * Drops all thread locals (and inherited thread locals).
+     */
+    public final void eraseThreadLocals() {
+        UNSAFE.putObject(this, THREAD_LOCALS, null);
+        UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+    }
+
+    static {
+        UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
+        Class<?> t = Thread.class;
+        try {
+            THREAD_LOCALS = UNSAFE.objectFieldOffset
+                (t.getDeclaredField("threadLocals"));
+            INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
+                (t.getDeclaredField("inheritableThreadLocals"));
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/sun/misc/Signal.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.util.Objects;
+
+/**
+ * This class provides ANSI/ISO C signal support. A Java program can register
+ * signal handlers for the current process. There are two restrictions:
+ * <ul>
+ * <li>
+ * Java code cannot register a handler for signals that are already used
+ * by the Java VM implementation. The <code>Signal.handle</code>
+ * function raises an <code>IllegalArgumentException</code> if such an attempt
+ * is made.
+ * <li>
+ * When <code>Signal.handle</code> is called, the VM internally registers a
+ * special C signal handler. There is no way to force the Java signal handler
+ * to run synchronously before the C signal handler returns. Instead, when the
+ * VM receives a signal, the special C signal handler creates a new thread
+ * (at priority <code>Thread.MAX_PRIORITY</code>) to
+ * run the registered Java signal handler. The C signal handler immediately
+ * returns. Note that because the Java signal handler runs in a newly created
+ * thread, it may not actually be executed until some time after the C signal
+ * handler returns.
+ * </ul>
+ * <p>
+ * Signal objects are created based on their names. For example:
+ * <blockquote><pre>
+ * new Signal("INT");
+ * </pre></blockquote>
+ * constructs a signal object corresponding to <code>SIGINT</code>, which is
+ * typically produced when the user presses <code>Ctrl-C</code> at the command line.
+ * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
+ * when it is passed an unknown signal.
+ * <p>
+ * This is an example of how Java code handles <code>SIGINT</code>:
+ * <blockquote><pre>
+ * SignalHandler handler = new SignalHandler () {
+ *     public void handle(Signal sig) {
+ *       ... // handle SIGINT
+ *     }
+ * };
+ * Signal.handle(new Signal("INT"), handler);
+ * </pre></blockquote>
+ *
+ * @author   Sheng Liang
+ * @author   Bill Shannon
+ * @see     sun.misc.SignalHandler
+ * @since    1.2
+ */
+public final class Signal {
+
+    // Delegate to jdk.internal.misc.Signal.
+    private final jdk.internal.misc.Signal iSignal;
+
+    /* Returns the signal number */
+    public int getNumber() {
+        return iSignal.getNumber();
+    }
+
+    /**
+     * Returns the signal name.
+     *
+     * @return the name of the signal.
+     * @see sun.misc.Signal#Signal(String name)
+     */
+    public String getName() {
+        return iSignal.getName();
+    }
+
+    /**
+     * Compares the equality of two <code>Signal</code> objects.
+     *
+     * @param other the object to compare with.
+     * @return whether two <code>Signal</code> objects are equal.
+     */
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (other == null || !(other instanceof Signal)) {
+            return false;
+        }
+        Signal other1 = (Signal)other;
+        return iSignal.equals(other1.iSignal);
+    }
+
+    /**
+     * Returns a hashcode for this Signal.
+     *
+     * @return  a hash code value for this object.
+     */
+    public int hashCode() {
+        return getNumber();
+    }
+
+    /**
+     * Returns a string representation of this signal. For example, "SIGINT"
+     * for an object constructed using <code>new Signal ("INT")</code>.
+     *
+     * @return a string representation of the signal
+     */
+    public String toString() {
+        return iSignal.toString();
+    }
+
+    /**
+     * Constructs a signal from its name.
+     *
+     * @param name the name of the signal.
+     * @exception IllegalArgumentException unknown signal
+     * @see sun.misc.Signal#getName()
+     */
+    public Signal(String name) {
+        iSignal = new jdk.internal.misc.Signal(name);
+    }
+
+    /**
+     * Registers a signal handler.
+     *
+     * @param sig a signal
+     * @param handler the handler to be registered with the given signal.
+     * @return the old handler
+     * @exception IllegalArgumentException the signal is in use by the VM
+     * @see sun.misc.Signal#raise(Signal sig)
+     * @see sun.misc.SignalHandler
+     * @see sun.misc.SignalHandler#SIG_DFL
+     * @see sun.misc.SignalHandler#SIG_IGN
+     */
+    public static synchronized SignalHandler handle(Signal sig,
+                                                    SignalHandler handler)
+        throws IllegalArgumentException {
+        jdk.internal.misc.Signal.Handler oldHandler = jdk.internal.misc.Signal.handle(sig.iSignal,
+                InternalMiscHandler.of(sig, handler));
+        return SunMiscHandler.of(sig.iSignal, oldHandler);
+    }
+
+    /**
+     * Raises a signal in the current process.
+     *
+     * @param sig a signal
+     * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
+     */
+    public static void raise(Signal sig) throws IllegalArgumentException {
+        jdk.internal.misc.Signal.raise(sig.iSignal);
+    }
+
+    /*
+     * Wrapper class to proxy a SignalHandler to a jdk.internal.misc.Signal.Handler.
+     */
+    static final class InternalMiscHandler implements jdk.internal.misc.Signal.Handler {
+        private final SignalHandler handler;
+        private final Signal signal;
+
+        static jdk.internal.misc.Signal.Handler of(Signal signal, SignalHandler handler) {
+            if (handler == SignalHandler.SIG_DFL) {
+                return jdk.internal.misc.Signal.Handler.SIG_DFL;
+            } else if (handler == SignalHandler.SIG_IGN) {
+                return jdk.internal.misc.Signal.Handler.SIG_IGN;
+            } else if (handler instanceof SunMiscHandler) {
+                return ((SunMiscHandler)handler).iHandler;
+            } else {
+                return new InternalMiscHandler(signal, handler);
+            }
+        }
+
+        private InternalMiscHandler(Signal signal, SignalHandler handler) {
+            this.handler = handler;
+            this.signal = signal;
+        }
+
+        @Override
+        public void handle(jdk.internal.misc.Signal ignore) {
+            handler.handle(signal);
+        }
+    }
+
+    /*
+     * Wrapper class to proxy a jdk.internal.misc.Signal.Handler to a SignalHandler.
+     */
+    static final class SunMiscHandler implements SignalHandler {
+        private final jdk.internal.misc.Signal iSignal;
+        private final jdk.internal.misc.Signal.Handler iHandler;
+
+        static SignalHandler of(jdk.internal.misc.Signal signal, jdk.internal.misc.Signal.Handler handler) {
+            if (handler == jdk.internal.misc.Signal.Handler.SIG_DFL) {
+                return SignalHandler.SIG_DFL;
+            } else if (handler == jdk.internal.misc.Signal.Handler.SIG_IGN) {
+                return SignalHandler.SIG_IGN;
+            } else if (handler instanceof InternalMiscHandler) {
+                return ((InternalMiscHandler) handler).handler;
+            } else {
+                return new SunMiscHandler(signal, handler);
+            }
+        }
+
+        SunMiscHandler(jdk.internal.misc.Signal iSignal, jdk.internal.misc.Signal.Handler iHandler) {
+            this.iSignal = iSignal;
+            this.iHandler = iHandler;
+        }
+
+        @Override
+        public void handle(Signal sig) {
+            iHandler.handle(iSignal);
+        }
+
+        public String toString() {
+            return iHandler.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/sun/misc/SignalHandler.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+/**
+ * This is the signal handler interface expected in <code>Signal.handle</code>.
+ *
+ * @author   Sheng Liang
+ * @author   Bill Shannon
+ * @see      sun.misc.Signal
+ * @since    1.2
+ */
+
+public interface SignalHandler {
+
+    /**
+     * The default signal handler
+     */
+    public static final SignalHandler SIG_DFL =
+            new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_DFL);
+    /**
+     * Ignore the signal
+     */
+    public static final SignalHandler SIG_IGN =
+            new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_IGN);
+
+    /**
+     * Handle the given signal
+     *
+     * @param sig a signal object
+     */
+    public void handle(Signal sig);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/sun/misc/SoftCache.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.lang.ref.SoftReference;
+import java.lang.ref.ReferenceQueue;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.AbstractSet;
+import java.util.NoSuchElementException;
+
+
+/**
+ * A memory-sensitive implementation of the <code>Map</code> interface.
+ *
+ * <p> A <code>SoftCache</code> object uses {@link java.lang.ref.SoftReference
+ * soft references} to implement a memory-sensitive hash map.  If the garbage
+ * collector determines at a certain point in time that a value object in a
+ * <code>SoftCache</code> entry is no longer strongly reachable, then it may
+ * remove that entry in order to release the memory occupied by the value
+ * object.  All <code>SoftCache</code> objects are guaranteed to be completely
+ * cleared before the virtual machine will throw an
+ * <code>OutOfMemoryError</code>.  Because of this automatic clearing feature,
+ * the behavior of this class is somewhat different from that of other
+ * <code>Map</code> implementations.
+ *
+ * <p> Both null values and the null key are supported.  This class has the
+ * same performance characteristics as the <code>HashMap</code> class, and has
+ * the same efficiency parameters of <em>initial capacity</em> and <em>load
+ * factor</em>.
+ *
+ * <p> Like most collection classes, this class is not synchronized.  A
+ * synchronized <code>SoftCache</code> may be constructed using the
+ * <code>Collections.synchronizedMap</code> method.
+ *
+ * <p> In typical usage this class will be subclassed and the <code>fill</code>
+ * method will be overridden.  When the <code>get</code> method is invoked on a
+ * key for which there is no mapping in the cache, it will in turn invoke the
+ * <code>fill</code> method on that key in an attempt to construct a
+ * corresponding value.  If the <code>fill</code> method returns such a value
+ * then the cache will be updated and the new value will be returned.  Thus,
+ * for example, a simple URL-content cache can be constructed as follows:
+ *
+ * <pre>
+ *     public class URLCache extends SoftCache {
+ *         protected Object fill(Object key) {
+ *             return ((URL)key).getContent();
+ *         }
+ *     }
+ * </pre>
+ *
+ * <p> The behavior of the <code>SoftCache</code> class depends in part upon
+ * the actions of the garbage collector, so several familiar (though not
+ * required) <code>Map</code> invariants do not hold for this class.  <p>
+ * Because entries are removed from a <code>SoftCache</code> in response to
+ * dynamic advice from the garbage collector, a <code>SoftCache</code> may
+ * behave as though an unknown thread is silently removing entries.  In
+ * particular, even if you synchronize on a <code>SoftCache</code> instance and
+ * invoke none of its mutator methods, it is possible for the <code>size</code>
+ * method to return smaller values over time, for the <code>isEmpty</code>
+ * method to return <code>false</code> and then <code>true</code>, for the
+ * <code>containsKey</code> method to return <code>true</code> and later
+ * <code>false</code> for a given key, for the <code>get</code> method to
+ * return a value for a given key but later return <code>null</code>, for the
+ * <code>put</code> method to return <code>null</code> and the
+ * <code>remove</code> method to return <code>false</code> for a key that
+ * previously appeared to be in the map, and for successive examinations of the
+ * key set, the value set, and the entry set to yield successively smaller
+ * numbers of elements.
+ *
+ * @author      Mark Reinhold
+ * @since       1.2
+ * @see         java.util.HashMap
+ * @see         java.lang.ref.SoftReference
+ * @deprecated No direct replacement; {@link java.util.WeakHashMap}
+ * addresses a related by different use-case.
+ */
+
+@Deprecated
+public class SoftCache extends AbstractMap<Object, Object> implements Map<Object, Object> {
+
+    /* The basic idea of this implementation is to maintain an internal HashMap
+       that maps keys to soft references whose referents are the keys' values;
+       the various accessor methods dereference these soft references before
+       returning values.  Because we don't have access to the innards of the
+       HashMap, each soft reference must contain the key that maps to it so
+       that the processQueue method can remove keys whose values have been
+       discarded.  Thus the HashMap actually maps keys to instances of the
+       ValueCell class, which is a simple extension of the SoftReference class.
+     */
+
+
+    private static class ValueCell extends SoftReference<Object> {
+        private static Object INVALID_KEY = new Object();
+        private static int dropped = 0;
+        private Object key;
+
+        private ValueCell(Object key, Object value, ReferenceQueue<Object> queue) {
+            super(value, queue);
+            this.key = key;
+        }
+
+        private static ValueCell create(Object key, Object value,
+                                        ReferenceQueue<Object> queue)
+        {
+            if (value == null) return null;
+            return new ValueCell(key, value, queue);
+        }
+
+        private static Object strip(Object val, boolean drop) {
+            if (val == null) return null;
+            ValueCell vc = (ValueCell)val;
+            Object o = vc.get();
+            if (drop) vc.drop();
+            return o;
+        }
+
+        private boolean isValid() {
+            return (key != INVALID_KEY);
+        }
+
+        private void drop() {
+            super.clear();
+            key = INVALID_KEY;
+            dropped++;
+        }
+
+    }
+
+
+    /* Hash table mapping keys to ValueCells */
+    private Map<Object, Object> hash;
+
+    /* Reference queue for cleared ValueCells */
+    private ReferenceQueue<Object> queue = new ReferenceQueue<>();
+
+
+    /* Process any ValueCells that have been cleared and enqueued by the
+       garbage collector.  This method should be invoked once by each public
+       mutator in this class.  We don't invoke this method in public accessors
+       because that can lead to surprising ConcurrentModificationExceptions.
+     */
+    private void processQueue() {
+        ValueCell vc;
+        while ((vc = (ValueCell)queue.poll()) != null) {
+            if (vc.isValid()) hash.remove(vc.key);
+            else ValueCell.dropped--;
+        }
+    }
+
+
+    /* -- Constructors -- */
+
+    /**
+     * Construct a new, empty <code>SoftCache</code> with the given
+     * initial capacity and the given load factor.
+     *
+     * @param  initialCapacity  The initial capacity of the cache
+     *
+     * @param  loadFactor       A number between 0.0 and 1.0
+     *
+     * @throws IllegalArgumentException  If the initial capacity is less than
+     *                                   or equal to zero, or if the load
+     *                                   factor is less than zero
+     */
+    public SoftCache(int initialCapacity, float loadFactor) {
+        hash = new HashMap<>(initialCapacity, loadFactor);
+    }
+
+    /**
+     * Construct a new, empty <code>SoftCache</code> with the given
+     * initial capacity and the default load factor.
+     *
+     * @param  initialCapacity  The initial capacity of the cache
+     *
+     * @throws IllegalArgumentException  If the initial capacity is less than
+     *                                   or equal to zero
+     */
+    public SoftCache(int initialCapacity) {
+        hash = new HashMap<>(initialCapacity);
+    }
+
+    /**
+     * Construct a new, empty <code>SoftCache</code> with the default
+     * capacity and the default load factor.
+     */
+    public SoftCache() {
+        hash = new HashMap<>();
+    }
+
+
+    /* -- Simple queries -- */
+
+    /**
+     * Return the number of key-value mappings in this cache.  The time
+     * required by this operation is linear in the size of the map.
+     */
+    public int size() {
+        return entrySet().size();
+    }
+
+    /**
+     * Return <code>true</code> if this cache contains no key-value mappings.
+     */
+    public boolean isEmpty() {
+        return entrySet().isEmpty();
+    }
+
+    /**
+     * Return <code>true</code> if this cache contains a mapping for the
+     * specified key.  If there is no mapping for the key, this method will not
+     * attempt to construct one by invoking the <code>fill</code> method.
+     *
+     * @param   key   The key whose presence in the cache is to be tested
+     */
+    public boolean containsKey(Object key) {
+        return ValueCell.strip(hash.get(key), false) != null;
+    }
+
+
+    /* -- Lookup and modification operations -- */
+
+    /**
+     * Create a value object for the given <code>key</code>.  This method is
+     * invoked by the <code>get</code> method when there is no entry for
+     * <code>key</code>.  If this method returns a non-<code>null</code> value,
+     * then the cache will be updated to map <code>key</code> to that value,
+     * and that value will be returned by the <code>get</code> method.
+     *
+     * <p> The default implementation of this method simply returns
+     * <code>null</code> for every <code>key</code> value.  A subclass may
+     * override this method to provide more useful behavior.
+     *
+     * @param  key  The key for which a value is to be computed
+     *
+     * @return      A value for <code>key</code>, or <code>null</code> if one
+     *              could not be computed
+     * @see #get
+     */
+    protected Object fill(Object key) {
+        return null;
+    }
+
+    /**
+     * Return the value to which this cache maps the specified
+     * <code>key</code>.  If the cache does not presently contain a value for
+     * this key, then invoke the <code>fill</code> method in an attempt to
+     * compute such a value.  If that method returns a non-<code>null</code>
+     * value, then update the cache and return the new value.  Otherwise,
+     * return <code>null</code>.
+     *
+     * <p> Note that because this method may update the cache, it is considered
+     * a mutator and may cause <code>ConcurrentModificationException</code>s to
+     * be thrown if invoked while an iterator is in use.
+     *
+     * @param  key  The key whose associated value, if any, is to be returned
+     *
+     * @see #fill
+     */
+    public Object get(Object key) {
+        processQueue();
+        Object v = hash.get(key);
+        if (v == null) {
+            v = fill(key);
+            if (v != null) {
+                hash.put(key, ValueCell.create(key, v, queue));
+                return v;
+            }
+        }
+        return ValueCell.strip(v, false);
+    }
+
+    /**
+     * Update this cache so that the given <code>key</code> maps to the given
+     * <code>value</code>.  If the cache previously contained a mapping for
+     * <code>key</code> then that mapping is replaced and the old value is
+     * returned.
+     *
+     * @param  key    The key that is to be mapped to the given
+     *                <code>value</code>
+     * @param  value  The value to which the given <code>key</code> is to be
+     *                mapped
+     *
+     * @return  The previous value to which this key was mapped, or
+     *          <code>null</code> if there was no mapping for the key
+     */
+    public Object put(Object key, Object value) {
+        processQueue();
+        ValueCell vc = ValueCell.create(key, value, queue);
+        return ValueCell.strip(hash.put(key, vc), true);
+    }
+
+    /**
+     * Remove the mapping for the given <code>key</code> from this cache, if
+     * present.
+     *
+     * @param  key  The key whose mapping is to be removed
+     *
+     * @return  The value to which this key was mapped, or <code>null</code> if
+     *          there was no mapping for the key
+     */
+    public Object remove(Object key) {
+        processQueue();
+        return ValueCell.strip(hash.remove(key), true);
+    }
+
+    /**
+     * Remove all mappings from this cache.
+     */
+    public void clear() {
+        processQueue();
+        hash.clear();
+    }
+
+
+    /* -- Views -- */
+
+    private static boolean valEquals(Object o1, Object o2) {
+        return (o1 == null) ? (o2 == null) : o1.equals(o2);
+    }
+
+
+    /* Internal class for entries.
+       Because it uses SoftCache.this.queue, this class cannot be static.
+     */
+    private class Entry implements Map.Entry<Object, Object> {
+        private Map.Entry<Object, Object> ent;
+        private Object value;   /* Strong reference to value, to prevent the GC
+                                   from flushing the value while this Entry
+                                   exists */
+
+        Entry(Map.Entry<Object, Object> ent, Object value) {
+            this.ent = ent;
+            this.value = value;
+        }
+
+        public Object getKey() {
+            return ent.getKey();
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object setValue(Object value) {
+            return ent.setValue(ValueCell.create(ent.getKey(), value, queue));
+        }
+
+        @SuppressWarnings("unchecked")
+        public boolean equals(Object o) {
+            if (! (o instanceof Map.Entry)) return false;
+            Map.Entry<Object, Object> e = (Map.Entry<Object, Object>)o;
+            return (valEquals(ent.getKey(), e.getKey())
+                    && valEquals(value, e.getValue()));
+        }
+
+        public int hashCode() {
+            Object k;
+            return ((((k = getKey()) == null) ? 0 : k.hashCode())
+                    ^ ((value == null) ? 0 : value.hashCode()));
+        }
+
+    }
+
+
+    /* Internal class for entry sets */
+    private class EntrySet extends AbstractSet<Map.Entry<Object, Object>> {
+        Set<Map.Entry<Object, Object>> hashEntries = hash.entrySet();
+
+        public Iterator<Map.Entry<Object, Object>> iterator() {
+
+            return new Iterator<Map.Entry<Object, Object>>() {
+                Iterator<Map.Entry<Object, Object>> hashIterator = hashEntries.iterator();
+                Entry next = null;
+
+                public boolean hasNext() {
+                    while (hashIterator.hasNext()) {
+                        Map.Entry<Object, Object> ent = hashIterator.next();
+                        ValueCell vc = (ValueCell)ent.getValue();
+                        Object v = null;
+                        if ((vc != null) && ((v = vc.get()) == null)) {
+                            /* Value has been flushed by GC */
+                            continue;
+                        }
+                        next = new Entry(ent, v);
+                        return true;
+                    }
+                    return false;
+                }
+
+                public Map.Entry<Object, Object> next() {
+                    if ((next == null) && !hasNext())
+                        throw new NoSuchElementException();
+                    Entry e = next;
+                    next = null;
+                    return e;
+                }
+
+                public void remove() {
+                    hashIterator.remove();
+                }
+
+            };
+        }
+
+        public boolean isEmpty() {
+            return !(iterator().hasNext());
+        }
+
+        public int size() {
+            int j = 0;
+            for (Iterator<Map.Entry<Object, Object>> i = iterator(); i.hasNext(); i.next()) j++;
+            return j;
+        }
+
+        public boolean remove(Object o) {
+            processQueue();
+            if (o instanceof Entry) return hashEntries.remove(((Entry)o).ent);
+            else return false;
+        }
+
+    }
+
+
+    private Set<Map.Entry<Object, Object>> entrySet = null;
+
+    /**
+     * Return a <code>Set</code> view of the mappings in this cache.
+     */
+    public Set<Map.Entry<Object, Object>> entrySet() {
+        if (entrySet == null) entrySet = new EntrySet();
+        return entrySet;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1270 @@
+/*
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.misc.VM;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
+import java.lang.reflect.Field;
+import java.security.ProtectionDomain;
+
+
+/**
+ * A collection of methods for performing low-level, unsafe operations.
+ * Although the class and all methods are public, use of this class is
+ * limited because only trusted code can obtain instances of it.
+ *
+ * <em>Note:</em> It is the resposibility of the caller to make sure
+ * arguments are checked before methods of this class are
+ * called. While some rudimentary checks are performed on the input,
+ * the checks are best effort and when performance is an overriding
+ * priority, as when methods of this class are optimized by the
+ * runtime compiler, some or all checks (if any) may be elided. Hence,
+ * the caller must not rely on the checks and corresponding
+ * exceptions!
+ *
+ * @author John R. Rose
+ * @see #getUnsafe
+ */
+
+public final class Unsafe {
+
+    static {
+        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
+    }
+
+    private Unsafe() {}
+
+    private static final Unsafe theUnsafe = new Unsafe();
+    private static final jdk.internal.misc.Unsafe theInternalUnsafe = jdk.internal.misc.Unsafe.getUnsafe();
+
+    /**
+     * Provides the caller with the capability of performing unsafe
+     * operations.
+     *
+     * <p>The returned {@code Unsafe} object should be carefully guarded
+     * by the caller, since it can be used to read and write data at arbitrary
+     * memory addresses.  It must never be passed to untrusted code.
+     *
+     * <p>Most methods in this class are very low-level, and correspond to a
+     * small number of hardware instructions (on typical machines).  Compilers
+     * are encouraged to optimize these methods accordingly.
+     *
+     * <p>Here is a suggested idiom for using unsafe operations:
+     *
+     * <pre> {@code
+     * class MyTrustedClass {
+     *   private static final Unsafe unsafe = Unsafe.getUnsafe();
+     *   ...
+     *   private long myCountAddress = ...;
+     *   public int getCount() { return unsafe.getByte(myCountAddress); }
+     * }}</pre>
+     *
+     * (It may assist compilers to make the local variable {@code final}.)
+     *
+     * @throws  SecurityException  if a security manager exists and its
+     *          {@code checkPropertiesAccess} method doesn't allow
+     *          access to the system properties.
+     */
+    @CallerSensitive
+    public static Unsafe getUnsafe() {
+        Class<?> caller = Reflection.getCallerClass();
+        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
+            throw new SecurityException("Unsafe");
+        return theUnsafe;
+    }
+
+    /// peek and poke operations
+    /// (compilers should optimize these to memory ops)
+
+    // These work on object fields in the Java heap.
+    // They will not work on elements of packed arrays.
+
+    /**
+     * Fetches a value from a given Java variable.
+     * More specifically, fetches a field or array element within the given
+     * object {@code o} at the given offset, or (if {@code o} is null)
+     * from the memory address whose numerical value is the given offset.
+     * <p>
+     * The results are undefined unless one of the following cases is true:
+     * <ul>
+     * <li>The offset was obtained from {@link #objectFieldOffset} on
+     * the {@link java.lang.reflect.Field} of some Java field and the object
+     * referred to by {@code o} is of a class compatible with that
+     * field's class.
+     *
+     * <li>The offset and object reference {@code o} (either null or
+     * non-null) were both obtained via {@link #staticFieldOffset}
+     * and {@link #staticFieldBase} (respectively) from the
+     * reflective {@link Field} representation of some Java field.
+     *
+     * <li>The object referred to by {@code o} is an array, and the offset
+     * is an integer of the form {@code B+N*S}, where {@code N} is
+     * a valid index into the array, and {@code B} and {@code S} are
+     * the values obtained by {@link #arrayBaseOffset} and {@link
+     * #arrayIndexScale} (respectively) from the array's class.  The value
+     * referred to is the {@code N}<em>th</em> element of the array.
+     *
+     * </ul>
+     * <p>
+     * If one of the above cases is true, the call references a specific Java
+     * variable (field or array element).  However, the results are undefined
+     * if that variable is not in fact of the type returned by this method.
+     * <p>
+     * This method refers to a variable by means of two parameters, and so
+     * it provides (in effect) a <em>double-register</em> addressing mode
+     * for Java variables.  When the object reference is null, this method
+     * uses its offset as an absolute address.  This is similar in operation
+     * to methods such as {@link #getInt(long)}, which provide (in effect) a
+     * <em>single-register</em> addressing mode for non-Java variables.
+     * However, because Java variables may have a different layout in memory
+     * from non-Java variables, programmers should not assume that these
+     * two addressing modes are ever equivalent.  Also, programmers should
+     * remember that offsets from the double-register addressing mode cannot
+     * be portably confused with longs used in the single-register addressing
+     * mode.
+     *
+     * @param o Java heap object in which the variable resides, if any, else
+     *        null
+     * @param offset indication of where the variable resides in a Java heap
+     *        object, if any, else a memory address locating the variable
+     *        statically
+     * @return the value fetched from the indicated Java variable
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     */
+    @ForceInline
+    public int getInt(Object o, long offset) {
+        return theInternalUnsafe.getInt(o, offset);
+    }
+
+    /**
+     * Stores a value into a given Java variable.
+     * <p>
+     * The first two parameters are interpreted exactly as with
+     * {@link #getInt(Object, long)} to refer to a specific
+     * Java variable (field or array element).  The given value
+     * is stored into that variable.
+     * <p>
+     * The variable must be of the same type as the method
+     * parameter {@code x}.
+     *
+     * @param o Java heap object in which the variable resides, if any, else
+     *        null
+     * @param offset indication of where the variable resides in a Java heap
+     *        object, if any, else a memory address locating the variable
+     *        statically
+     * @param x the value to store into the indicated Java variable
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     */
+    @ForceInline
+    public void putInt(Object o, long offset, int x) {
+        theInternalUnsafe.putInt(o, offset, x);
+    }
+
+    /**
+     * Fetches a reference value from a given Java variable.
+     * @see #getInt(Object, long)
+     */
+    @ForceInline
+    public Object getObject(Object o, long offset) {
+        return theInternalUnsafe.getObject(o, offset);
+    }
+
+    /**
+     * Stores a reference value into a given Java variable.
+     * <p>
+     * Unless the reference {@code x} being stored is either null
+     * or matches the field type, the results are undefined.
+     * If the reference {@code o} is non-null, card marks or
+     * other store barriers for that object (if the VM requires them)
+     * are updated.
+     * @see #putInt(Object, long, int)
+     */
+    @ForceInline
+    public void putObject(Object o, long offset, Object x) {
+        theInternalUnsafe.putObject(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public boolean getBoolean(Object o, long offset) {
+        return theInternalUnsafe.getBoolean(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putBoolean(Object o, long offset, boolean x) {
+        theInternalUnsafe.putBoolean(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public byte getByte(Object o, long offset) {
+        return theInternalUnsafe.getByte(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putByte(Object o, long offset, byte x) {
+        theInternalUnsafe.putByte(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public short getShort(Object o, long offset) {
+        return theInternalUnsafe.getShort(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putShort(Object o, long offset, short x) {
+        theInternalUnsafe.putShort(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public char getChar(Object o, long offset) {
+        return theInternalUnsafe.getChar(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putChar(Object o, long offset, char x) {
+        theInternalUnsafe.putChar(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public long getLong(Object o, long offset) {
+        return theInternalUnsafe.getLong(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putLong(Object o, long offset, long x) {
+        theInternalUnsafe.putLong(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public float getFloat(Object o, long offset) {
+        return theInternalUnsafe.getFloat(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putFloat(Object o, long offset, float x) {
+        theInternalUnsafe.putFloat(o, offset, x);
+    }
+
+    /** @see #getInt(Object, long) */
+    @ForceInline
+    public double getDouble(Object o, long offset) {
+        return theInternalUnsafe.getDouble(o, offset);
+    }
+
+    /** @see #putInt(Object, long, int) */
+    @ForceInline
+    public void putDouble(Object o, long offset, double x) {
+        theInternalUnsafe.putDouble(o, offset, x);
+    }
+
+
+    // These read VM internal data.
+
+    /**
+     * Fetches an uncompressed reference value from a given native variable
+     * ignoring the VM's compressed references mode.
+     *
+     * @param address a memory address locating the variable
+     * @return the value fetched from the indicated native variable
+     */
+    @ForceInline
+    public Object getUncompressedObject(long address) {
+        return theInternalUnsafe.getUncompressedObject(address);
+    }
+
+    /**
+     * Fetches the {@link java.lang.Class} Java mirror for the given native
+     * metaspace {@code Klass} pointer.
+     *
+     * @param metaspaceKlass a native metaspace {@code Klass} pointer
+     * @return the {@link java.lang.Class} Java mirror
+     */
+    @ForceInline
+    public Class<?> getJavaMirror(long metaspaceKlass) {
+        return theInternalUnsafe.getJavaMirror(metaspaceKlass);
+    }
+
+    /**
+     * Fetches a native metaspace {@code Klass} pointer for the given Java
+     * object.
+     *
+     * @param o Java heap object for which to fetch the class pointer
+     * @return a native metaspace {@code Klass} pointer
+     */
+    @ForceInline
+    public long getKlassPointer(Object o) {
+        return theInternalUnsafe.getKlassPointer(o);
+    }
+
+    // These work on values in the C heap.
+
+    /**
+     * Fetches a value from a given memory address.  If the address is zero, or
+     * does not point into a block obtained from {@link #allocateMemory}, the
+     * results are undefined.
+     *
+     * @see #allocateMemory
+     */
+    @ForceInline
+    public byte getByte(long address) {
+        return theInternalUnsafe.getByte(address);
+    }
+
+    /**
+     * Stores a value into a given memory address.  If the address is zero, or
+     * does not point into a block obtained from {@link #allocateMemory}, the
+     * results are undefined.
+     *
+     * @see #getByte(long)
+     */
+    @ForceInline
+    public void putByte(long address, byte x) {
+        theInternalUnsafe.putByte(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public short getShort(long address) {
+        return theInternalUnsafe.getShort(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putShort(long address, short x) {
+        theInternalUnsafe.putShort(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public char getChar(long address) {
+        return theInternalUnsafe.getChar(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putChar(long address, char x) {
+        theInternalUnsafe.putChar(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public int getInt(long address) {
+        return theInternalUnsafe.getInt(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putInt(long address, int x) {
+        theInternalUnsafe.putInt(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public long getLong(long address) {
+        return theInternalUnsafe.getLong(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putLong(long address, long x) {
+        theInternalUnsafe.putLong(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public float getFloat(long address) {
+        return theInternalUnsafe.getFloat(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putFloat(long address, float x) {
+        theInternalUnsafe.putFloat(address, x);
+    }
+
+    /** @see #getByte(long) */
+    @ForceInline
+    public double getDouble(long address) {
+        return theInternalUnsafe.getDouble(address);
+    }
+
+    /** @see #putByte(long, byte) */
+    @ForceInline
+    public void putDouble(long address, double x) {
+        theInternalUnsafe.putDouble(address, x);
+    }
+
+
+    /**
+     * Fetches a native pointer from a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>If the native pointer is less than 64 bits wide, it is extended as
+     * an unsigned number to a Java long.  The pointer may be indexed by any
+     * given byte offset, simply by adding that offset (as a simple integer) to
+     * the long representing the pointer.  The number of bytes actually read
+     * from the target address may be determined by consulting {@link
+     * #addressSize}.
+     *
+     * @see #allocateMemory
+     */
+    @ForceInline
+    public long getAddress(long address) {
+        return theInternalUnsafe.getAddress(address);
+    }
+
+    /**
+     * Stores a native pointer into a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>The number of bytes actually written at the target address may be
+     * determined by consulting {@link #addressSize}.
+     *
+     * @see #getAddress(long)
+     */
+    @ForceInline
+    public void putAddress(long address, long x) {
+        theInternalUnsafe.putAddress(address, x);
+    }
+
+
+    /// wrappers for malloc, realloc, free:
+
+    /**
+     * Allocates a new block of native memory, of the given size in bytes.  The
+     * contents of the memory are uninitialized; they will generally be
+     * garbage.  The resulting native pointer will never be zero, and will be
+     * aligned for all value types.  Dispose of this memory by calling {@link
+     * #freeMemory}, or resize it with {@link #reallocateMemory}.
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @throws RuntimeException if the size is negative or too large
+     *         for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the system
+     *
+     * @see #getByte(long)
+     * @see #putByte(long, byte)
+     */
+    @ForceInline
+    public long allocateMemory(long bytes) {
+        return theInternalUnsafe.allocateMemory(bytes);
+    }
+
+    /**
+     * Resizes a new block of native memory, to the given size in bytes.  The
+     * contents of the new block past the size of the old block are
+     * uninitialized; they will generally be garbage.  The resulting native
+     * pointer will be zero if and only if the requested size is zero.  The
+     * resulting native pointer will be aligned for all value types.  Dispose
+     * of this memory by calling {@link #freeMemory}, or resize it with {@link
+     * #reallocateMemory}.  The address passed to this method may be null, in
+     * which case an allocation will be performed.
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @throws RuntimeException if the size is negative or too large
+     *         for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the system
+     *
+     * @see #allocateMemory
+     */
+    @ForceInline
+    public long reallocateMemory(long address, long bytes) {
+        return theInternalUnsafe.reallocateMemory(address, bytes);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a fixed value
+     * (usually zero).
+     *
+     * <p>This method determines a block's base address by means of two parameters,
+     * and so it provides (in effect) a <em>double-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
+     * the offset supplies an absolute base address.
+     *
+     * <p>The stores are in coherent (atomic) units of a size determined
+     * by the address and length parameters.  If the effective address and
+     * length are all even modulo 8, the stores take place in 'long' units.
+     * If the effective address and length are (resp.) even modulo 4 or 2,
+     * the stores take place in units of 'int' or 'short'.
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @throws RuntimeException if any of the arguments is invalid
+     *
+     * @since 1.7
+     */
+    @ForceInline
+    public void setMemory(Object o, long offset, long bytes, byte value) {
+        theInternalUnsafe.setMemory(o, offset, bytes, value);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a fixed value
+     * (usually zero).  This provides a <em>single-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.
+     *
+     * <p>Equivalent to {@code setMemory(null, address, bytes, value)}.
+     */
+    @ForceInline
+    public void setMemory(long address, long bytes, byte value) {
+        theInternalUnsafe.setMemory(address, bytes, value);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a copy of another
+     * block.
+     *
+     * <p>This method determines each block's base address by means of two parameters,
+     * and so it provides (in effect) a <em>double-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
+     * the offset supplies an absolute base address.
+     *
+     * <p>The transfers are in coherent (atomic) units of a size determined
+     * by the address and length parameters.  If the effective addresses and
+     * length are all even modulo 8, the transfer takes place in 'long' units.
+     * If the effective addresses and length are (resp.) even modulo 4 or 2,
+     * the transfer takes place in units of 'int' or 'short'.
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @throws RuntimeException if any of the arguments is invalid
+     *
+     * @since 1.7
+     */
+    @ForceInline
+    public void copyMemory(Object srcBase, long srcOffset,
+                           Object destBase, long destOffset,
+                           long bytes) {
+        theInternalUnsafe.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a copy of another
+     * block.  This provides a <em>single-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.
+     *
+     * Equivalent to {@code copyMemory(null, srcAddress, null, destAddress, bytes)}.
+     */
+    @ForceInline
+    public void copyMemory(long srcAddress, long destAddress, long bytes) {
+        theInternalUnsafe.copyMemory(srcAddress, destAddress, bytes);
+    }
+
+    /**
+     * Disposes of a block of native memory, as obtained from {@link
+     * #allocateMemory} or {@link #reallocateMemory}.  The address passed to
+     * this method may be null, in which case no action is taken.
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @throws RuntimeException if any of the arguments is invalid
+     *
+     * @see #allocateMemory
+     */
+    @ForceInline
+    public void freeMemory(long address) {
+        theInternalUnsafe.freeMemory(address);
+    }
+
+    /// random queries
+
+    /**
+     * This constant differs from all results that will ever be returned from
+     * {@link #staticFieldOffset}, {@link #objectFieldOffset},
+     * or {@link #arrayBaseOffset}.
+     */
+    public static final int INVALID_FIELD_OFFSET = jdk.internal.misc.Unsafe.INVALID_FIELD_OFFSET;
+
+    /**
+     * Reports the location of a given field in the storage allocation of its
+     * class.  Do not expect to perform any sort of arithmetic on this offset;
+     * it is just a cookie which is passed to the unsafe heap memory accessors.
+     *
+     * <p>Any given field will always have the same offset and base, and no
+     * two distinct fields of the same class will ever have the same offset
+     * and base.
+     *
+     * <p>As of 1.4.1, offsets for fields are represented as long values,
+     * although the Sun JVM does not use the most significant 32 bits.
+     * However, JVM implementations which store static fields at absolute
+     * addresses can use long offsets and null base pointers to express
+     * the field locations in a form usable by {@link #getInt(Object,long)}.
+     * Therefore, code which will be ported to such JVMs on 64-bit platforms
+     * must preserve all bits of static field offsets.
+     * @see #getInt(Object, long)
+     */
+    @ForceInline
+    public long objectFieldOffset(Field f) {
+        return theInternalUnsafe.objectFieldOffset(f);
+    }
+
+    /**
+     * Reports the location of a given static field, in conjunction with {@link
+     * #staticFieldBase}.
+     * <p>Do not expect to perform any sort of arithmetic on this offset;
+     * it is just a cookie which is passed to the unsafe heap memory accessors.
+     *
+     * <p>Any given field will always have the same offset, and no two distinct
+     * fields of the same class will ever have the same offset.
+     *
+     * <p>As of 1.4.1, offsets for fields are represented as long values,
+     * although the Sun JVM does not use the most significant 32 bits.
+     * It is hard to imagine a JVM technology which needs more than
+     * a few bits to encode an offset within a non-array object,
+     * However, for consistency with other methods in this class,
+     * this method reports its result as a long value.
+     * @see #getInt(Object, long)
+     */
+    @ForceInline
+    public long staticFieldOffset(Field f) {
+        return theInternalUnsafe.staticFieldOffset(f);
+    }
+
+    /**
+     * Reports the location of a given static field, in conjunction with {@link
+     * #staticFieldOffset}.
+     * <p>Fetch the base "Object", if any, with which static fields of the
+     * given class can be accessed via methods like {@link #getInt(Object,
+     * long)}.  This value may be null.  This value may refer to an object
+     * which is a "cookie", not guaranteed to be a real Object, and it should
+     * not be used in any way except as argument to the get and put routines in
+     * this class.
+     */
+    @ForceInline
+    public Object staticFieldBase(Field f) {
+        return theInternalUnsafe.staticFieldBase(f);
+    }
+
+    /**
+     * Detects if the given class may need to be initialized. This is often
+     * needed in conjunction with obtaining the static field base of a
+     * class.
+     * @return false only if a call to {@code ensureClassInitialized} would have no effect
+     */
+    @ForceInline
+    public boolean shouldBeInitialized(Class<?> c) {
+        return theInternalUnsafe.shouldBeInitialized(c);
+    }
+
+    /**
+     * Ensures the given class has been initialized. This is often
+     * needed in conjunction with obtaining the static field base of a
+     * class.
+     */
+    @ForceInline
+    public void ensureClassInitialized(Class<?> c) {
+        theInternalUnsafe.ensureClassInitialized(c);
+    }
+
+    /**
+     * Reports the offset of the first element in the storage allocation of a
+     * given array class.  If {@link #arrayIndexScale} returns a non-zero value
+     * for the same class, you may use that scale factor, together with this
+     * base offset, to form new offsets to access elements of arrays of the
+     * given class.
+     *
+     * @see #getInt(Object, long)
+     * @see #putInt(Object, long, int)
+     */
+    @ForceInline
+    public int arrayBaseOffset(Class<?> arrayClass) {
+        return theInternalUnsafe.arrayBaseOffset(arrayClass);
+    }
+
+    /** The value of {@code arrayBaseOffset(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(byte[].class)} */
+    public static final int ARRAY_BYTE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(short[].class)} */
+    public static final int ARRAY_SHORT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(char[].class)} */
+    public static final int ARRAY_CHAR_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_CHAR_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(int[].class)} */
+    public static final int ARRAY_INT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_INT_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(long[].class)} */
+    public static final int ARRAY_LONG_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_LONG_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(float[].class)} */
+    public static final int ARRAY_FLOAT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(double[].class)} */
+    public static final int ARRAY_DOUBLE_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+
+    /** The value of {@code arrayBaseOffset(Object[].class)} */
+    public static final int ARRAY_OBJECT_BASE_OFFSET = jdk.internal.misc.Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+
+    /**
+     * Reports the scale factor for addressing elements in the storage
+     * allocation of a given array class.  However, arrays of "narrow" types
+     * will generally not work properly with accessors like {@link
+     * #getByte(Object, long)}, so the scale factor for such classes is reported
+     * as zero.
+     *
+     * @see #arrayBaseOffset
+     * @see #getInt(Object, long)
+     * @see #putInt(Object, long, int)
+     */
+    @ForceInline
+    public int arrayIndexScale(Class<?> arrayClass) {
+        return theInternalUnsafe.arrayIndexScale(arrayClass);
+    }
+
+    /** The value of {@code arrayIndexScale(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(byte[].class)} */
+    public static final int ARRAY_BYTE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(short[].class)} */
+    public static final int ARRAY_SHORT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(char[].class)} */
+    public static final int ARRAY_CHAR_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_CHAR_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(int[].class)} */
+    public static final int ARRAY_INT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_INT_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(long[].class)} */
+    public static final int ARRAY_LONG_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_LONG_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(float[].class)} */
+    public static final int ARRAY_FLOAT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(double[].class)} */
+    public static final int ARRAY_DOUBLE_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+
+    /** The value of {@code arrayIndexScale(Object[].class)} */
+    public static final int ARRAY_OBJECT_INDEX_SCALE = jdk.internal.misc.Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+
+    /**
+     * Reports the size in bytes of a native pointer, as stored via {@link
+     * #putAddress}.  This value will be either 4 or 8.  Note that the sizes of
+     * other primitive types (as stored in native memory blocks) is determined
+     * fully by their information content.
+     */
+    @ForceInline
+    public int addressSize() {
+        return theInternalUnsafe.addressSize();
+    }
+
+    /** The value of {@code addressSize()} */
+    public static final int ADDRESS_SIZE = theInternalUnsafe.addressSize();
+
+    /**
+     * Reports the size in bytes of a native memory page (whatever that is).
+     * This value will always be a power of two.
+     */
+    @ForceInline
+    public int pageSize() {
+        return theInternalUnsafe.pageSize();
+    }
+
+
+    /// random trusted operations from JNI:
+
+    /**
+     * Tells the VM to define a class, without security checks.  By default, the
+     * class loader and protection domain come from the caller's class.
+     */
+    @ForceInline
+    public Class<?> defineClass(String name, byte[] b, int off, int len,
+                                ClassLoader loader,
+                                ProtectionDomain protectionDomain) {
+        return theInternalUnsafe.defineClass(name, b, off, len, loader, protectionDomain);
+    }
+
+    /**
+     * Defines a class but does not make it known to the class loader or system dictionary.
+     * <p>
+     * For each CP entry, the corresponding CP patch must either be null or have
+     * the a format that matches its tag:
+     * <ul>
+     * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang
+     * <li>Utf8: a string (must have suitable syntax if used as signature or name)
+     * <li>Class: any java.lang.Class object
+     * <li>String: any object (not just a java.lang.String)
+     * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments
+     * </ul>
+     * @param hostClass context for linkage, access control, protection domain, and class loader
+     * @param data      bytes of a class file
+     * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data
+     */
+    @ForceInline
+    public Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches) {
+        return theInternalUnsafe.defineAnonymousClass(hostClass, data, cpPatches);
+    }
+
+    /**
+     * Allocates an instance but does not run any constructor.
+     * Initializes the class if it has not yet been.
+     */
+    @ForceInline
+    public Object allocateInstance(Class<?> cls)
+        throws InstantiationException {
+        return theInternalUnsafe.allocateInstance(cls);
+    }
+
+    /** Throws the exception without telling the verifier. */
+    @ForceInline
+    public void throwException(Throwable ee) {
+        theInternalUnsafe.throwException(ee);
+    }
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @ForceInline
+    public final boolean compareAndSwapObject(Object o, long offset,
+                                              Object expected,
+                                              Object x) {
+        return theInternalUnsafe.compareAndSwapObject(o, offset, expected, x);
+    }
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @ForceInline
+    public final boolean compareAndSwapInt(Object o, long offset,
+                                           int expected,
+                                           int x) {
+        return theInternalUnsafe.compareAndSwapInt(o, offset, expected, x);
+    }
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @ForceInline
+    public final boolean compareAndSwapLong(Object o, long offset,
+                                            long expected,
+                                            long x) {
+        return theInternalUnsafe.compareAndSwapLong(o, offset, expected, x);
+    }
+
+    /**
+     * Fetches a reference value from a given Java variable, with volatile
+     * load semantics. Otherwise identical to {@link #getObject(Object, long)}
+     */
+    @ForceInline
+    public Object getObjectVolatile(Object o, long offset) {
+        return theInternalUnsafe.getObjectVolatile(o, offset);
+    }
+
+    /**
+     * Stores a reference value into a given Java variable, with
+     * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
+     */
+    @ForceInline
+    public void putObjectVolatile(Object o, long offset, Object x) {
+        theInternalUnsafe.putObjectVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getInt(Object, long)}  */
+    @ForceInline
+    public int getIntVolatile(Object o, long offset) {
+        return theInternalUnsafe.getIntVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putInt(Object, long, int)}  */
+    @ForceInline
+    public void putIntVolatile(Object o, long offset, int x) {
+        theInternalUnsafe.putIntVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getBoolean(Object, long)}  */
+    @ForceInline
+    public boolean getBooleanVolatile(Object o, long offset) {
+        return theInternalUnsafe.getBooleanVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putBoolean(Object, long, boolean)}  */
+    @ForceInline
+    public void putBooleanVolatile(Object o, long offset, boolean x) {
+        theInternalUnsafe.putBooleanVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getByte(Object, long)}  */
+    @ForceInline
+    public byte getByteVolatile(Object o, long offset) {
+        return theInternalUnsafe.getByteVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putByte(Object, long, byte)}  */
+    @ForceInline
+    public void putByteVolatile(Object o, long offset, byte x) {
+        theInternalUnsafe.putByteVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getShort(Object, long)}  */
+    @ForceInline
+    public short getShortVolatile(Object o, long offset) {
+        return theInternalUnsafe.getShortVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putShort(Object, long, short)}  */
+    @ForceInline
+    public void putShortVolatile(Object o, long offset, short x) {
+        theInternalUnsafe.putShortVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getChar(Object, long)}  */
+    @ForceInline
+    public char getCharVolatile(Object o, long offset) {
+        return theInternalUnsafe.getCharVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putChar(Object, long, char)}  */
+    @ForceInline
+    public void putCharVolatile(Object o, long offset, char x) {
+        theInternalUnsafe.putCharVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getLong(Object, long)}  */
+    @ForceInline
+    public long getLongVolatile(Object o, long offset) {
+        return theInternalUnsafe.getLongVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putLong(Object, long, long)}  */
+    @ForceInline
+    public void putLongVolatile(Object o, long offset, long x) {
+        theInternalUnsafe.putLongVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getFloat(Object, long)}  */
+    @ForceInline
+    public float getFloatVolatile(Object o, long offset) {
+        return theInternalUnsafe.getFloatVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putFloat(Object, long, float)}  */
+    @ForceInline
+    public void putFloatVolatile(Object o, long offset, float x) {
+        theInternalUnsafe.putFloatVolatile(o, offset, x);
+    }
+
+    /** Volatile version of {@link #getDouble(Object, long)}  */
+    @ForceInline
+    public double getDoubleVolatile(Object o, long offset) {
+        return theInternalUnsafe.getDoubleVolatile(o, offset);
+    }
+
+    /** Volatile version of {@link #putDouble(Object, long, double)}  */
+    @ForceInline
+    public void putDoubleVolatile(Object o, long offset, double x) {
+        theInternalUnsafe.putDoubleVolatile(o, offset, x);
+    }
+
+    /**
+     * Version of {@link #putObjectVolatile(Object, long, Object)}
+     * that does not guarantee immediate visibility of the store to
+     * other threads. This method is generally only useful if the
+     * underlying field is a Java volatile (or if an array cell, one
+     * that is otherwise only accessed using volatile accesses).
+     *
+     * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
+     */
+    @ForceInline
+    public void putOrderedObject(Object o, long offset, Object x) {
+        theInternalUnsafe.putObjectRelease(o, offset, x);
+    }
+
+    /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
+    @ForceInline
+    public void putOrderedInt(Object o, long offset, int x) {
+        theInternalUnsafe.putIntRelease(o, offset, x);
+    }
+
+    /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
+    @ForceInline
+    public void putOrderedLong(Object o, long offset, long x) {
+        theInternalUnsafe.putLongRelease(o, offset, x);
+    }
+
+    /**
+     * Unblocks the given thread blocked on {@code park}, or, if it is
+     * not blocked, causes the subsequent call to {@code park} not to
+     * block.  Note: this operation is "unsafe" solely because the
+     * caller must somehow ensure that the thread has not been
+     * destroyed. Nothing special is usually required to ensure this
+     * when called from Java (in which there will ordinarily be a live
+     * reference to the thread) but this is not nearly-automatically
+     * so when calling from native code.
+     *
+     * @param thread the thread to unpark.
+     */
+    @ForceInline
+    public void unpark(Object thread) {
+        theInternalUnsafe.unpark(thread);
+    }
+
+    /**
+     * Blocks current thread, returning when a balancing
+     * {@code unpark} occurs, or a balancing {@code unpark} has
+     * already occurred, or the thread is interrupted, or, if not
+     * absolute and time is not zero, the given time nanoseconds have
+     * elapsed, or if absolute, the given deadline in milliseconds
+     * since Epoch has passed, or spuriously (i.e., returning for no
+     * "reason"). Note: This operation is in the Unsafe class only
+     * because {@code unpark} is, so it would be strange to place it
+     * elsewhere.
+     */
+    @ForceInline
+    public void park(boolean isAbsolute, long time) {
+        theInternalUnsafe.park(isAbsolute, time);
+    }
+
+    /**
+     * Gets the load average in the system run queue assigned
+     * to the available processors averaged over various periods of time.
+     * This method retrieves the given {@code nelem} samples and
+     * assigns to the elements of the given {@code loadavg} array.
+     * The system imposes a maximum of 3 samples, representing
+     * averages over the last 1,  5,  and  15 minutes, respectively.
+     *
+     * @param loadavg an array of double of size nelems
+     * @param nelems the number of samples to be retrieved and
+     *        must be 1 to 3.
+     *
+     * @return the number of samples actually retrieved; or -1
+     *         if the load average is unobtainable.
+     */
+    @ForceInline
+    public int getLoadAverage(double[] loadavg, int nelems) {
+        return theInternalUnsafe.getLoadAverage(loadavg, nelems);
+    }
+
+    // The following contain CAS-based Java implementations used on
+    // platforms not supporting native instructions
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @ForceInline
+    public final int getAndAddInt(Object o, long offset, int delta) {
+        return theInternalUnsafe.getAndAddInt(o, offset, delta);
+    }
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @ForceInline
+    public final long getAndAddLong(Object o, long offset, long delta) {
+        return theInternalUnsafe.getAndAddLong(o, offset, delta);
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @ForceInline
+    public final int getAndSetInt(Object o, long offset, int newValue) {
+        return theInternalUnsafe.getAndSetInt(o, offset, newValue);
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @ForceInline
+    public final long getAndSetLong(Object o, long offset, long newValue) {
+        return theInternalUnsafe.getAndSetLong(o, offset, newValue);
+    }
+
+    /**
+     * Atomically exchanges the given reference value with the current
+     * reference value of a field or array element within the given
+     * object {@code o} at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @ForceInline
+    public final Object getAndSetObject(Object o, long offset, Object newValue) {
+        return theInternalUnsafe.getAndSetObject(o, offset, newValue);
+    }
+
+
+    /**
+     * Ensures that loads before the fence will not be reordered with loads and
+     * stores after the fence; a "LoadLoad plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
+     * (an "acquire fence").
+     *
+     * A pure LoadLoad fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a LoadLoad barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @ForceInline
+    public void loadFence() {
+        theInternalUnsafe.loadFence();
+    }
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered with
+     * stores after the fence; a "StoreStore plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_release)
+     * (a "release fence").
+     *
+     * A pure StoreStore fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a StoreStore barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @ForceInline
+    public void storeFence() {
+        theInternalUnsafe.storeFence();
+    }
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered
+     * with loads and stores after the fence.  Implies the effects of both
+     * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
+     * barrier.
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
+     * @since 1.8
+     */
+    @ForceInline
+    public void fullFence() {
+        theInternalUnsafe.fullFence();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.unsupported/unix/classes/sun/misc/GThreadHelper.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * This class is used to prevent multiple calling of g_thread_init ()
+ * and gdk_thread_init ().
+ *
+ * Since version 2.24 of GLib, calling g_thread_init () multiple times is
+ * allowed, but it will crash for older versions. There are two ways to
+ * find out if g_thread_init () has been called:
+ * g_thread_get_initialized (), but it was introduced in 2.20
+ * g_thread_supported (), but it is a macro and cannot be loaded with dlsym.
+ *
+ * usage:
+ * <pre>
+ * lock();
+ * try {
+ *    if (!getAndSetInitializationNeededFlag()) {
+ *        //call to g_thread_init();
+ *        //call to gdk_thread_init();
+ *    }
+ * } finally {
+ *    unlock();
+ * }
+ * </pre>
+ */
+public final class GThreadHelper {
+
+    private static final ReentrantLock LOCK = new ReentrantLock();
+    private static boolean isGThreadInitialized = false;
+
+    /**
+     * Acquires the lock.
+     */
+    public static void lock() {
+        LOCK.lock();
+    }
+
+    /**
+     * Releases the lock.
+     */
+    public static void unlock() {
+        LOCK.unlock();
+    }
+
+    /**
+     * Gets current value of initialization flag and sets it to {@code true}.
+     * MUST be called under the lock.
+     *
+     * A return value of {@code false} indicates that the calling code
+     * should call the g_thread_init() and gdk_thread_init() functions
+     * before releasing the lock.
+     *
+     * @return {@code true} if initialization has been completed.
+     */
+    public static boolean getAndSetInitializationNeededFlag() {
+        boolean ret = isGThreadInitialized;
+        isGThreadInitialized = true;
+        return ret;
+    }
+}
--- a/test/ProblemList.txt	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/ProblemList.txt	Mon Apr 11 11:19:33 2016 -0700
@@ -159,8 +159,6 @@
 
 # jdk_net
 
-sun/net/InetAddress/nameservice/simple/CacheTest.java           7148829 generic-all
-sun/net/InetAddress/nameservice/simple/DefaultCaching.java      7148829 generic-all
 
 java/net/MulticastSocket/NoLoopbackPackets.java                 7122846 macosx-all
 java/net/MulticastSocket/SetLoopbackMode.java                   7122846 macosx-all
@@ -238,7 +236,7 @@
 sun/security/pkcs11/MessageDigest/ReinitDigest.java             8077138,8023434 windows-all
 sun/security/pkcs11/MessageDigest/TestCloning.java              8077138,8023434 windows-all
 sun/security/pkcs11/Provider/ConfigQuotedString.sh              8077138,8023434 windows-all
-sun/security/pkcs11/Provider/Login.sh                           8077138,8023434 windows-all
+sun/security/pkcs11/Provider/Login.sh                           8077138,8023434,8153545 windows-all,linux-all
 sun/security/pkcs11/SampleTest.java                             8077138,8023434 windows-all
 sun/security/pkcs11/Secmod/AddPrivateKey.java                   8077138,8023434 windows-all
 sun/security/pkcs11/Secmod/AddTrustedCert.java                  8077138,8023434 windows-all
@@ -282,11 +280,16 @@
 
 sun/security/tools/keytool/autotest.sh                          8130302 generic-all
 
+sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java    8137255 generic-all
+
+sun/security/x509/URICertStore/ExtensionsWithLDAP.java          8134577 generic-all
+
 ############################################################################
 
 # jdk_sound
 
 javax/sound/midi/Gervill/SoftProvider/GetDevice.java            8059743 generic-all
+javax/sound/sampled/DirectAudio/bug6400879.java                 8148915 linux-all
 
 ############################################################################
 
@@ -307,6 +310,7 @@
 
 # jdk_time
 
+
 ############################################################################
 
 # jdk_tools
@@ -315,8 +319,6 @@
 
 tools/pack200/Pack200Test.java                                  8059906,8151901 generic-all
 
-tools/pack200/Pack200Props.java                                 8152622 macosx-all
-
 tools/launcher/FXLauncherTest.java                              8068049 linux-all,macosx-all
 
 ############################################################################
--- a/test/com/sun/jdi/cds/CDSBreakpointTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/com/sun/jdi/cds/CDSBreakpointTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,7 +26,6 @@
  * @bug 8054386
  * @summary java debugging test for CDS
  * @modules jdk.jdi
- *          java.base/sun.misc
  *          java.management
  *          jdk.jartool/sun.tools.jar
  * @library /lib/testlibrary
--- a/test/com/sun/jdi/cds/CDSDeleteAllBkptsTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/com/sun/jdi/cds/CDSDeleteAllBkptsTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,7 +26,6 @@
  * @bug 8054386
  * @summary java debugging test for CDS
  * @modules jdk.jdi
- *          java.base/sun.misc
  *          java.management
  *          jdk.jartool/sun.tools.jar
  * @library /lib/testlibrary
--- a/test/com/sun/jdi/cds/CDSFieldWatchpoints.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/com/sun/jdi/cds/CDSFieldWatchpoints.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,7 +26,6 @@
  * @bug 8054386
  * @summary java debugging test for CDS
  * @modules jdk.jdi
- *          java.base/sun.misc
  *          java.management
  *          jdk.jartool/sun.tools.jar
  * @library /lib/testlibrary
--- a/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -113,7 +113,8 @@
 case "$OS" in
   Windows* | CYGWIN* )
     ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          *.java
     status=$?
     if [ ! $status -eq "0" ]; then
@@ -123,7 +124,8 @@
 
   SunOS | Linux )
     ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                          *.java
     status=$?
     if [ ! $status -eq "0" ]; then
@@ -133,7 +135,8 @@
 
   Darwin)
     ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
                          *.java
     status=$?
     if [ ! $status -eq "0" ]; then
@@ -151,14 +154,16 @@
 case "$OS" in
   Windows* | CYGWIN* )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          TestWrapped sun.awt.windows.WToolkit
     status=$?
     if [ ! $status -eq "0" ]; then
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit";
     fi
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.windows.WToolkit \
                          TestWrapped sun.awt.windows.WToolkit
     status=$?
@@ -169,7 +174,8 @@
 
   SunOS | Linux )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.X11.XToolkit \
                          TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -177,7 +183,8 @@
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
     fi
     AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                                               -Djava.awt.headless=true \
                                               TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -188,14 +195,16 @@
 
   Darwin)
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
                          TestWrapped sun.lwawt.macosx.LWCToolkit
     status=$?
     if [ ! $status -eq "0" ]; then
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
     fi
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
+                         -XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \
                          TestWrapped sun.lwawt.macosx.LWCToolkit
     status=$?
--- a/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -61,8 +61,8 @@
  *          loads all the classes in the BCL, get their declared fields,
  *          and call setAccessible(false) followed by setAccessible(true);
  * @modules java.base/jdk.internal.module
- * @run main/othervm FieldSetAccessibleTest UNSECURE
- * @run main/othervm FieldSetAccessibleTest SECURE
+ * @run main/othervm -Djdk.launcher.addmods=ALL-SYSTEM FieldSetAccessibleTest UNSECURE
+ * @run main/othervm -Djdk.launcher.addmods=ALL-SYSTEM FieldSetAccessibleTest SECURE
  *
  * @author danielfuchs
  */
--- a/test/java/lang/ProcessBuilder/Basic.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessBuilder/Basic.java	Mon Apr 11 11:19:33 2016 -0700
@@ -29,7 +29,6 @@
  *      4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464
  *      8067796
  * @summary Basic tests for Process and Environment Variable code
- * @modules java.base/sun.misc
  * @run main/othervm/timeout=300 Basic
  * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
  * @author Martin Buchholz
--- a/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessBuilder/RedirectWithLongFilename.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,7 +25,6 @@
  * @test
  * @bug 8072611
  * @summary ProcessBuilder Redirect to file appending on Windows should work with long file names
- * @modules java.base/sun.misc
  * @author Thomas Stuefe
  */
 
--- a/test/java/lang/ProcessHandle/Basic.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessHandle/Basic.java	Mon Apr 11 11:19:33 2016 -0700
@@ -37,7 +37,8 @@
 /*
  * @test
  * @library /test/lib/share/classes
- * @modules jdk.management
+ * @modules java.base/jdk.internal.misc
+ *          jdk.management
  * @run testng Basic
  * @summary Basic tests for ProcessHandler
  * @author Roger Riggs
--- a/test/java/lang/ProcessHandle/InfoTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessHandle/InfoTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -49,7 +49,8 @@
  * @test
  * @bug 8077350 8081566 8081567 8098852 8136597
  * @library /test/lib/share/classes
- * @modules jdk.management
+ * @modules java.base/jdk.internal.misc
+ *          jdk.management
  * @build jdk.test.lib.Platform jdk.test.lib.Utils
  * @run testng InfoTest
  * @summary Functions of ProcessHandle.Info
--- a/test/java/lang/ProcessHandle/OnExitTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessHandle/OnExitTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -39,7 +39,8 @@
 /*
  * @test
  * @library /test/lib/share/classes
- * @modules jdk.management
+ * @modules java.base/jdk.internal.misc
+ *          jdk.management
  * @build jdk.test.lib.Platform jdk.test.lib.Utils
  * @run testng OnExitTest
  * @summary Functions of Process.onExit and ProcessHandle.onExit
--- a/test/java/lang/ProcessHandle/TreeTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/ProcessHandle/TreeTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -45,7 +45,8 @@
 /*
  * @test
  * @library /test/lib/share/classes
- * @modules jdk.management
+ * @modules java.base/jdk.internal.misc
+ *          jdk.management
  * @build jdk.test.lib.Utils
  * @run testng/othervm TreeTest
  * @summary Test counting and JavaChild.spawning and counting of Processes.
--- a/test/java/lang/invoke/VMAnonymousClass.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/lang/invoke/VMAnonymousClass.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,7 +24,7 @@
 /* @test
  * @bug 8046903
  * @summary VM anonymous class members can't be statically invocable
- * @modules java.base/sun.misc java.base/jdk.internal.org.objectweb.asm
+ * @modules java.base/jdk.internal.misc java.base/jdk.internal.org.objectweb.asm
  * @run junit test.java.lang.invoke.VMAnonymousClass
  */
 package test.java.lang.invoke;
@@ -34,7 +34,7 @@
 import java.lang.invoke.MethodType;
 import java.lang.reflect.Field;
 import org.junit.Test;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.org.objectweb.asm.*;
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
@@ -43,17 +43,17 @@
         VMAnonymousClass test = new VMAnonymousClass();
         test.testJavaLang();
         test.testJavaUtil();
-        test.testSunMisc();
+        test.testJdkInternalMisc();
         test.testJavaLangInvoke();
         System.out.println("TEST PASSED");
     }
 
     // Test VM anonymous classes from different packages
     // (see j.l.i.InvokerBytecodeGenerator::isStaticallyInvocable).
-    @Test public void testJavaLang()       throws Throwable { test("java/lang");        }
-    @Test public void testJavaUtil()       throws Throwable { test("java/util");        }
-    @Test public void testSunMisc()        throws Throwable { test("sun/misc");         }
-    @Test public void testJavaLangInvoke() throws Throwable { test("java/lang/invoke"); }
+    @Test public void testJavaLang()        throws Throwable { test("java/lang");         }
+    @Test public void testJavaUtil()        throws Throwable { test("java/util");         }
+    @Test public void testJdkInternalMisc() throws Throwable { test("jdk/internal/misc"); }
+    @Test public void testJavaLangInvoke()  throws Throwable { test("java/lang/invoke");  }
 
     private static Unsafe unsafe = getUnsafe();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Function;
+
+public abstract class VarHandleBaseByteArrayTest extends VarHandleBaseTest {
+
+    enum MemoryMode {
+        ALIGNED(0, false), UNALIGNED(0, true),
+        BIG_ENDIAN(1, false), LITTLE_ENDIAN(1, true),
+        READ_WRITE(2, false), READ_ONLY(2, true),;
+
+        final int bit;
+        final int value;
+
+        MemoryMode(int bit, boolean value) {
+            this.bit = bit;
+            this.value = value ? 1 << bit : 0;
+        }
+
+        boolean isSet(int bitSet) {
+            return (bitSet & (1 << bit)) == value;
+        }
+
+        static int bitSet(MemoryMode... modes) {
+            if (modes == null) return 0;
+
+            int set = 0;
+            for (MemoryMode m : modes) {
+                set = (set & ~(1 << m.bit)) | m.value;
+            }
+            return set;
+        }
+
+        static EnumSet<MemoryMode> enumSet(int bitSet) {
+            EnumSet<MemoryMode> es = EnumSet.noneOf(MemoryMode.class);
+            for (MemoryMode m : values()) {
+                if (m.isSet(bitSet)) {
+                    es.add(m);
+                }
+            }
+            return es;
+        }
+    }
+
+    static class Source<T> {
+        final T s;
+        final int memoryModes;
+
+        public Source(T s, MemoryMode... modes) {
+            this.s = s;
+            memoryModes = MemoryMode.bitSet(modes);
+        }
+
+        @Override
+        public String toString() {
+            return s.getClass().getCanonicalName() + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static abstract class ByteArrayViewSource<T> extends Source<T> {
+        public ByteArrayViewSource(T t, MemoryMode... modes) {
+            super(t, modes);
+        }
+
+        abstract void fill(byte value);
+
+        abstract void fill(byte[] values);
+    }
+
+    static class ByteArraySource extends ByteArrayViewSource<byte[]> {
+        public ByteArraySource(byte[] bytes, MemoryMode... modes) {
+            super(bytes, modes);
+        }
+
+        void fill(byte value) {
+            Arrays.fill(s, value);
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.length; i++) {
+                s[i] = values[i % values.length];
+            }
+        }
+    }
+
+    static class ByteBufferSource extends ByteArrayViewSource<ByteBuffer> {
+        public ByteBufferSource(ByteBuffer buffer, MemoryMode... modes) {
+            super(buffer, modes);
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, values[i % values.length]);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return s + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class ByteBufferReadOnlySource extends ByteBufferSource {
+        final ByteBuffer rwSource;
+
+        public ByteBufferReadOnlySource(ByteBuffer roBuffer, ByteBuffer rwSource, MemoryMode... modes) {
+            super(roBuffer, modes);
+            this.rwSource = rwSource;
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, values[i % values.length]);
+            }
+        }
+    }
+
+    static class VarHandleSource extends Source<VarHandle> {
+        VarHandleSource(VarHandle vh, MemoryMode... modes) {
+            super(vh, modes);
+        }
+
+        boolean matches(ByteArrayViewSource<?> bav) {
+            return s.coordinateTypes().get(0).isAssignableFrom(bav.s.getClass());
+        }
+
+        @Override
+        public String toString() {
+            return " VarHandle " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class VarHandleSourceAccessTestCase extends AccessTestCase<VarHandleSource> {
+        final ByteArrayViewSource<?> bs;
+        final VarHandleSource vhs;
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata) {
+            this(desc, bs, vhs, ata, true);
+        }
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata, boolean loop) {
+            super(vhs + " -> " + bs + " " + desc, ata, loop);
+            this.bs = bs;
+            this.vhs = vhs;
+        }
+
+        @Override
+        VarHandleSource get() {
+            return vhs;
+        }
+    }
+
+
+    static double rotateLeft(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateLeft(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static double rotateRight(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateRight(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static float rotateLeft(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateLeft(Float.floatToRawIntBits(i), distance));
+    }
+
+    static float rotateRight(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateRight(Float.floatToRawIntBits(i), distance));
+    }
+
+    static long rotateLeft(long i, int distance) {
+        return Long.rotateLeft(i, distance);
+    }
+
+    static long rotateRight(long i, int distance) {
+        return Long.rotateRight(i, distance);
+    }
+
+    static int rotateLeft(int i, int distance) {
+        return Integer.rotateLeft(i, distance);
+    }
+
+    static int rotateRight(int i, int distance) {
+        return Integer.rotateRight(i, distance);
+    }
+
+    static short rotateLeft(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (short) v;
+    }
+
+    static short rotateRight(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (short) v;
+    }
+
+    static char rotateLeft(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (char) v;
+    }
+
+    static char rotateRight(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (char) v;
+    }
+
+    static final int LENGTH_BYTES = 32;
+
+    byte[] array;
+
+    List<ByteArrayViewSource<?>> bavss;
+
+    List<VarHandleSource> vhss;
+
+    public void setupByteSources() {
+        array = new byte[LENGTH_BYTES];
+
+        // Native endianess
+        MemoryMode ne = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN
+                        ? MemoryMode.BIG_ENDIAN : MemoryMode.LITTLE_ENDIAN;
+
+        bavss = new ArrayList<>();
+
+        // byte[] source
+        ByteArraySource a =
+                new ByteArraySource(array,
+                                    ne, MemoryMode.READ_WRITE);
+        bavss.add(a);
+
+
+        // Combinations of ByteBuffer sources
+        ByteBufferSource hbb =
+                new ByteBufferSource(ByteBuffer.wrap(array),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb);
+        ByteBufferReadOnlySource hbb_ro =
+                new ByteBufferReadOnlySource(hbb.s.asReadOnlyBuffer(), hbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_ro);
+
+        ByteBufferSource hbb_offset_aligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4, array.length / 2).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_aligned);
+        ByteBufferReadOnlySource hbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_aligned.s.asReadOnlyBuffer(), hbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_aligned_ro);
+
+        ByteBufferSource hbb_offset_unaligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4 - 1, array.length / 2).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_unaligned);
+        ByteBufferReadOnlySource hbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_unaligned.s.asReadOnlyBuffer(), hbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_unaligned_ro);
+
+
+        ByteBufferSource dbb =
+                new ByteBufferSource(ByteBuffer.allocateDirect(array.length),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb);
+        ByteBufferReadOnlySource dbb_ro =
+                new ByteBufferReadOnlySource(dbb.s.asReadOnlyBuffer(), dbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_ro);
+
+        ByteBufferSource dbb_offset_aligned =
+                new ByteBufferSource(dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_aligned);
+        ByteBufferReadOnlySource dbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_aligned.s.asReadOnlyBuffer(), dbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_aligned_ro);
+
+        ByteBufferSource dbb_offset_unaligned =
+                new ByteBufferSource(dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_unaligned);
+        ByteBufferReadOnlySource dbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_unaligned.s.asReadOnlyBuffer(), dbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_unaligned_ro);
+    }
+
+    @BeforeClass
+    public void setup() {
+        setupByteSources();
+        setupVarHandleSources();
+    }
+
+    abstract void setupVarHandleSources();
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        return vhss.stream().map(cvh -> new Object[]{cvh}).toArray(Object[][]::new);
+    }
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<java.lang.Class<?>> aepts = Arrays.asList(byte[].class, int.class);
+        List<java.lang.Class<?>> bbpts = Arrays.asList(ByteBuffer.class, int.class);
+
+        Function<VarHandle, List<Class<?>>> vhToPts = vh ->
+                vh.coordinateTypes().get(0) == byte[].class ? aepts : bbpts;
+
+        return vhss.stream().map(vh -> new Object[]{vh.s, vhToPts.apply(vh.s)}).toArray(Object[][]::new);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Method;
+import java.nio.ReadOnlyBufferException;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.*;
+
+abstract class VarHandleBaseTest {
+    static final int ITERS = Integer.getInteger("iters", 1);
+
+    interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+
+    static void checkUOE(ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, null, r);
+    }
+
+    static void checkUOE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, message, r);
+    }
+
+    static void checkROBE(ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, null, r);
+    }
+
+    static void checkROBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, message, r);
+    }
+
+    static void checkIOOBE(ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, null, r);
+    }
+
+    static void checkIOOBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, message, r);
+    }
+
+    static void checkISE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, null, r);
+    }
+
+    static void checkISE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, message, r);
+    }
+
+    static void checkIAE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, null, r);
+    }
+
+    static void checkIAE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, message, r);
+    }
+
+    static void checkWMTE(ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, null, r);
+    }
+
+    static void checkWMTE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, message, r);
+    }
+
+    static void checkCCE(ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, null, r);
+    }
+
+    static void checkCCE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, message, r);
+    }
+
+    static void checkNPE(ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, null, r);
+    }
+
+    static void checkNPE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, message, r);
+    }
+
+    static void checkWithThrowable(Class<? extends Throwable> re,
+                                   Object message,
+                                   ThrowingRunnable r) {
+        Throwable _e = null;
+        try {
+            r.run();
+        }
+        catch (Throwable e) {
+            _e = e;
+        }
+        message = message == null ? "" : message + ". ";
+        assertNotNull(_e, String.format("%sNo throwable thrown. Expected %s", message, re));
+        assertTrue(re.isInstance(_e), String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re));
+    }
+
+
+    enum TestAccessType {
+        get,
+        set,
+        compareAndSet,
+        compareAndExchange,
+        getAndSet,
+        getAndAdd;
+    }
+
+    enum TestAccessMode {
+        get(TestAccessType.get),
+        set(TestAccessType.set),
+        getVolatile(TestAccessType.get),
+        setVolatile(TestAccessType.set),
+        getAcquire(TestAccessType.get),
+        setRelease(TestAccessType.set),
+        getOpaque(TestAccessType.get),
+        setOpaque(TestAccessType.set),
+        compareAndSet(TestAccessType.compareAndSet),
+        compareAndExchangeVolatile(TestAccessType.compareAndExchange),
+        compareAndExchangeAcquire(TestAccessType.compareAndExchange),
+        compareAndExchangeRelease(TestAccessType.compareAndExchange),
+        weakCompareAndSet(TestAccessType.compareAndSet),
+        weakCompareAndSetAcquire(TestAccessType.compareAndSet),
+        weakCompareAndSetRelease(TestAccessType.compareAndSet),
+        getAndSet(TestAccessType.getAndSet),
+        getAndAdd(TestAccessType.getAndAdd),
+        addAndGet(TestAccessType.getAndAdd),;
+
+        final TestAccessType at;
+        final boolean isPolyMorphicInReturnType;
+        final Class<?> returnType;
+
+        TestAccessMode(TestAccessType at) {
+            this.at = at;
+
+            try {
+                Method m = VarHandle.class.getMethod(name(), Object[].class);
+                this.returnType = m.getReturnType();
+                isPolyMorphicInReturnType = returnType != Object.class;
+            }
+            catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+
+        boolean isOfType(TestAccessType at) {
+            return this.at == at;
+        }
+
+        VarHandle.AccessMode toAccessMode() {
+            return VarHandle.AccessMode.valueOf(name());
+        }
+    }
+
+    static List<TestAccessMode> testAccessModes() {
+        return Stream.of(TestAccessMode.values()).collect(toList());
+    }
+
+    static List<TestAccessMode> testAccessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        for (TestAccessType at : ats) {
+            s = s.filter(e -> e.isOfType(at));
+        }
+        return s.collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModes() {
+        return Stream.of(VarHandle.AccessMode.values()).collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        for (TestAccessType at : ats) {
+            s = s.filter(e -> e.isOfType(at));
+        }
+        return s.map(TestAccessMode::toAccessMode).collect(toList());
+    }
+
+    static MethodHandle toMethodHandle(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        return vh.toMethodHandle(tam.toAccessMode());
+    }
+
+    static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh;
+        try {
+            mh = MethodHandles.publicLookup().
+                    findVirtual(VarHandle.class,
+                                tam.name(),
+                                mt);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleInvokerWithSymbolicTypeDescriptor(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleExactInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh = MethodHandles.varHandleExactInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    private static MethodHandle bind(VarHandle vh, TestAccessMode testAccessMode, MethodHandle mh, MethodType emt) {
+        assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class),
+                     "MethodHandle type differs from access mode type");
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+        assertEquals(info.getMethodType(), emt,
+                     "MethodHandleInfo method type differs from access mode type");
+
+        return mh.bindTo(vh);
+    }
+
+    private interface TriFunction<T, U, V, R> {
+        R apply(T t, U u, V v);
+    }
+
+    enum VarHandleToMethodHandle {
+        VAR_HANDLE_TO_METHOD_HANDLE(
+                "VarHandle.toMethodHandle",
+                VarHandleBaseTest::toMethodHandle),
+        METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
+                "Lookup.findVirtual",
+                VarHandleBaseTest::findVirtual),
+        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_ACCESS_MODE_TYPE(
+                "MethodHandles.varHandleInvoker(accessModeType)",
+                VarHandleBaseTest::varHandleInvokerWithAccessModeType),
+        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_SYMBOLIC_TYPE_DESCRIPTOR(
+                "MethodHandles.varHandleInvoker(symbolicTypeDescriptor)",
+                VarHandleBaseTest::varHandleInvokerWithSymbolicTypeDescriptor),
+        METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER_WITH_ACCESS_MODE_TYPE(
+                "MethodHandles.varHandleExactInvoker(accessModeType)",
+                VarHandleBaseTest::varHandleExactInvokerWithAccessModeType);
+
+        final String desc;
+        final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
+        final boolean exact;
+
+        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
+            this(desc, f, false);
+        }
+
+        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f,
+                                boolean exact) {
+            this.desc = desc;
+            this.f = f;
+            this.exact = exact;
+        }
+
+        MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) {
+            return f.apply(vh, am, mt);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class Handles {
+        static class AccessModeAndType {
+            final TestAccessMode tam;
+            final MethodType t;
+
+            public AccessModeAndType(TestAccessMode tam, MethodType t) {
+                this.tam = tam;
+                this.t = t;
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+
+                AccessModeAndType x = (AccessModeAndType) o;
+
+                if (tam != x.tam) return false;
+                if (t != null ? !t.equals(x.t) : x.t != null) return false;
+
+                return true;
+            }
+
+            @Override
+            public int hashCode() {
+                int result = tam != null ? tam.hashCode() : 0;
+                result = 31 * result + (t != null ? t.hashCode() : 0);
+                return result;
+            }
+        }
+
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+        final EnumMap<TestAccessMode, MethodType> amToType;
+        final Map<AccessModeAndType, MethodHandle> amToHandle;
+
+        Handles(VarHandle vh, VarHandleToMethodHandle f) throws Exception {
+            this.vh = vh;
+            this.f = f;
+            this.amToHandle = new HashMap<>();
+
+            amToType = new EnumMap<>(TestAccessMode.class);
+            for (TestAccessMode am : testAccessModes()) {
+                amToType.put(am, vh.accessModeType(am.toAccessMode()));
+            }
+        }
+
+        MethodHandle get(TestAccessMode am) {
+            return get(am, amToType.get(am));
+        }
+
+        MethodHandle get(TestAccessMode am, MethodType mt) {
+            AccessModeAndType amt = new AccessModeAndType(am, mt);
+            return amToHandle.computeIfAbsent(
+                    amt, k -> f.apply(vh, am, mt));
+        }
+    }
+
+    interface AccessTestAction<T> {
+        void action(T t) throws Throwable;
+    }
+
+    static abstract class AccessTestCase<T> {
+        final String desc;
+        final AccessTestAction<T> ata;
+        final boolean loop;
+
+        AccessTestCase(String desc, AccessTestAction<T> ata, boolean loop) {
+            this.desc = desc;
+            this.ata = ata;
+            this.loop = loop;
+        }
+
+        boolean requiresLoop() {
+            return loop;
+        }
+
+        abstract T get() throws Exception;
+
+        void testAccess(T t) throws Throwable {
+            ata.action(t);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class VarHandleAccessTestCase extends AccessTestCase<VarHandle> {
+        final VarHandle vh;
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata) {
+            this(desc, vh, ata, true);
+        }
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata, boolean loop) {
+            super("VarHandle -> " + desc, ata, loop);
+            this.vh = vh;
+        }
+
+        @Override
+        VarHandle get() {
+            return vh;
+        }
+    }
+
+    static class MethodHandleAccessTestCase extends AccessTestCase<Handles> {
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata) {
+            this(desc, vh, f, ata, true);
+        }
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata, boolean loop) {
+            super("VarHandle -> " + f.toString() + " -> " + desc, ata, loop);
+            this.vh = vh;
+            this.f = f;
+        }
+
+        @Override
+        Handles get() throws Exception {
+            return new Handles(vh, f);
+        }
+    }
+
+    static void testTypes(VarHandle vh) {
+        List<Class<?>> pts = vh.coordinateTypes();
+
+        for (TestAccessMode accessMode : testAccessModes()) {
+            MethodType amt = vh.accessModeType(accessMode.toAccessMode());
+
+            assertEquals(amt.parameterList().subList(0, pts.size()), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.get)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterList(), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.set)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), void.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), boolean.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.getAndSet, TestAccessType.getAndAdd)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v;
+
+    final boolean final_v = true;
+
+    boolean v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessBoolean.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(boolean[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), boolean.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "v", boolean.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessBoolean::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(recv, true);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(true);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, true);
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, false);
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, true);
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, false);
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(recv, true);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(true);
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(false);
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(true);
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(false);
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(true);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, true);
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "get boolean value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, false);
+                boolean x = (boolean) vh.getVolatile(array, i);
+                assertEquals(x, false, "setVolatile boolean value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, true);
+                boolean x = (boolean) vh.getAcquire(array, i);
+                assertEquals(x, true, "setRelease boolean value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, false);
+                boolean x = (boolean) vh.getOpaque(array, i);
+                assertEquals(x, false, "setOpaque boolean value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(array, i, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(array, i, true);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, true);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)1;
+
+    static byte static_v;
+
+    final byte final_v = (byte)1;
+
+    byte v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessByte.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(byte[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), byte.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "final_v", byte.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "v", byte.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_final_v", byte.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_v", byte.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessByte::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessByte::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessByte::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)1, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)1, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)1, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)1, "getOpaque byte value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(recv, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(recv, (byte)1);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)1, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)1, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)1, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)1, "getOpaque byte value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque((byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd((byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet((byte)1);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, (byte)1);
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, (byte)2);
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, (byte)1);
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, (byte)2);
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(recv, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(recv, (byte)1);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set((byte)1);
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile((byte)2);
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease((byte)1);
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque((byte)2);
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd((byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet((byte)1);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, (byte)1);
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)1, "get byte value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, (byte)2);
+                byte x = (byte) vh.getVolatile(array, i);
+                assertEquals(x, (byte)2, "setVolatile byte value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, (byte)1);
+                byte x = (byte) vh.getAcquire(array, i);
+                assertEquals(x, (byte)1, "setRelease byte value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, (byte)2);
+                byte x = (byte) vh.getOpaque(array, i);
+                assertEquals(x, (byte)2, "setOpaque byte value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(array, i, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(array, i, (byte)1);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, (byte)1);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessChar extends VarHandleBaseTest {
+    static final char static_final_v = 'a';
+
+    static char static_v;
+
+    final char final_v = 'a';
+
+    char v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessChar.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(char[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), char.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "final_v", char.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "v", char.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_final_v", char.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_v", char.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessChar::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessChar::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) {
+        // Plain
+        {
+            char x = (char) vh.get(recv);
+            assertEquals(x, 'a', "get char value");
+        }
+
+
+        // Volatile
+        {
+            char x = (char) vh.getVolatile(recv);
+            assertEquals(x, 'a', "getVolatile char value");
+        }
+
+        // Lazy
+        {
+            char x = (char) vh.getAcquire(recv);
+            assertEquals(x, 'a', "getRelease char value");
+        }
+
+        // Opaque
+        {
+            char x = (char) vh.getOpaque(recv);
+            assertEquals(x, 'a', "getOpaque char value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd(recv, 'a');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet(recv, 'a');
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            char x = (char) vh.get();
+            assertEquals(x, 'a', "get char value");
+        }
+
+
+        // Volatile
+        {
+            char x = (char) vh.getVolatile();
+            assertEquals(x, 'a', "getVolatile char value");
+        }
+
+        // Lazy
+        {
+            char x = (char) vh.getAcquire();
+            assertEquals(x, 'a', "getRelease char value");
+        }
+
+        // Opaque
+        {
+            char x = (char) vh.getOpaque();
+            assertEquals(x, 'a', "getOpaque char value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set('b');
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile('b');
+        });
+
+        checkUOE(() -> {
+            vh.setRelease('b');
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque('b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd('a');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet('a');
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 'a');
+            char x = (char) vh.get(recv);
+            assertEquals(x, 'a', "set char value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 'b');
+            char x = (char) vh.getVolatile(recv);
+            assertEquals(x, 'b', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 'a');
+            char x = (char) vh.getAcquire(recv);
+            assertEquals(x, 'a', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 'b');
+            char x = (char) vh.getOpaque(recv);
+            assertEquals(x, 'b', "setOpaque char value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd(recv, 'a');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet(recv, 'a');
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set('a');
+            char x = (char) vh.get();
+            assertEquals(x, 'a', "set char value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile('b');
+            char x = (char) vh.getVolatile();
+            assertEquals(x, 'b', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease('a');
+            char x = (char) vh.getAcquire();
+            assertEquals(x, 'a', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque('b');
+            char x = (char) vh.getOpaque();
+            assertEquals(x, 'b', "setOpaque char value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire('a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease('a', 'b');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd('a');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet('a');
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        char[] array = new char[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 'a');
+                char x = (char) vh.get(array, i);
+                assertEquals(x, 'a', "get char value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 'b');
+                char x = (char) vh.getVolatile(array, i);
+                assertEquals(x, 'b', "setVolatile char value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 'a');
+                char x = (char) vh.getAcquire(array, i);
+                assertEquals(x, 'a', "setRelease char value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 'b');
+                char x = (char) vh.getOpaque(array, i);
+                assertEquals(x, 'b', "setOpaque char value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        char[] array = new char[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd(array, i, 'a');
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet(array, i, 'a');
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 'a');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 'a');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 'a');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 'a');
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v;
+
+    final double final_v = 1.0d;
+
+    double v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessDouble.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(double[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), double.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessDouble.class, "final_v", double.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessDouble.class, "v", double.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "static_final_v", double.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "static_v", double.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessDouble::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessDouble::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessDouble::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessDouble::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessDouble::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessDouble recv, VarHandle vh) {
+        // Plain
+        {
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "get double value");
+        }
+
+
+        // Volatile
+        {
+            double x = (double) vh.getVolatile(recv);
+            assertEquals(x, 1.0d, "getVolatile double value");
+        }
+
+        // Lazy
+        {
+            double x = (double) vh.getAcquire(recv);
+            assertEquals(x, 1.0d, "getRelease double value");
+        }
+
+        // Opaque
+        {
+            double x = (double) vh.getOpaque(recv);
+            assertEquals(x, 1.0d, "getOpaque double value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(recv, 1.0d);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "get double value");
+        }
+
+
+        // Volatile
+        {
+            double x = (double) vh.getVolatile();
+            assertEquals(x, 1.0d, "getVolatile double value");
+        }
+
+        // Lazy
+        {
+            double x = (double) vh.getAcquire();
+            assertEquals(x, 1.0d, "getRelease double value");
+        }
+
+        // Opaque
+        {
+            double x = (double) vh.getOpaque();
+            assertEquals(x, 1.0d, "getOpaque double value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(1.0d);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1.0d);
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2.0d);
+            double x = (double) vh.getVolatile(recv);
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1.0d);
+            double x = (double) vh.getAcquire(recv);
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2.0d);
+            double x = (double) vh.getOpaque(recv);
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(recv, 1.0d);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1.0d);
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2.0d);
+            double x = (double) vh.getVolatile();
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1.0d);
+            double x = (double) vh.getAcquire();
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2.0d);
+            double x = (double) vh.getOpaque();
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(1.0d);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        double[] array = new double[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1.0d);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "get double value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2.0d);
+                double x = (double) vh.getVolatile(array, i);
+                assertEquals(x, 2.0d, "setVolatile double value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1.0d);
+                double x = (double) vh.getAcquire(array, i);
+                assertEquals(x, 1.0d, "setRelease double value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2.0d);
+                double x = (double) vh.getOpaque(array, i);
+                assertEquals(x, 2.0d, "setOpaque double value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        double[] array = new double[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeVolatile(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(array, i, 1.0d);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1.0d);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v;
+
+    final float final_v = 1.0f;
+
+    float v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessFloat.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(float[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), float.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessFloat.class, "final_v", float.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessFloat.class, "v", float.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "static_final_v", float.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "static_v", float.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessFloat::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessFloat::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessFloat::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessFloat::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessFloat::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessFloat recv, VarHandle vh) {
+        // Plain
+        {
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "get float value");
+        }
+
+
+        // Volatile
+        {
+            float x = (float) vh.getVolatile(recv);
+            assertEquals(x, 1.0f, "getVolatile float value");
+        }
+
+        // Lazy
+        {
+            float x = (float) vh.getAcquire(recv);
+            assertEquals(x, 1.0f, "getRelease float value");
+        }
+
+        // Opaque
+        {
+            float x = (float) vh.getOpaque(recv);
+            assertEquals(x, 1.0f, "getOpaque float value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeVolatile(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(recv, 1.0f);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "get float value");
+        }
+
+
+        // Volatile
+        {
+            float x = (float) vh.getVolatile();
+            assertEquals(x, 1.0f, "getVolatile float value");
+        }
+
+        // Lazy
+        {
+            float x = (float) vh.getAcquire();
+            assertEquals(x, 1.0f, "getRelease float value");
+        }
+
+        // Opaque
+        {
+            float x = (float) vh.getOpaque();
+            assertEquals(x, 1.0f, "getOpaque float value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeVolatile(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(1.0f);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1.0f);
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2.0f);
+            float x = (float) vh.getVolatile(recv);
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1.0f);
+            float x = (float) vh.getAcquire(recv);
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2.0f);
+            float x = (float) vh.getOpaque(recv);
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeVolatile(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(recv, 1.0f);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1.0f);
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2.0f);
+            float x = (float) vh.getVolatile();
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1.0f);
+            float x = (float) vh.getAcquire();
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2.0f);
+            float x = (float) vh.getOpaque();
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeVolatile(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(1.0f);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        float[] array = new float[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1.0f);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "get float value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2.0f);
+                float x = (float) vh.getVolatile(array, i);
+                assertEquals(x, 2.0f, "setVolatile float value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1.0f);
+                float x = (float) vh.getAcquire(array, i);
+                assertEquals(x, 1.0f, "setRelease float value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2.0f);
+                float x = (float) vh.getOpaque(array, i);
+                assertEquals(x, 2.0f, "setOpaque float value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        float[] array = new float[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeVolatile(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(array, i, 1.0f);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1.0f);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessInt extends VarHandleBaseTest {
+    static final int static_final_v = 1;
+
+    static int static_v;
+
+    final int final_v = 1;
+
+    int v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessInt.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(int[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), int.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessInt.class, "final_v", int.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessInt.class, "v", int.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "static_final_v", int.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "static_v", int.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessInt::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessInt::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessInt::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessInt::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessInt::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessInt recv, VarHandle vh) {
+        // Plain
+        {
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "get int value");
+        }
+
+
+        // Volatile
+        {
+            int x = (int) vh.getVolatile(recv);
+            assertEquals(x, 1, "getVolatile int value");
+        }
+
+        // Lazy
+        {
+            int x = (int) vh.getAcquire(recv);
+            assertEquals(x, 1, "getRelease int value");
+        }
+
+        // Opaque
+        {
+            int x = (int) vh.getOpaque(recv);
+            assertEquals(x, 1, "getOpaque int value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2);
+        });
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            int x = (int) vh.get();
+            assertEquals(x, 1, "get int value");
+        }
+
+
+        // Volatile
+        {
+            int x = (int) vh.getVolatile();
+            assertEquals(x, 1, "getVolatile int value");
+        }
+
+        // Lazy
+        {
+            int x = (int) vh.getAcquire();
+            assertEquals(x, 1, "getRelease int value");
+        }
+
+        // Opaque
+        {
+            int x = (int) vh.getOpaque();
+            assertEquals(x, 1, "getOpaque int value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2);
+        });
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1);
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "set int value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2);
+            int x = (int) vh.getVolatile(recv);
+            assertEquals(x, 2, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1);
+            int x = (int) vh.getAcquire(recv);
+            assertEquals(x, 1, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2);
+            int x = (int) vh.getOpaque(recv);
+            assertEquals(x, 2, "setOpaque int value");
+        }
+
+        vh.set(recv, 1);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 1, 2);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 1, 3);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeVolatile(recv, 2, 1);
+            assertEquals(r, 2, "success compareAndExchangeVolatile int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeVolatile(recv, 2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(recv, 1, 2);
+            assertEquals(r, 1, "success compareAndExchangeAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(recv, 1, 3);
+            assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(recv, 2, 1);
+            assertEquals(r, 2, "success compareAndExchangeRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(recv, 2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSet(recv, 1, 2);
+            assertEquals(r, true, "weakCompareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "weakCompareAndSet int value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 2, 1);
+            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1, 2);
+            assertEquals(r, true, "weakCompareAndSetRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 2, "weakCompareAndSetRelease int");
+        }
+
+        // Compare set and get
+        {
+            int o = (int) vh.getAndSet(recv, 1);
+            assertEquals(o, 2, "getAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "getAndSet int value");
+        }
+
+        vh.set(recv, 1);
+
+        // get and add, add and get
+        {
+            int o = (int) vh.getAndAdd(recv, 3);
+            assertEquals(o, 1, "getAndAdd int");
+            int c = (int) vh.addAndGet(recv, 3);
+            assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1);
+            int x = (int) vh.get();
+            assertEquals(x, 1, "set int value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2);
+            int x = (int) vh.getVolatile();
+            assertEquals(x, 2, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1);
+            int x = (int) vh.getAcquire();
+            assertEquals(x, 1, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2);
+            int x = (int) vh.getOpaque();
+            assertEquals(x, 2, "setOpaque int value");
+        }
+
+        vh.set(1);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(1, 2);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(1, 3);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeVolatile(2, 1);
+            assertEquals(r, 2, "success compareAndExchangeVolatile int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeVolatile(2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(1, 2);
+            assertEquals(r, 1, "success compareAndExchangeAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(1, 3);
+            assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(2, 1);
+            assertEquals(r, 2, "success compareAndExchangeRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSet(1, 2);
+            assertEquals(r, true, "weakCompareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "weakCompareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetAcquire(2, 1);
+            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2);
+            assertEquals(r, true, "weakCompareAndSetRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 2, "weakCompareAndSetRelease int");
+        }
+
+        // Compare set and get
+        {
+            int o = (int) vh.getAndSet( 1);
+            assertEquals(o, 2, "getAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "getAndSet int value");
+        }
+
+        vh.set(1);
+
+        // get and add, add and get
+        {
+            int o = (int) vh.getAndAdd( 3);
+            assertEquals(o, 1, "getAndAdd int");
+            int c = (int) vh.addAndGet(3);
+            assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        int[] array = new int[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "get int value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2);
+                int x = (int) vh.getVolatile(array, i);
+                assertEquals(x, 2, "setVolatile int value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1);
+                int x = (int) vh.getAcquire(array, i);
+                assertEquals(x, 1, "setRelease int value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2);
+                int x = (int) vh.getOpaque(array, i);
+                assertEquals(x, 2, "setOpaque int value");
+            }
+
+            vh.set(array, i, 1);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 1, 2);
+                assertEquals(r, true, "success compareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "success compareAndSet int value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 1, 3);
+                assertEquals(r, false, "failing compareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "failing compareAndSet int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeVolatile(array, i, 2, 1);
+                assertEquals(r, 2, "success compareAndExchangeVolatile int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeVolatile(array, i, 2, 3);
+                assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeAcquire(array, i, 1, 2);
+                assertEquals(r, 1, "success compareAndExchangeAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeAcquire(array, i, 1, 3);
+                assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeRelease(array, i, 2, 1);
+                assertEquals(r, 2, "success compareAndExchangeRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "success compareAndExchangeRelease int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeRelease(array, i, 2, 3);
+                assertEquals(r, 1, "failing compareAndExchangeRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSet(array, i, 1, 2);
+                assertEquals(r, true, "weakCompareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "weakCompareAndSet int value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetAcquire(array, i, 2, 1);
+                assertEquals(r, true, "weakCompareAndSetAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "weakCompareAndSetAcquire int");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetRelease(array, i, 1, 2);
+                assertEquals(r, true, "weakCompareAndSetRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 2, "weakCompareAndSetRelease int");
+            }
+
+            // Compare set and get
+            {
+                int o = (int) vh.getAndSet(array, i, 1);
+                assertEquals(o, 2, "getAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "getAndSet int value");
+            }
+
+            vh.set(array, i, 1);
+
+            // get and add, add and get
+            {
+                int o = (int) vh.getAndAdd(array, i, 3);
+                assertEquals(o, 1, "getAndAdd int");
+                int c = (int) vh.addAndGet(array, i, 3);
+                assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        int[] array = new int[10];
+
+        int i = 0;
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 1, 2);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeVolatile(array, ci, 2, 1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, 2, 1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, 2, 1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 1, 2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 1, 2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 1, 2);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, 1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, 3);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.addAndGet(array, ci, 3);
+            });
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessLong extends VarHandleBaseTest {
+    static final long static_final_v = 1L;
+
+    static long static_v;
+
+    final long final_v = 1L;
+
+    long v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessLong.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(long[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), long.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessLong.class, "final_v", long.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessLong.class, "v", long.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "static_final_v", long.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "static_v", long.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessLong::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessLong::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessLong::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessLong::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessLong::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessLong recv, VarHandle vh) {
+        // Plain
+        {
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "get long value");
+        }
+
+
+        // Volatile
+        {
+            long x = (long) vh.getVolatile(recv);
+            assertEquals(x, 1L, "getVolatile long value");
+        }
+
+        // Lazy
+        {
+            long x = (long) vh.getAcquire(recv);
+            assertEquals(x, 1L, "getRelease long value");
+        }
+
+        // Opaque
+        {
+            long x = (long) vh.getOpaque(recv);
+            assertEquals(x, 1L, "getOpaque long value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2L);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2L);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2L);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2L);
+        });
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "get long value");
+        }
+
+
+        // Volatile
+        {
+            long x = (long) vh.getVolatile();
+            assertEquals(x, 1L, "getVolatile long value");
+        }
+
+        // Lazy
+        {
+            long x = (long) vh.getAcquire();
+            assertEquals(x, 1L, "getRelease long value");
+        }
+
+        // Opaque
+        {
+            long x = (long) vh.getOpaque();
+            assertEquals(x, 1L, "getOpaque long value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2L);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2L);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2L);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2L);
+        });
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1L);
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "set long value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2L);
+            long x = (long) vh.getVolatile(recv);
+            assertEquals(x, 2L, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1L);
+            long x = (long) vh.getAcquire(recv);
+            assertEquals(x, 1L, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2L);
+            long x = (long) vh.getOpaque(recv);
+            assertEquals(x, 2L, "setOpaque long value");
+        }
+
+        vh.set(recv, 1L);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 1L, 2L);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 1L, 3L);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeVolatile(recv, 2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeVolatile(recv, 2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(recv, 1L, 2L);
+            assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(recv, 1L, 3L);
+            assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(recv, 2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(recv, 2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSet(recv, 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "weakCompareAndSet long value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetRelease(recv, 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSetRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 2L, "weakCompareAndSetRelease long");
+        }
+
+        // Compare set and get
+        {
+            long o = (long) vh.getAndSet(recv, 1L);
+            assertEquals(o, 2L, "getAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "getAndSet long value");
+        }
+
+        vh.set(recv, 1L);
+
+        // get and add, add and get
+        {
+            long o = (long) vh.getAndAdd(recv, 3L);
+            assertEquals(o, 1L, "getAndAdd long");
+            long c = (long) vh.addAndGet(recv, 3L);
+            assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1L);
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "set long value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2L);
+            long x = (long) vh.getVolatile();
+            assertEquals(x, 2L, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1L);
+            long x = (long) vh.getAcquire();
+            assertEquals(x, 1L, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2L);
+            long x = (long) vh.getOpaque();
+            assertEquals(x, 2L, "setOpaque long value");
+        }
+
+        vh.set(1L);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(1L, 2L);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(1L, 3L);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeVolatile(2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeVolatile(2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(1L, 2L);
+            assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(1L, 3L);
+            assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSet(1L, 2L);
+            assertEquals(r, true, "weakCompareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "weakCompareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetAcquire(2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSetRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 2L, "weakCompareAndSetRelease long");
+        }
+
+        // Compare set and get
+        {
+            long o = (long) vh.getAndSet( 1L);
+            assertEquals(o, 2L, "getAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "getAndSet long value");
+        }
+
+        vh.set(1L);
+
+        // get and add, add and get
+        {
+            long o = (long) vh.getAndAdd( 3L);
+            assertEquals(o, 1L, "getAndAdd long");
+            long c = (long) vh.addAndGet(3L);
+            assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        long[] array = new long[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1L);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "get long value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2L);
+                long x = (long) vh.getVolatile(array, i);
+                assertEquals(x, 2L, "setVolatile long value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1L);
+                long x = (long) vh.getAcquire(array, i);
+                assertEquals(x, 1L, "setRelease long value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2L);
+                long x = (long) vh.getOpaque(array, i);
+                assertEquals(x, 2L, "setOpaque long value");
+            }
+
+            vh.set(array, i, 1L);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 1L, 2L);
+                assertEquals(r, true, "success compareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "success compareAndSet long value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 1L, 3L);
+                assertEquals(r, false, "failing compareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "failing compareAndSet long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeVolatile(array, i, 2L, 1L);
+                assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeVolatile(array, i, 2L, 3L);
+                assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeAcquire(array, i, 1L, 2L);
+                assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeAcquire(array, i, 1L, 3L);
+                assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeRelease(array, i, 2L, 1L);
+                assertEquals(r, 2L, "success compareAndExchangeRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeRelease(array, i, 2L, 3L);
+                assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSet(array, i, 1L, 2L);
+                assertEquals(r, true, "weakCompareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "weakCompareAndSet long value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetAcquire(array, i, 2L, 1L);
+                assertEquals(r, true, "weakCompareAndSetAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetRelease(array, i, 1L, 2L);
+                assertEquals(r, true, "weakCompareAndSetRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 2L, "weakCompareAndSetRelease long");
+            }
+
+            // Compare set and get
+            {
+                long o = (long) vh.getAndSet(array, i, 1L);
+                assertEquals(o, 2L, "getAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "getAndSet long value");
+            }
+
+            vh.set(array, i, 1L);
+
+            // get and add, add and get
+            {
+                long o = (long) vh.getAndAdd(array, i, 3L);
+                assertEquals(o, 1L, "getAndAdd long");
+                long c = (long) vh.addAndGet(array, i, 3L);
+                assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        long[] array = new long[10];
+
+        int i = 0;
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1L);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 1L, 2L);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeVolatile(array, ci, 2L, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, 2L, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, 2L, 1L);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 1L, 2L);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 1L, 2L);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 1L, 2L);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, 1L);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, 3L);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.addAndGet(array, ci, 3L);
+            });
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)1;
+
+    static short static_v;
+
+    final short final_v = (short)1;
+
+    short v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessShort.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(short[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), short.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessShort.class, "final_v", short.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessShort.class, "v", short.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "static_final_v", short.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "static_v", short.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessShort::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessShort::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessShort::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessShort::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessShort::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessShort recv, VarHandle vh) {
+        // Plain
+        {
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)1, "get short value");
+        }
+
+
+        // Volatile
+        {
+            short x = (short) vh.getVolatile(recv);
+            assertEquals(x, (short)1, "getVolatile short value");
+        }
+
+        // Lazy
+        {
+            short x = (short) vh.getAcquire(recv);
+            assertEquals(x, (short)1, "getRelease short value");
+        }
+
+        // Opaque
+        {
+            short x = (short) vh.getOpaque(recv);
+            assertEquals(x, (short)1, "getOpaque short value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, (short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, (short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, (short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd(recv, (short)1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet(recv, (short)1);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            short x = (short) vh.get();
+            assertEquals(x, (short)1, "get short value");
+        }
+
+
+        // Volatile
+        {
+            short x = (short) vh.getVolatile();
+            assertEquals(x, (short)1, "getVolatile short value");
+        }
+
+        // Lazy
+        {
+            short x = (short) vh.getAcquire();
+            assertEquals(x, (short)1, "getRelease short value");
+        }
+
+        // Opaque
+        {
+            short x = (short) vh.getOpaque();
+            assertEquals(x, (short)1, "getOpaque short value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set((short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile((short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease((short)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque((short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd((short)1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet((short)1);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, (short)1);
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)1, "set short value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, (short)2);
+            short x = (short) vh.getVolatile(recv);
+            assertEquals(x, (short)2, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, (short)1);
+            short x = (short) vh.getAcquire(recv);
+            assertEquals(x, (short)1, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, (short)2);
+            short x = (short) vh.getOpaque(recv);
+            assertEquals(x, (short)2, "setOpaque short value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd(recv, (short)1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet(recv, (short)1);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set((short)1);
+            short x = (short) vh.get();
+            assertEquals(x, (short)1, "set short value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile((short)2);
+            short x = (short) vh.getVolatile();
+            assertEquals(x, (short)2, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease((short)1);
+            short x = (short) vh.getAcquire();
+            assertEquals(x, (short)1, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque((short)2);
+            short x = (short) vh.getOpaque();
+            assertEquals(x, (short)2, "setOpaque short value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd((short)1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet((short)1);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        short[] array = new short[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, (short)1);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)1, "get short value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, (short)2);
+                short x = (short) vh.getVolatile(array, i);
+                assertEquals(x, (short)2, "setVolatile short value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, (short)1);
+                short x = (short) vh.getAcquire(array, i);
+                assertEquals(x, (short)1, "setRelease short value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, (short)2);
+                short x = (short) vh.getOpaque(array, i);
+                assertEquals(x, (short)2, "setOpaque short value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        short[] array = new short[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd(array, i, (short)1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet(array, i, (short)1);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, (short)1);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, (short)1);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, (short)1);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, (short)1);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,804 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v;
+
+    final String final_v = "foo";
+
+    String v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessString.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(String[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), String.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessString.class, "final_v", String.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessString.class, "v", String.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "static_final_v", String.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "static_v", String.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessString::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessString::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessString::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessString::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessString::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessString::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessString::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessString recv, VarHandle vh) {
+        // Plain
+        {
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "get String value");
+        }
+
+
+        // Volatile
+        {
+            String x = (String) vh.getVolatile(recv);
+            assertEquals(x, "foo", "getVolatile String value");
+        }
+
+        // Lazy
+        {
+            String x = (String) vh.getAcquire(recv);
+            assertEquals(x, "foo", "getRelease String value");
+        }
+
+        // Opaque
+        {
+            String x = (String) vh.getOpaque(recv);
+            assertEquals(x, "foo", "getOpaque String value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, "bar");
+        });
+
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.addAndGet(recv, "foo");
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "get String value");
+        }
+
+
+        // Volatile
+        {
+            String x = (String) vh.getVolatile();
+            assertEquals(x, "foo", "getVolatile String value");
+        }
+
+        // Lazy
+        {
+            String x = (String) vh.getAcquire();
+            assertEquals(x, "foo", "getRelease String value");
+        }
+
+        // Opaque
+        {
+            String x = (String) vh.getOpaque();
+            assertEquals(x, "foo", "getOpaque String value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setRelease("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque("bar");
+        });
+
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.addAndGet("foo");
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, "foo");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, "bar");
+            String x = (String) vh.getVolatile(recv);
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, "foo");
+            String x = (String) vh.getAcquire(recv);
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, "bar");
+            String x = (String) vh.getOpaque(recv);
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        vh.set(recv, "foo");
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, "foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, "foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeVolatile(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeVolatile(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSet(recv, "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "weakCompareAndSet String value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetAcquire(recv, "bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetRelease(recv, "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSetRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        // Compare set and get
+        {
+            String o = (String) vh.getAndSet(recv, "foo");
+            assertEquals(o, "bar", "getAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "getAndSet String value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.addAndGet(recv, "foo");
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set("foo");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile("bar");
+            String x = (String) vh.getVolatile();
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease("foo");
+            String x = (String) vh.getAcquire();
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque("bar");
+            String x = (String) vh.getOpaque();
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        vh.set("foo");
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet("foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = vh.compareAndSet("foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeVolatile("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeVolatile("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire("foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire("foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSet("foo", "bar");
+            assertEquals(r, true, "weakCompareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "weakCompareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetAcquire("bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSetRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        // Compare set and get
+        {
+            String o = (String) vh.getAndSet( "foo");
+            assertEquals(o, "bar", "getAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "getAndSet String value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.addAndGet("foo");
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        String[] array = new String[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, "foo");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "get String value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, "bar");
+                String x = (String) vh.getVolatile(array, i);
+                assertEquals(x, "bar", "setVolatile String value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, "foo");
+                String x = (String) vh.getAcquire(array, i);
+                assertEquals(x, "foo", "setRelease String value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, "bar");
+                String x = (String) vh.getOpaque(array, i);
+                assertEquals(x, "bar", "setOpaque String value");
+            }
+
+            vh.set(array, i, "foo");
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, "foo", "bar");
+                assertEquals(r, true, "success compareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "success compareAndSet String value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, "foo", "baz");
+                assertEquals(r, false, "failing compareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "failing compareAndSet String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeVolatile(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeVolatile(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "bar");
+                assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "baz");
+                assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSet(array, i, "foo", "bar");
+                assertEquals(r, true, "weakCompareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "weakCompareAndSet String value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetAcquire(array, i, "bar", "foo");
+                assertEquals(r, true, "weakCompareAndSetAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetRelease(array, i, "foo", "bar");
+                assertEquals(r, true, "weakCompareAndSetRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetRelease String");
+            }
+
+            // Compare set and get
+            {
+                String o = (String) vh.getAndSet(array, i, "foo");
+                assertEquals(o, "bar", "getAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "getAndSet String value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        String[] array = new String[10];
+
+        int i = 0;
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.addAndGet(array, i, "foo");
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                String x = (String) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchangeVolatile(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchangeAcquire(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchangeRelease(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                String o = (String) vh.getAndSet(array, ci, "foo");
+            });
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsChar
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsChar
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Character.BYTES;
+
+    static final char VALUE_1 = (char)0x0102;
+
+    static final char VALUE_2 = (char)0x1112;
+
+    static final char VALUE_3 = (char)0x2122;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(char[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(char[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), char.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.addAndGet(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    char x = (char) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    char x = (char) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                char x = (char) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get char value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile char value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease char value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque char value");
+                }
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                char x = (char) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get char value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile char value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease char value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque char value");
+                }
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putChar(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                char x = (char) vh.get(array, i);
+                assertEquals(x, v, "get char value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile char value");
+                }
+
+                // Lazy
+                {
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease char value");
+                }
+
+                // Opaque
+                {
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque char value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,892 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsDouble
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsDouble
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Double.BYTES;
+
+    static final double VALUE_1 = 0x0102030405060708L;
+
+    static final double VALUE_2 = 0x1112131415161718L;
+
+    static final double VALUE_3 = 0x2122232425262728L;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(double[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(double[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), double.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.addAndGet(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                double o = (double) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    double x = (double) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    double x = (double) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get double value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile double value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease double value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque double value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
+                }
+
+                // Compare set and get
+                {
+                    double o = (double) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet double value");
+                }
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get double value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile double value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease double value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque double value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
+                }
+
+                // Compare set and get
+                {
+                    double o = (double) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet double value");
+                }
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putDouble(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            double v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                double x = (double) vh.get(array, i);
+                assertEquals(x, v, "get double value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile double value");
+                }
+
+                // Lazy
+                {
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease double value");
+                }
+
+                // Opaque
+                {
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque double value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,892 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsFloat
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsFloat
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Float.BYTES;
+
+    static final float VALUE_1 = 0x01020304;
+
+    static final float VALUE_2 = 0x11121314;
+
+    static final float VALUE_3 = 0x21222324;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(float[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(float[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), float.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.addAndGet(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                float o = (float) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    float x = (float) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    float x = (float) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get float value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile float value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease float value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque float value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
+                }
+
+                // Compare set and get
+                {
+                    float o = (float) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet float value");
+                }
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get float value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile float value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease float value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque float value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
+                }
+
+                // Compare set and get
+                {
+                    float o = (float) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet float value");
+                }
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putFloat(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            float v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                float x = (float) vh.get(array, i);
+                assertEquals(x, v, "get float value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile float value");
+                }
+
+                // Lazy
+                {
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease float value");
+                }
+
+                // Opaque
+                {
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque float value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,924 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsInt
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsInt
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Integer.BYTES;
+
+    static final int VALUE_1 = 0x01020304;
+
+    static final int VALUE_2 = 0x11121314;
+
+    static final int VALUE_3 = 0x21222324;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(int[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(int[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), int.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.addAndGet(array, ci, VALUE_1);
+            });
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.addAndGet(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    int x = (int) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.addAndGet(array, ci, VALUE_1);
+                });
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    int x = (int) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.addAndGet(array, ci, VALUE_1);
+                    });
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get int value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile int value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease int value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
+                }
+
+                // Compare set and get
+                {
+                    int o = (int) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    int o = (int) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd int");
+                    int c = (int) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd int value");
+                }
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get int value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile int value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease int value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
+                }
+
+                // Compare set and get
+                {
+                    int o = (int) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    int o = (int) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd int");
+                    int c = (int) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd int value");
+                }
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putInt(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            int v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                int x = (int) vh.get(array, i);
+                assertEquals(x, v, "get int value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile int value");
+                }
+
+                // Lazy
+                {
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease int value");
+                }
+
+                // Opaque
+                {
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque int value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,924 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsLong
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsLong
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Long.BYTES;
+
+    static final long VALUE_1 = 0x0102030405060708L;
+
+    static final long VALUE_2 = 0x1112131415161718L;
+
+    static final long VALUE_3 = 0x2122232425262728L;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(long[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(long[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), long.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.addAndGet(array, ci, VALUE_1);
+            });
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.addAndGet(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    long x = (long) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.addAndGet(array, ci, VALUE_1);
+                });
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    long x = (long) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.addAndGet(array, ci, VALUE_1);
+                    });
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get long value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile long value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease long value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
+                }
+
+                // Compare set and get
+                {
+                    long o = (long) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    long o = (long) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd long");
+                    long c = (long) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd long value");
+                }
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get long value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile long value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease long value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
+                }
+
+                // Compare set and get
+                {
+                    long o = (long) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    long o = (long) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd long");
+                    long c = (long) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd long value");
+                }
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putLong(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            long v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                long x = (long) vh.get(array, i);
+                assertEquals(x, v, "get long value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile long value");
+                }
+
+                // Lazy
+                {
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease long value");
+                }
+
+                // Opaque
+                {
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque long value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsShort
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsShort
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Short.BYTES;
+
+    static final short VALUE_1 = (short)0x0102;
+
+    static final short VALUE_2 = (short)0x1112;
+
+    static final short VALUE_3 = (short)0x2122;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(short[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(short[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), short.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.addAndGet(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.addAndGet(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    short x = (short) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    short x = (short) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get short value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile short value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease short value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque short value");
+                }
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get short value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile short value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease short value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque short value");
+                }
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putShort(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                short x = (short) vh.get(array, i);
+                assertEquals(x, v, "get short value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile short value");
+                }
+
+                // Lazy
+                {
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease short value");
+                }
+
+                // Opaque
+                {
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque short value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v;
+
+    final boolean final_v = true;
+
+    boolean v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, true);
+            boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, false);
+            boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, true);
+            boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, false);
+            boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, true);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, true);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(true);
+            boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(false);
+            boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(true);
+            boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(false);
+            boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(true);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(true);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, true);
+                boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, true, "get boolean value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, false);
+                boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, false, "setVolatile boolean value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, true);
+                boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, true, "setRelease boolean value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, false);
+                boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, false, "setOpaque boolean value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, true, false);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, true);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                boolean o = (boolean) hs.get(am).invokeExact(array, i, true);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    boolean x = (boolean) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, true);
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)1;
+
+    static byte static_v;
+
+    final byte final_v = (byte)1;
+
+    byte v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, (byte)1);
+            byte x = (byte) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, (byte)2);
+            byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, (byte)1);
+            byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, (byte)2);
+            byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, (byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact(recv, (byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact(recv, (byte)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact(recv, (byte)1);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact((byte)1);
+            byte x = (byte) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact((byte)2);
+            byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact((byte)1);
+            byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact((byte)2);
+            byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact((byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact((byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact((byte)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact((byte)1);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, (byte)1);
+                byte x = (byte) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, (byte)1, "get byte value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, (byte)2);
+                byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, (byte)2, "setVolatile byte value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, (byte)1);
+                byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, (byte)1, "setRelease byte value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, (byte)2);
+                byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, (byte)2, "setOpaque byte value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, (byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact(array, i, (byte)1, (byte)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                byte r = (byte) hs.get(am).invokeExact(array, i, (byte)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                byte o = (byte) hs.get(am).invokeExact(array, i, (byte)1);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    byte x = (byte) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, (byte)1);
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessChar extends VarHandleBaseTest {
+    static final char static_final_v = 'a';
+
+    static char static_v;
+
+    final char final_v = 'a';
+
+    char v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, 'a');
+            char x = (char) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 'a', "set char value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, 'b');
+            char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, 'b', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, 'a');
+            char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, 'a', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, 'b');
+            char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, 'b', "setOpaque char value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, 'a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact(recv, 'a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact(recv, 'a');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact(recv, 'a');
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact('a');
+            char x = (char) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 'a', "set char value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact('b');
+            char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, 'b', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact('a');
+            char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, 'a', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact('b');
+            char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, 'b', "setOpaque char value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact('a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact('a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact('a');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact('a');
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, 'a');
+                char x = (char) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 'a', "get char value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 'b');
+                char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, 'b', "setVolatile char value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, 'a');
+                char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, 'a', "setRelease char value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 'b');
+                char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, 'b', "setOpaque char value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, 'a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact(array, i, 'a', 'b');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                char r = (char) hs.get(am).invokeExact(array, i, 'a');
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                char o = (char) hs.get(am).invokeExact(array, i, 'a');
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    char x = (char) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 'a');
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v;
+
+    final double final_v = 1.0d;
+
+    double v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, 1.0d);
+            double x = (double) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2.0d);
+            double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, 1.0d);
+            double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2.0d);
+            double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, 1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(recv, 1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(recv, 1.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(recv, 1.0d);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(1.0d);
+            double x = (double) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(2.0d);
+            double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(1.0d);
+            double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(2.0d);
+            double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(1.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(1.0d);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, 1.0d);
+                double x = (double) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1.0d, "get double value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2.0d);
+                double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, 2.0d, "setVolatile double value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1.0d);
+                double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, 1.0d, "setRelease double value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2.0d);
+                double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, 2.0d, "setOpaque double value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, 1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(array, i, 1.0d, 2.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(array, i, 1.0d);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                double o = (double) hs.get(am).invokeExact(array, i, 1.0d);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    double x = (double) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1.0d);
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v;
+
+    final float final_v = 1.0f;
+
+    float v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, 1.0f);
+            float x = (float) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2.0f);
+            float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, 1.0f);
+            float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2.0f);
+            float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, 1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(recv, 1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(recv, 1.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(recv, 1.0f);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(1.0f);
+            float x = (float) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(2.0f);
+            float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(1.0f);
+            float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(2.0f);
+            float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(1.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(1.0f);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, 1.0f);
+                float x = (float) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1.0f, "get float value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2.0f);
+                float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, 2.0f, "setVolatile float value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1.0f);
+                float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, 1.0f, "setRelease float value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2.0f);
+                float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, 2.0f, "setOpaque float value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, 1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(array, i, 1.0f, 2.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(array, i, 1.0f);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                float o = (float) hs.get(am).invokeExact(array, i, 1.0f);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    float x = (float) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1.0f);
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
+    static final int static_final_v = 1;
+
+    static int static_v;
+
+    final int final_v = 1;
+
+    int v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, 1);
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "set int value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2);
+            int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, 2, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, 1);
+            int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, 1, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2);
+            int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, 2, "setOpaque int value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(recv, 1);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1, 2);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1, 3);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2, 1);
+            assertEquals(r, 2, "success compareAndExchangeVolatile int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1, 2);
+            assertEquals(r, 1, "success compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1, 3);
+            assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2, 1);
+            assertEquals(r, 2, "success compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, 1, 2);
+            assertEquals(r, true, "weakCompareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "weakCompareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, 2, 1);
+            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, 1, 2);
+            assertEquals(r, true, "weakCompareAndSetRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2, "weakCompareAndSetRelease int");
+        }
+
+        // Compare set and get
+        {
+            int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact(recv, 1);
+            assertEquals(o, 2, "getAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1, "getAndSet int value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(recv, 1);
+
+        // get and add, add and get
+        {
+            int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, 3);
+            assertEquals(o, 1, "getAndAdd int");
+            int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(recv, 3);
+            assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(1);
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "set int value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(2);
+            int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, 2, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(1);
+            int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, 1, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(2);
+            int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, 2, "setOpaque int value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(1);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1, 2);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1, 3);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2, 1);
+            assertEquals(r, 2, "success compareAndExchangeVolatile int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1, 2);
+            assertEquals(r, 1, "success compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1, 3);
+            assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2, 1);
+            assertEquals(r, 2, "success compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2, 3);
+            assertEquals(r, 1, "failing compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(1, 2);
+            assertEquals(r, true, "weakCompareAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "weakCompareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(2, 1);
+            assertEquals(r, true, "weakCompareAndSetAcquire int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( 1, 2);
+            assertEquals(r, true, "weakCompareAndSetRelease int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2, "weakCompareAndSetRelease int");
+        }
+
+        // Compare set and get
+        {
+            int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact( 1);
+            assertEquals(o, 2, "getAndSet int");
+            int x = (int) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1, "getAndSet int value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(1);
+
+        // get and add, add and get
+        {
+            int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact( 3);
+            assertEquals(o, 1, "getAndAdd int");
+            int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(3);
+            assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, 1);
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "get int value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2);
+                int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, 2, "setVolatile int value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1);
+                int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, 1, "setRelease int value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2);
+                int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, 2, "setOpaque int value");
+            }
+
+            hs.get(TestAccessMode.set).invokeExact(array, i, 1);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1, 2);
+                assertEquals(r, true, "success compareAndSet int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "success compareAndSet int value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1, 3);
+                assertEquals(r, false, "failing compareAndSet int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "failing compareAndSet int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2, 1);
+                assertEquals(r, 2, "success compareAndExchangeVolatile int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "success compareAndExchangeVolatile int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2, 3);
+                assertEquals(r, 1, "failing compareAndExchangeVolatile int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1, 2);
+                assertEquals(r, 1, "success compareAndExchangeAcquire int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "success compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1, 3);
+                assertEquals(r, 2, "failing compareAndExchangeAcquire int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2, 1);
+                assertEquals(r, 2, "success compareAndExchangeRelease int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "success compareAndExchangeRelease int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2, 3);
+                assertEquals(r, 1, "failing compareAndExchangeRelease int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "failing compareAndExchangeRelease int value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, 1, 2);
+                assertEquals(r, true, "weakCompareAndSet int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "weakCompareAndSet int value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, 2, 1);
+                assertEquals(r, true, "weakCompareAndSetAcquire int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "weakCompareAndSetAcquire int");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, 1, 2);
+                assertEquals(r, true, "weakCompareAndSetRelease int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2, "weakCompareAndSetRelease int");
+            }
+
+            // Compare set and get
+            {
+                int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, 1);
+                assertEquals(o, 2, "getAndSet int");
+                int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1, "getAndSet int value");
+            }
+
+            hs.get(TestAccessMode.set).invokeExact(array, i, 1);
+
+            // get and add, add and get
+            {
+                int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, 3);
+                assertEquals(o, 1, "getAndAdd int");
+                int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, 3);
+                assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        final int i = 0;
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    int x = (int) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1, 2);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+                checkIOOBE(am, () -> {
+                    int r = (int) hs.get(am).invokeExact(array, ci, 2, 1);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+                checkIOOBE(am, () -> {
+                    int o = (int) hs.get(am).invokeExact(array, ci, 1);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+                checkIOOBE(am, () -> {
+                    int o = (int) hs.get(am).invokeExact(array, ci, 3);
+                });
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
+    static final long static_final_v = 1L;
+
+    static long static_v;
+
+    final long final_v = 1L;
+
+    long v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, 1L);
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "set long value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2L);
+            long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, 2L, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, 1L);
+            long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, 1L, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2L);
+            long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, 2L, "setOpaque long value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(recv, 1L);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1L, 2L);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1L, 3L);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1L, 2L);
+            assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1L, 3L);
+            assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "weakCompareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, 2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSetRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 2L, "weakCompareAndSetRelease long");
+        }
+
+        // Compare set and get
+        {
+            long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact(recv, 1L);
+            assertEquals(o, 2L, "getAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, 1L, "getAndSet long value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(recv, 1L);
+
+        // get and add, add and get
+        {
+            long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, 3L);
+            assertEquals(o, 1L, "getAndAdd long");
+            long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(recv, 3L);
+            assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(1L);
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "set long value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(2L);
+            long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, 2L, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(1L);
+            long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, 1L, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(2L);
+            long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, 2L, "setOpaque long value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(1L);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1L, 2L);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1L, 3L);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1L, 2L);
+            assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1L, 3L);
+            assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2L, 1L);
+            assertEquals(r, 2L, "success compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2L, 3L);
+            assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(1L, 2L);
+            assertEquals(r, true, "weakCompareAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "weakCompareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetAcquire long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( 1L, 2L);
+            assertEquals(r, true, "weakCompareAndSetRelease long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 2L, "weakCompareAndSetRelease long");
+        }
+
+        // Compare set and get
+        {
+            long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact( 1L);
+            assertEquals(o, 2L, "getAndSet long");
+            long x = (long) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, 1L, "getAndSet long value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(1L);
+
+        // get and add, add and get
+        {
+            long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact( 3L);
+            assertEquals(o, 1L, "getAndAdd long");
+            long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(3L);
+            assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "get long value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2L);
+                long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, 2L, "setVolatile long value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1L);
+                long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, 1L, "setRelease long value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2L);
+                long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, 2L, "setOpaque long value");
+            }
+
+            hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1L, 2L);
+                assertEquals(r, true, "success compareAndSet long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "success compareAndSet long value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1L, 3L);
+                assertEquals(r, false, "failing compareAndSet long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "failing compareAndSet long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2L, 1L);
+                assertEquals(r, 2L, "success compareAndExchangeVolatile long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2L, 3L);
+                assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1L, 2L);
+                assertEquals(r, 1L, "success compareAndExchangeAcquire long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1L, 3L);
+                assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2L, 1L);
+                assertEquals(r, 2L, "success compareAndExchangeRelease long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "success compareAndExchangeRelease long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2L, 3L);
+                assertEquals(r, 1L, "failing compareAndExchangeRelease long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, 1L, 2L);
+                assertEquals(r, true, "weakCompareAndSet long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "weakCompareAndSet long value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, 2L, 1L);
+                assertEquals(r, true, "weakCompareAndSetAcquire long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "weakCompareAndSetAcquire long");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, 1L, 2L);
+                assertEquals(r, true, "weakCompareAndSetRelease long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 2L, "weakCompareAndSetRelease long");
+            }
+
+            // Compare set and get
+            {
+                long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, 1L);
+                assertEquals(o, 2L, "getAndSet long");
+                long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, 1L, "getAndSet long value");
+            }
+
+            hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
+
+            // get and add, add and get
+            {
+                long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, 3L);
+                assertEquals(o, 1L, "getAndAdd long");
+                long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, 3L);
+                assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        final int i = 0;
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    long x = (long) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1L);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1L, 2L);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+                checkIOOBE(am, () -> {
+                    long r = (long) hs.get(am).invokeExact(array, ci, 2L, 1L);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+                checkIOOBE(am, () -> {
+                    long o = (long) hs.get(am).invokeExact(array, ci, 1L);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+                checkIOOBE(am, () -> {
+                    long o = (long) hs.get(am).invokeExact(array, ci, 3L);
+                });
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)1;
+
+    static short static_v;
+
+    final short final_v = (short)1;
+
+    short v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, (short)1);
+            short x = (short) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, (short)1, "set short value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, (short)2);
+            short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, (short)2, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, (short)1);
+            short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, (short)1, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, (short)2);
+            short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, (short)2, "setOpaque short value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, (short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact(recv, (short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact(recv, (short)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact(recv, (short)1);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact((short)1);
+            short x = (short) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, (short)1, "set short value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact((short)2);
+            short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, (short)2, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact((short)1);
+            short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, (short)1, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact((short)2);
+            short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, (short)2, "setOpaque short value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact((short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact((short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact((short)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact((short)1);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, (short)1);
+                short x = (short) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, (short)1, "get short value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, (short)2);
+                short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, (short)2, "setVolatile short value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, (short)1);
+                short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, (short)1, "setRelease short value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, (short)2);
+                short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, (short)2, "setOpaque short value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        final int i = 0;
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, (short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact(array, i, (short)1, (short)2);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                short r = (short) hs.get(am).invokeExact(array, i, (short)1);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                short o = (short) hs.get(am).invokeExact(array, i, (short)1);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    short x = (short) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, (short)1);
+                });
+            }
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v;
+
+    final String final_v = "foo";
+
+    String v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, "foo");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, "bar");
+            String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, "foo");
+            String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, "bar");
+            String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact(recv, "foo");
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, "foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, "foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, "foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, "foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "weakCompareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, "bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSetRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        // Compare set and get
+        {
+            String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact(recv, "foo");
+            assertEquals(o, "bar", "getAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, "foo", "getAndSet String value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact(recv, "foo");
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact("foo");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact("bar");
+            String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact("foo");
+            String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact("bar");
+            String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        hs.get(TestAccessMode.set).invokeExact("foo");
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact("foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact("foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact("foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact("foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact("foo", "bar");
+            assertEquals(r, true, "weakCompareAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "weakCompareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact("bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetAcquire String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( "foo", "bar");
+            assertEquals(r, true, "weakCompareAndSetRelease String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        // Compare set and get
+        {
+            String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact( "foo");
+            assertEquals(o, "bar", "getAndSet String");
+            String x = (String) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, "foo", "getAndSet String value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact("foo");
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, "foo");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "get String value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, "bar");
+                String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, "bar", "setVolatile String value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, "foo");
+                String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, "foo", "setRelease String value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, "bar");
+                String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, "bar", "setOpaque String value");
+            }
+
+            hs.get(TestAccessMode.set).invokeExact(array, i, "foo");
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, true, "success compareAndSet String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "success compareAndSet String value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, "foo", "baz");
+                assertEquals(r, false, "failing compareAndSet String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "failing compareAndSet String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeVolatile String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, "foo", "baz");
+                assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeRelease String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, true, "weakCompareAndSet String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "weakCompareAndSet String value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, true, "weakCompareAndSetAcquire String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, true, "weakCompareAndSetRelease String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetRelease String");
+            }
+
+            // Compare set and get
+            {
+                String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, "foo");
+                assertEquals(o, "bar", "getAndSet String");
+                String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, "foo", "getAndSet String value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        final int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                String o = (String) hs.get(am).invokeExact(array, i, "foo");
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    String x = (String) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, "foo");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, "foo", "bar");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+                checkIOOBE(am, () -> {
+                    String r = (String) hs.get(am).invokeExact(array, ci, "bar", "foo");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+                checkIOOBE(am, () -> {
+                    String o = (String) hs.get(am).invokeExact(array, ci, "foo");
+                });
+            }
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeBoolean
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v = true;
+
+    final boolean final_v = true;
+
+    boolean v = true;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.get();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, true, Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, boolean.class)).
+                    invoke(null, true);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, boolean.class)).
+                    invoke(Void.class, true);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, boolean.class)).
+                    invoke(0, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
+                    invoke(recv, true, Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(true, Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, boolean.class, Class.class)).
+                    invoke(true, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        boolean[] array = new boolean[10];
+        Arrays.fill(array, true);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.get();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, true, Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+        Arrays.fill(array, true);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, boolean.class)).
+                    invoke(null, 0, true);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, boolean.class)).
+                    invoke(Void.class, 0, true);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, boolean.class)).
+                    invoke(0, 0, true);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, boolean[].class, Class.class, boolean.class)).
+                    invoke(array, Void.class, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
+                    invoke(array, 0, true, Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeByte
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)1;
+
+    static byte static_v = (byte)1;
+
+    final byte final_v = (byte)1;
+
+    byte v = (byte)1;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.get();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, (byte)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, (byte)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, (byte)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, (byte)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, (byte)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, (byte)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, (byte)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, (byte)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, byte.class)).
+                    invoke(null, (byte)1);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, byte.class)).
+                    invoke(Void.class, (byte)1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, byte.class)).
+                    invoke(0, (byte)1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
+                    invoke(recv, (byte)1, Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set((byte)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile((byte)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque((byte)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease((byte)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, byte.class, Class.class)).
+                    invoke((byte)1, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        byte[] array = new byte[10];
+        Arrays.fill(array, (byte)1);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.get();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, (byte)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, (byte)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, (byte)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, (byte)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, (byte)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, (byte)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, (byte)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, (byte)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, (byte)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, (byte)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, (byte)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, (byte)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, (byte)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, (byte)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+        Arrays.fill(array, (byte)1);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                byte x = (byte) hs.get(am, methodType(byte.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, byte.class)).
+                    invoke(null, 0, (byte)1);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, byte.class)).
+                    invoke(Void.class, 0, (byte)1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, byte.class)).
+                    invoke(0, 0, (byte)1);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, byte[].class, Class.class, byte.class)).
+                    invoke(array, Void.class, (byte)1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
+                    invoke(array, 0, (byte)1, Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeChar
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
+    static final char static_final_v = 'a';
+
+    static char static_v = 'a';
+
+    final char final_v = 'a';
+
+    char v = 'a';
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.get();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 'a');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 'a', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 'a');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 'a', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 'a');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 'a', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 'a');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 'a', Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, char.class)).
+                    invoke(null, 'a');
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, char.class)).
+                    invoke(Void.class, 'a');
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, char.class)).
+                    invoke(0, 'a');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
+                    invoke(recv, 'a', Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set('a', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile('a', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque('a', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease('a', Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, char.class, Class.class)).
+                    invoke('a', Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        char[] array = new char[10];
+        Arrays.fill(array, 'a');
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.get();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 'a');
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 'a');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 'a', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 'a');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 'a');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 'a', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 'a');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 'a');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 'a', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 'a');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 'a');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 'a');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 'a');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 'a', Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        char[] array = new char[10];
+        Arrays.fill(array, 'a');
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                char x = (char) hs.get(am, methodType(char.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, char[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, char.class)).
+                    invoke(null, 0, 'a');
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, char.class)).
+                    invoke(Void.class, 0, 'a');
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, char.class)).
+                    invoke(0, 0, 'a');
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, char[].class, Class.class, char.class)).
+                    invoke(array, Void.class, 'a');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
+                    invoke(array, 0, 'a', Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeDouble
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v = 1.0d;
+
+    final double final_v = 1.0d;
+
+    double v = 1.0d;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.get();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1.0d, Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, double.class)).
+                    invoke(null, 1.0d);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, double.class)).
+                    invoke(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, double.class)).
+                    invoke(0, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
+                    invoke(recv, 1.0d, Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1.0d, Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, double.class, Class.class)).
+                    invoke(1.0d, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        double[] array = new double[10];
+        Arrays.fill(array, 1.0d);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.get();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1.0d, Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        double[] array = new double[10];
+        Arrays.fill(array, 1.0d);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                double x = (double) hs.get(am, methodType(double.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, double[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, double.class)).
+                    invoke(null, 0, 1.0d);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, double.class)).
+                    invoke(Void.class, 0, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, double.class)).
+                    invoke(0, 0, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, double[].class, Class.class, double.class)).
+                    invoke(array, Void.class, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
+                    invoke(array, 0, 1.0d, Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeFloat
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v = 1.0f;
+
+    final float final_v = 1.0f;
+
+    float v = 1.0f;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.get();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1.0f, Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, float.class)).
+                    invoke(null, 1.0f);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, float.class)).
+                    invoke(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, float.class)).
+                    invoke(0, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
+                    invoke(recv, 1.0f, Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1.0f, Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, float.class, Class.class)).
+                    invoke(1.0f, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        float[] array = new float[10];
+        Arrays.fill(array, 1.0f);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.get();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1.0f, Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        float[] array = new float[10];
+        Arrays.fill(array, 1.0f);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                float x = (float) hs.get(am, methodType(float.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, float[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, float.class)).
+                    invoke(null, 0, 1.0f);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, float.class)).
+                    invoke(Void.class, 0, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, float.class)).
+                    invoke(0, 0, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, float[].class, Class.class, float.class)).
+                    invoke(array, Void.class, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
+                    invoke(array, 0, 1.0f, Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,2075 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeInt
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
+    static final int static_final_v = 1;
+
+    static int static_v = 1;
+
+    final int final_v = 1;
+
+    int v = 1;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.get();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeVolatile(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchangeVolatile(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeVolatile(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeVolatile(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchangeVolatile(0, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(recv, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(recv, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeVolatile(recv, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatileAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeAcquire(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchangeAcquire(0, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(recv, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeRelease(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchangeRelease(0, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(recv, 1, 1, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndSet(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndSet(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndSet(0, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(recv, 1, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndAdd(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndAdd(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndAdd(0, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(recv, 1, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.addAndGet(null, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.addAndGet(Void.class, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.addAndGet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.addAndGet(0, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(recv, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(recv, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.addAndGet(recv, 1, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, int.class)).
+                    invoke(null, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, int.class)).
+                    invoke(Void.class, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class)).
+                    invoke(0, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invoke(recv, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class)).
+                    invoke(null, 1, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class)).
+                    invoke(Void.class, 1, 1);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
+                    invoke(recv, Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invoke(recv, 1, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , int.class, int.class)).
+                    invoke(0, 1, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
+                    invoke(recv, 1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
+                    invoke(null, 1, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invoke(Void.class, 1, 1);
+            });
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
+                    invoke(recv, Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invoke(recv, 1, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class , int.class, int.class)).
+                    invoke(0, 1, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
+                    invoke(recv, 1, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
+                    invoke(recv, 1, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
+                    invoke(recv, 1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
+                    invoke(null, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invoke(Void.class, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invoke(0, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
+                    invoke(null, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invoke(Void.class, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invoke(0, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invoke(recv, 1, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(1, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(1, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(1, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(1, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeVolatile(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeVolatile(1, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeVolatile(1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(1, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(1, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(1, 1, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(1, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(1, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.addAndGet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.addAndGet(1, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, int.class, Class.class)).
+                    invoke(1, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
+                    invoke(Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, Class.class)).
+                    invoke(1, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, Class.class)).
+                    invoke(1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invoke(Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invoke(1, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class, int.class)).
+                    invoke(1, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
+                    invoke(1, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, Class.class)).
+                    invoke(1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
+                    invoke(1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invoke(1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invoke(1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
+                    invoke(1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invoke(1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invoke(1, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        int[] array = new int[10];
+        Arrays.fill(array, 1);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.get();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1, 1, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeVolatile(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchangeVolatile(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeVolatile(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeVolatile(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchangeVolatile(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchangeVolatile(array, Void.class, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(array, 0, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(array, 0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeVolatile(array, 0, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeAcquire(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchangeAcquire(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, Void.class, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, 1, 1, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeRelease(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchangeRelease(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchangeRelease(array, Void.class, 1, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 1, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(array, 0, 1, 1, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndSet(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndSet(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            int x = (int) vh.getAndSet(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndSet(array, Void.class, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(array, 0, 1, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndAdd(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndAdd(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndAdd(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndAdd(array, Void.class, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(array, 0, 1, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.addAndGet(null, 0, 1);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.addAndGet(Void.class, 0, 1);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.addAndGet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.addAndGet(0, 0, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.addAndGet(array, Void.class, 1);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(array, 0, 1);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(array, 0, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.addAndGet(array, 0, 1, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        int[] array = new int[10];
+        Arrays.fill(array, 1);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, int[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, int.class)).
+                    invoke(null, 0, 1);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, int.class)).
+                    invoke(Void.class, 0, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, int.class)).
+                    invoke(0, 0, 1);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, int[].class, Class.class, int.class)).
+                    invoke(array, Void.class, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
+                    invoke(array, 0, 1, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, int.class, int.class)).
+                    invoke(null, 0, 1, 1);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class, int.class)).
+                    invoke(Void.class, 0, 1, 1);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, Class.class, int.class)).
+                    invoke(array, 0, Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, int.class, int.class)).
+                    invoke(0, 0, 1, 1);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, Class.class, int.class, int.class)).
+                    invoke(array, Void.class, 1, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class, int.class)).
+                    invoke(null, 0, 1, 1);
+            });
+            checkCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class, int.class)).
+                    invoke(Void.class, 0, 1, 1);
+            });
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class, int.class)).
+                    invoke(array, 0, Void.class, 1);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class, int.class)).
+                    invoke(0, 0, 1, 1);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class, int.class)).
+                    invoke(array, Void.class, 1, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class, int.class)).
+                    invoke(array, 0, 1, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)).
+                    invoke(array, 0, 1, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
+                    invoke(null, 0, 1);
+            });
+            checkCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invoke(Void.class, 0, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
+                    invoke(0, 0, 1);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
+                    invoke(array, Void.class, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
+                    invoke(array, 0, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
+                    invoke(array, 0, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, Void.class, int.class, int.class)).
+                    invoke(null, 0, 1);
+            });
+            checkCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invoke(Void.class, 0, 1);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
+                    invoke(0, 0, 1);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
+                    invoke(array, Void.class, 1);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
+                    invoke(array, 0, 1);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
+                    invoke(array, 0, 1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invoke(array, 0, 1, Void.class);
+            });
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,2075 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeLong
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
+    static final long static_final_v = 1L;
+
+    static long static_v = 1L;
+
+    final long final_v = 1L;
+
+    long v = 1L;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.get();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1L, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1L, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1L, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1L, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeVolatile(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchangeVolatile(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeVolatile(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeVolatile(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchangeVolatile(0, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(recv, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(recv, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeVolatile(recv, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatileAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeAcquire(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchangeAcquire(0, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(recv, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeRelease(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchangeRelease(0, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(recv, 1L, 1L, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndSet(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndSet(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndSet(0, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(recv, 1L, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndAdd(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndAdd(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndAdd(0, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(recv, 1L, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.addAndGet(null, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.addAndGet(Void.class, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.addAndGet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.addAndGet(0, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(recv, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(recv, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.addAndGet(recv, 1L, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, long.class)).
+                    invoke(null, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, long.class)).
+                    invoke(Void.class, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, long.class)).
+                    invoke(0, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invoke(recv, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, long.class, long.class)).
+                    invoke(null, 1L, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class, long.class)).
+                    invoke(Void.class, 1L, 1L);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
+                    invoke(recv, Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invoke(recv, 1L, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , long.class, long.class)).
+                    invoke(0, 1L, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
+                    invoke(recv, 1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class, long.class)).
+                    invoke(null, 1L, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class, long.class)).
+                    invoke(Void.class, 1L, 1L);
+            });
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
+                    invoke(recv, Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invoke(recv, 1L, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class , long.class, long.class)).
+                    invoke(0, 1L, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
+                    invoke(recv, 1L, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
+                    invoke(recv, 1L, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
+                    invoke(recv, 1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)).
+                    invoke(null, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invoke(Void.class, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
+                    invoke(0, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, Void.class, long.class)).
+                    invoke(null, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invoke(Void.class, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
+                    invoke(0, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invoke(recv, 1L, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1L, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1L, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1L, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1L, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(1L, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(1L, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(1L, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(1L, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeVolatile(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeVolatile(1L, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeVolatile(1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(1L, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(1L, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(1L, 1L, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(1L, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(1L, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.addAndGet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.addAndGet(1L, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, long.class, Class.class)).
+                    invoke(1L, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class)).
+                    invoke(Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, Class.class)).
+                    invoke(1L, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class, Class.class)).
+                    invoke(1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invoke(Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invoke(1L, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class, long.class)).
+                    invoke(1L, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class)).
+                    invoke(1L, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, long.class, Class.class)).
+                    invoke(1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
+                    invoke(1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
+                    invoke(1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invoke(1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
+                    invoke(1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
+                    invoke(1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invoke(1L, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        long[] array = new long[10];
+        Arrays.fill(array, 1L);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.get();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1L, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1L, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1L, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1L, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeVolatile(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchangeVolatile(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeVolatile(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeVolatile(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchangeVolatile(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchangeVolatile(array, Void.class, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(array, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(array, 0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeVolatile(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeAcquire(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchangeAcquire(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, Void.class, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeRelease(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchangeRelease(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchangeRelease(array, Void.class, 1L, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(array, 0, 1L, 1L, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndSet(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndSet(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            long x = (long) vh.getAndSet(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndSet(array, Void.class, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(array, 0, 1L, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndAdd(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndAdd(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndAdd(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndAdd(array, Void.class, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(array, 0, 1L, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.addAndGet(null, 0, 1L);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.addAndGet(Void.class, 0, 1L);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.addAndGet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.addAndGet(0, 0, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.addAndGet(array, Void.class, 1L);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.addAndGet(array, 0, 1L);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.addAndGet(array, 0, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.addAndGet(array, 0, 1L, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        long[] array = new long[10];
+        Arrays.fill(array, 1L);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, long[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, long.class)).
+                    invoke(null, 0, 1L);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, long.class)).
+                    invoke(Void.class, 0, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, long.class)).
+                    invoke(0, 0, 1L);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, long[].class, Class.class, long.class)).
+                    invoke(array, Void.class, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
+                    invoke(array, 0, 1L, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, long.class, long.class)).
+                    invoke(null, 0, 1L, 1L);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, long.class, long.class)).
+                    invoke(Void.class, 0, 1L, 1L);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, Class.class, long.class)).
+                    invoke(array, 0, Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, long.class, long.class)).
+                    invoke(0, 0, 1L, 1L);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, Class.class, long.class, long.class)).
+                    invoke(array, Void.class, 1L, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class, long.class)).
+                    invoke(null, 0, 1L, 1L);
+            });
+            checkCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class, long.class)).
+                    invoke(Void.class, 0, 1L, 1L);
+            });
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class, long.class)).
+                    invoke(array, 0, Void.class, 1L);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class, long.class)).
+                    invoke(0, 0, 1L, 1L);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class, long.class)).
+                    invoke(array, Void.class, 1L, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class, long.class)).
+                    invoke(array, 0, 1L, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)).
+                    invoke(array, 0, 1L, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)).
+                    invoke(null, 0, 1L);
+            });
+            checkCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
+                    invoke(Void.class, 0, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
+                    invoke(0, 0, 1L);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
+                    invoke(array, Void.class, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
+                    invoke(array, 0, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
+                    invoke(array, 0, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, Void.class, int.class, long.class)).
+                    invoke(null, 0, 1L);
+            });
+            checkCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
+                    invoke(Void.class, 0, 1L);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
+                    invoke(0, 0, 1L);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
+                    invoke(array, Void.class, 1L);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
+                    invoke(array, 0, 1L);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
+                    invoke(array, 0, 1L);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invoke(array, 0, 1L, Void.class);
+            });
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeShort
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)1;
+
+    static short static_v = (short)1;
+
+    final short final_v = (short)1;
+
+    short v = (short)1;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.get();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, (short)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, (short)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, (short)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, (short)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, (short)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, (short)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, (short)1);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, (short)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, short.class)).
+                    invoke(null, (short)1);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, short.class)).
+                    invoke(Void.class, (short)1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, short.class)).
+                    invoke(0, (short)1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
+                    invoke(recv, (short)1, Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set((short)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile((short)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque((short)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease((short)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, short.class, Class.class)).
+                    invoke((short)1, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        short[] array = new short[10];
+        Arrays.fill(array, (short)1);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.get();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, (short)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, (short)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, (short)1, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, (short)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, (short)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, (short)1, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, (short)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, (short)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, (short)1, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, (short)1);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, (short)1);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, (short)1);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, (short)1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, (short)1, Void.class);
+        });
+
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        short[] array = new short[10];
+        Arrays.fill(array, (short)1);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                short x = (short) hs.get(am, methodType(short.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, short[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, short.class)).
+                    invoke(null, 0, (short)1);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, short.class)).
+                    invoke(Void.class, 0, (short)1);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, short.class)).
+                    invoke(0, 0, (short)1);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, short[].class, Class.class, short.class)).
+                    invoke(array, Void.class, (short)1);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
+                    invoke(array, 0, (short)1, Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1811 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodTypeString
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v = "foo";
+
+    final String final_v = "foo";
+
+    String v = "foo";
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodTypeString::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodTypeString::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.get(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.get();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, "foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, "foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, "foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, "foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeVolatile(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeVolatile(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeVolatile(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeVolatile(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchangeVolatile(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeVolatile(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeVolatileAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeAcquire(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchangeAcquire(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeRelease(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchangeRelease(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease(recv, "foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAndSet(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.getAndSet(0, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet(recv, "foo", Void.class);
+        });
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, String.class)).
+                    invoke(null, "foo");
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, String.class)).
+                    invoke(Void.class, "foo");
+            });
+            checkCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, String.class)).
+                    invoke(0, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invoke(recv, "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, String.class, String.class)).
+                    invoke(null, "foo", "foo");
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class, String.class)).
+                    invoke(Void.class, "foo", "foo");
+            });
+            checkCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
+                    invoke(recv, Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invoke(recv, "foo", Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , String.class, String.class)).
+                    invoke(0, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
+                    invoke(recv, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, Void.class, String.class, String.class)).
+                    invoke(null, "foo", "foo");
+            });
+            checkCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class, String.class)).
+                    invoke(Void.class, "foo", "foo");
+            });
+            checkCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
+                    invoke(recv, Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invoke(recv, "foo", Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class , String.class, String.class)).
+                    invoke(0, "foo", "foo");
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
+                    invoke(recv, "foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
+                    invoke(recv, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
+                    invoke(recv, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, Void.class, String.class)).
+                    invoke(null, "foo");
+            });
+            checkCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
+                    invoke(Void.class, "foo");
+            });
+            checkCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, String.class)).
+                    invoke(0, "foo");
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invoke(recv, "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invoke(recv, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invoke(recv, "foo", Void.class);
+            });
+        }
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set("foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile("foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque("foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease("foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeVolatile(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeVolatile("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeVolatile("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease("foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet("foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet("foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet("foo", Void.class);
+        });
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            checkCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, String.class, Class.class)).
+                    invoke("foo", Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class)).
+                    invoke(Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, Class.class)).
+                    invoke("foo", Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class, Class.class)).
+                    invoke("foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
+                    invoke(Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
+                    invoke("foo", Void.class);
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String.class, String.class)).
+                    invoke("foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class)).
+                    invoke("foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String.class, String.class, Class.class)).
+                    invoke("foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String.class)).
+                    invoke("foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class)).
+                    invoke("foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
+                    invoke("foo", Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        String[] array = new String[10];
+        Arrays.fill(array, "foo");
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.get();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, "foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, "foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, "foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, "foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeVolatile(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchangeVolatile(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeVolatile(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeVolatile(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchangeVolatile(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchangeVolatile(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeVolatile(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeVolatile(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeAcquire(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchangeAcquire(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeRelease(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchangeRelease(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchangeRelease(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAndSet(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAndSet(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            String x = (String) vh.getAndSet(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAndSet(array, Void.class, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet(array, 0, "foo", Void.class);
+        });
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        String[] array = new String[10];
+        Arrays.fill(array, "foo");
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, String[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, String.class)).
+                    invoke(null, 0, "foo");
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, String.class)).
+                    invoke(Void.class, 0, "foo");
+            });
+            checkCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, String.class)).
+                    invoke(0, 0, "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, String[].class, Class.class, String.class)).
+                    invoke(array, Void.class, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
+                    invoke(array, 0, "foo", Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, String.class, String.class)).
+                    invoke(null, 0, "foo", "foo");
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, String.class, String.class)).
+                    invoke(Void.class, 0, "foo", "foo");
+            });
+            checkCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, Class.class, String.class)).
+                    invoke(array, 0, Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, Class.class)).
+                    invoke(array, 0, "foo", Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, String.class, String.class)).
+                    invoke(0, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, Class.class, String.class, String.class)).
+                    invoke(array, Void.class, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class, Class.class)).
+                    invoke(array, 0, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class, String.class)).
+                    invoke(null, 0, "foo", "foo");
+            });
+            checkCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class, String.class)).
+                    invoke(Void.class, 0, "foo", "foo");
+            });
+            checkCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class, String.class)).
+                    invoke(array, 0, Void.class, "foo");
+            });
+            checkCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
+                    invoke(array, 0, "foo", Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class, String.class)).
+                    invoke(0, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class, String.class)).
+                    invoke(array, Void.class, "foo", "foo");
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class, String.class)).
+                    invoke(array, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)).
+                    invoke(array, 0, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class, Class.class)).
+                    invoke(array, 0, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                String x = (String) hs.get(am, methodType(String.class, Void.class, int.class, String.class)).
+                    invoke(null, 0, "foo");
+            });
+            checkCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class)).
+                    invoke(Void.class, 0, "foo");
+            });
+            checkCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class)).
+                    invoke(0, 0, "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class)).
+                    invoke(array, Void.class, "foo");
+            });
+            // Incorrect return type
+            checkCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class)).
+                    invoke(array, 0, "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class)).
+                    invoke(array, 0, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
+                    invoke(array, 0, "foo", Void.class);
+            });
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/VarHandleTestReflection.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng VarHandleTestReflection
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+
+public class VarHandleTestReflection extends VarHandleBaseTest {
+    String string;
+
+    @DataProvider
+    public static Object[][] accessModesProvider() {
+        return Stream.of(VarHandle.AccessMode.values()).
+                map(am -> new Object[]{am}).
+                toArray(Object[][]::new);
+    }
+
+    static VarHandle handle() throws Exception {
+        return MethodHandles.lookup().
+                findVarHandle(VarHandleTestReflection.class, "string", String.class);
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void methodInvocation(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a Method
+
+        Method vhm = VarHandle.class.getMethod(accessMode.name(), Object[].class);
+        vhm.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = UnsupportedOperationException.class)
+    public void methodHandleInvoke(VarHandle.AccessMode accessMode) throws Throwable {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a MethodHandle
+
+        MethodHandle mh = MethodHandles.lookup().unreflect(
+                VarHandle.class.getMethod(accessMode.name(), Object[].class));
+        // Use invoke to avoid WrongMethodTypeException for
+        // non-signature-polymorphic return types
+        Object o = (Object) mh.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void methodInvocationFromMethodInfo(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a Method obtained from cracking
+        // a MethodHandle
+
+        MethodHandle mh = MethodHandles.lookup().unreflect(
+                VarHandle.class.getMethod(accessMode.name(), Object[].class));
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+        Method im = info.reflectAs(Method.class, MethodHandles.lookup());
+        im.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void reflectAsFromVarHandleInvoker(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                accessMode, v.accessModeType(accessMode));
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+
+        info.reflectAs(Method.class, MethodHandles.lookup());
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void reflectAsFromFindVirtual(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        MethodHandle mh = MethodHandles.publicLookup().findVirtual(
+                VarHandle.class, accessMode.name(), v.accessModeType(accessMode));
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+
+        info.reflectAs(Method.class, MethodHandles.lookup());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1026 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccess$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccess$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccess$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+#if[CAS]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+#else[CAS]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+#end[CAS]
+
+#if[AtomicAdd]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+#else[AtomicAdd]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+#end[AtomicAdd]
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccess$Type$.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList($type$[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), $type$.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccess$Type$.class, "final_v", $type$.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccess$Type$.class, "v", $type$.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "static_final_v", $type$.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "static_v", $type$.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccess$Type$::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccess$Type$::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccess$Type$::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccess$Type$::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccess$Type$::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccess$Type$::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccess$Type$::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        // Plain
+        {
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "get $type$ value");
+        }
+
+
+        // Volatile
+        {
+            $type$ x = ($type$) vh.getVolatile(recv);
+            assertEquals(x, $value1$, "getVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            $type$ x = ($type$) vh.getAcquire(recv);
+            assertEquals(x, $value1$, "getRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            $type$ x = ($type$) vh.getOpaque(recv);
+            assertEquals(x, $value1$, "getOpaque $type$ value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, $value2$);
+        });
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet(recv, $value1$);
+        });
+#end[AtomicAdd]
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "get $type$ value");
+        }
+
+
+        // Volatile
+        {
+            $type$ x = ($type$) vh.getVolatile();
+            assertEquals(x, $value1$, "getVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            $type$ x = ($type$) vh.getAcquire();
+            assertEquals(x, $value1$, "getRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            $type$ x = ($type$) vh.getOpaque();
+            assertEquals(x, $value1$, "getOpaque $type$ value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque($value2$);
+        });
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet($value1$);
+        });
+#end[AtomicAdd]
+    }
+
+
+    static void testInstanceField(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, $value1$);
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, $value2$);
+            $type$ x = ($type$) vh.getVolatile(recv);
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, $value1$);
+            $type$ x = ($type$) vh.getAcquire(recv);
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, $value2$);
+            $type$ x = ($type$) vh.getOpaque(recv);
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        vh.set(recv, $value1$);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, $value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        // Compare set and get
+        {
+            $type$ o = ($type$) vh.getAndSet(recv, $value1$);
+            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "getAndSet $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        vh.set(recv, $value1$);
+
+        // get and add, add and get
+        {
+            $type$ o = ($type$) vh.getAndAdd(recv, $value3$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ c = ($type$) vh.addAndGet(recv, $value3$);
+            assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+        }
+#end[AtomicAdd]
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet(recv, $value1$);
+        });
+#end[AtomicAdd]
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set($value1$);
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile($value2$);
+            $type$ x = ($type$) vh.getVolatile();
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease($value1$);
+            $type$ x = ($type$) vh.getAcquire();
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque($value2$);
+            $type$ x = ($type$) vh.getOpaque();
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        vh.set($value1$);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = vh.compareAndSet($value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSet($value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetAcquire($value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean r = (boolean) vh.weakCompareAndSetRelease( $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        // Compare set and get
+        {
+            $type$ o = ($type$) vh.getAndSet( $value1$);
+            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "getAndSet $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        vh.set($value1$);
+
+        // get and add, add and get
+        {
+            $type$ o = ($type$) vh.getAndAdd( $value3$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ c = ($type$) vh.addAndGet($value3$);
+            assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+        }
+#end[AtomicAdd]
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet($value1$);
+        });
+#end[AtomicAdd]
+    }
+
+
+    static void testArray(VarHandle vh) {
+        $type$[] array = new $type$[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, $value1$);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "get $type$ value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, $value2$);
+                $type$ x = ($type$) vh.getVolatile(array, i);
+                assertEquals(x, $value2$, "setVolatile $type$ value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, $value1$);
+                $type$ x = ($type$) vh.getAcquire(array, i);
+                assertEquals(x, $value1$, "setRelease $type$ value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, $value2$);
+                $type$ x = ($type$) vh.getOpaque(array, i);
+                assertEquals(x, $value2$, "setOpaque $type$ value");
+            }
+
+#if[CAS]
+            vh.set(array, i, $value1$);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, $value1$, $value2$);
+                assertEquals(r, true, "success compareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "success compareAndSet $type$ value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, $value1$, $value3$);
+                assertEquals(r, false, "failing compareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value2$);
+                assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value3$);
+                assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$);
+                assertEquals(r, true, "weakCompareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$);
+                assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+            }
+
+            {
+                boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
+                assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+            }
+
+            // Compare set and get
+            {
+                $type$ o = ($type$) vh.getAndSet(array, i, $value1$);
+                assertEquals(o, $value2$, "getAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "getAndSet $type$ value");
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            vh.set(array, i, $value1$);
+
+            // get and add, add and get
+            {
+                $type$ o = ($type$) vh.getAndAdd(array, i, $value3$);
+                assertEquals(o, $value1$, "getAndAdd $type$");
+                $type$ c = ($type$) vh.addAndGet(array, i, $value3$);
+                assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+            }
+#end[AtomicAdd]
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        $type$[] array = new $type$[10];
+
+        int i = 0;
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet(array, i, $value1$);
+        });
+#end[AtomicAdd]
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, $value1$);
+            });
+
+#if[CAS]
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, $value1$);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, $value3$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.addAndGet(array, ci, $value3$);
+            });
+#end[AtomicAdd]
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAs$Type$
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAs$Type$
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
+    static final int SIZE = $BoxType$.BYTES;
+
+    static final $type$ VALUE_1 = $value1$;
+
+    static final $type$ VALUE_2 = $value2$;
+
+    static final $type$ VALUE_3 = $value3$;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle($type$[].class,
+                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle($type$[].class,
+                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+#if[CAS]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+#else[CAS]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+#end[CAS]
+
+#if[AtomicAdd]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+#else[AtomicAdd]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+#end[AtomicAdd]
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), $type$.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+        });
+#end[AtomicAdd]
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+#if[CAS]
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+#else[CAS]
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+            });
+#else[AtomicAdd]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+        }
+        else {
+#if[!CAS]
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+#end[CAS]
+#if[!AtomicAdd]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+#if[CAS]
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+#if[CAS]
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                });
+#end[CAS]
+
+#if[AtomicAdd]
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+                });
+#end[AtomicAdd]
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+#if[CAS]
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                });
+#end[CAS]
+
+#if[AtomicAdd]
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+                });
+#end[AtomicAdd]
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+#if[CAS]
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                    });
+#end[CAS]
+
+#if[AtomicAdd]
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
+                    });
+#end[AtomicAdd]
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get $type$ value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque $type$ value");
+                }
+#if[CAS]
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
+                }
+
+                // Compare set and get
+                {
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet $type$ value");
+                }
+#end[CAS]
+
+#if[AtomicAdd]
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd $type$");
+                    $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value");
+                }
+#end[AtomicAdd]
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get $type$ value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque $type$ value");
+                }
+#if[CAS]
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
+                }
+
+                {
+                    boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
+                }
+
+                // Compare set and get
+                {
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
+                    assertEquals(o, VALUE_2, "getAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "getAndSet $type$ value");
+                }
+#end[CAS]
+
+#if[AtomicAdd]
+                vh.set(array, i, VALUE_1);
+
+                // get and add, add and get
+                {
+                    $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3);
+                    assertEquals(o, VALUE_1, "getAndAdd $type$");
+                    $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3);
+                    assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value");
+                }
+#end[AtomicAdd]
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.put$Type$(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            $type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, v, "get $type$ value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque $type$ value");
+                }
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccess$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccess$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccess$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccess$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccess$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact(recv, $value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact(recv, $value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact(recv, $value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, $value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, $value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        // Compare set and get
+        {
+            $type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact(recv, $value1$);
+            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
+            assertEquals(x, $value1$, "getAndSet $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
+
+        // get and add, add and get
+        {
+            $type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, $value3$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact(recv, $value3$);
+            assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+        }
+#end[AtomicAdd]
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
+            });
+        }
+#end[AtomicAdd]
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.set).invokeExact($value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.setVolatile).invokeExact($value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact();
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.setRelease).invokeExact($value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact();
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.setOpaque).invokeExact($value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact();
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        hs.get(TestAccessMode.set).invokeExact($value1$);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact($value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact($value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact($value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact($value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact($value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact($value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( $value1$, $value2$);
+            assertEquals(r, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        // Compare set and get
+        {
+            $type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact( $value1$);
+            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
+            assertEquals(x, $value1$, "getAndSet $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        hs.get(TestAccessMode.set).invokeExact($value1$);
+
+        // get and add, add and get
+        {
+            $type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact( $value3$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact($value3$);
+            assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+        }
+#end[AtomicAdd]
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact($value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$);
+            });
+        }
+#end[AtomicAdd]
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "get $type$ value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.setVolatile).invokeExact(array, i, $value2$);
+                $type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
+                assertEquals(x, $value2$, "setVolatile $type$ value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.setRelease).invokeExact(array, i, $value1$);
+                $type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
+                assertEquals(x, $value1$, "setRelease $type$ value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.setOpaque).invokeExact(array, i, $value2$);
+                $type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
+                assertEquals(x, $value2$, "setOpaque $type$ value");
+            }
+
+#if[CAS]
+            hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, true, "success compareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "success compareAndSet $type$ value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, $value1$, $value3$);
+                assertEquals(r, false, "failing compareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, $value1$, $value3$);
+                assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, true, "weakCompareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, true, "weakCompareAndSetAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, true, "weakCompareAndSetRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+            }
+
+            // Compare set and get
+            {
+                $type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, $value1$);
+                assertEquals(o, $value2$, "getAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
+                assertEquals(x, $value1$, "getAndSet $type$ value");
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
+
+            // get and add, add and get
+            {
+                $type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, $value3$);
+                assertEquals(o, $value1$, "getAndAdd $type$");
+                $type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, $value3$);
+                assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
+            }
+#end[AtomicAdd]
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        final int i = 0;
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkUOE(am, () -> {
+                $type$ o = ($type$) hs.get(am).invokeExact(array, i, $value1$);
+            });
+        }
+#end[AtomicAdd]
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+                checkIOOBE(am, () -> {
+                    $type$ x = ($type$) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, $value1$);
+                });
+            }
+
+#if[CAS]
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, $value1$, $value2$);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+                checkIOOBE(am, () -> {
+                    $type$ r = ($type$) hs.get(am).invokeExact(array, ci, $value2$, $value1$);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+                checkIOOBE(am, () -> {
+                    $type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value1$);
+                });
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+                checkIOOBE(am, () -> {
+                    $type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value3$);
+                });
+            }
+#end[AtomicAdd]
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,2099 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng/othervm VarHandleTestMethodType$Type$
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodType$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v = $value1$;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v = $value1$;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodType$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodType$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodType$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodType$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field wrong method type",
+                                              vhStaticField, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array wrong method type",
+                                              vhArray, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
+                                              false));
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
+                                                     vhStaticField, f, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array wrong method type",
+                                                     vhArray, f, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodType$Type$ recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.get(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.get();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, $value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, $value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, $value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, $value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeVolatile(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatileAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeRelease(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndSet(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndSet(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet(recv, $value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndAdd(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndAdd(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd(recv, $value1$, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.addAndGet(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.addAndGet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.addAndGet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.addAndGet(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.addAndGet(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.addAndGet(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.addAndGet(recv, $value1$, Void.class);
+        });
+#end[AtomicAdd]
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodType$Type$ recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class)).
+                    invoke(null);
+            });
+            checkCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invoke(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class)).
+                    invoke(0);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)).
+                    invoke(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class)).
+                    invoke(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, Void.class, $type$.class)).
+                    invoke(null, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, $type$.class)).
+                    invoke(Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, $type$.class)).
+                    invoke(0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invoke(recv, $value1$, Void.class);
+            });
+        }
+
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, $type$.class, $type$.class)).
+                    invoke(null, $value1$, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class, $type$.class)).
+                    invoke(Void.class, $value1$, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
+                    invoke(recv, Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invoke(recv, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , $type$.class, $type$.class)).
+                    invoke(0, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
+                    invoke(recv, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class, $type$.class)).
+                    invoke(null, $value1$, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class, $type$.class)).
+                    invoke(Void.class, $value1$, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
+                    invoke(recv, Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invoke(recv, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class , $type$.class, $type$.class)).
+                    invoke(0, $value1$, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
+                    invoke(recv, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
+                    invoke(recv, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
+                    invoke(recv, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)).
+                    invoke(null, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invoke(Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
+                    invoke(0, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, $type$.class)).
+                    invoke(null, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invoke(Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invoke(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
+                    invoke(0, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invoke(recv, $value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set($value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile($value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque($value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease($value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeVolatile($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeVolatile($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease($value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet($value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd($value1$, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.addAndGet(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.addAndGet($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.addAndGet($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.addAndGet($value1$, Void.class);
+        });
+#end[AtomicAdd]
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class)).
+                    invoke();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType(Class.class)).
+                    invoke(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, $type$.class, Class.class)).
+                    invoke($value1$, Void.class);
+            });
+        }
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class)).
+                    invoke(Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, Class.class)).
+                    invoke($value1$, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, $type$.class, Class.class)).
+                    invoke($value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invoke(Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invoke($value1$, Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class, $type$.class)).
+                    invoke($value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class, $type$.class)).
+                    invoke($value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, $type$.class, Class.class)).
+                    invoke($value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
+                    invoke($value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
+                    invoke($value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invoke($value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invoke(Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
+                    invoke($value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
+                    invoke($value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invoke($value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        $type$[] array = new $type$[10];
+        Arrays.fill(array, $value1$);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.get();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, $value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeVolatile(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeVolatile(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeVolatile(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeRelease(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndSet(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            $type$ x = ($type$) vh.getAndSet(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndSet(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet(array, 0, $value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndAdd(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndAdd(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndAdd(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd(array, 0, $value1$, Void.class);
+        });
+
+
+        // AddAndGet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.addAndGet(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.addAndGet(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.addAndGet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.addAndGet(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.addAndGet(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.addAndGet(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.addAndGet(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.addAndGet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.addAndGet(array, 0, $value1$, Void.class);
+        });
+#end[AtomicAdd]
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+        Arrays.fill(array, $value1$);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class)).
+                    invoke(null, 0);
+            });
+            checkCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class)).
+                    invoke(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class)).
+                    invoke(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class)).
+                    invoke(array, Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class)).
+                    invoke(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class)).
+                    invoke(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, Void.class, int.class, $type$.class)).
+                    invoke(null, 0, $value1$);
+            });
+            checkCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, $type$.class)).
+                    invoke(Void.class, 0, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, $type$.class)).
+                    invoke(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, $type$[].class, Class.class, $type$.class)).
+                    invoke(array, Void.class, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
+                    invoke(array, 0, $value1$, Void.class);
+            });
+        }
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class, $type$.class, $type$.class)).
+                    invoke(null, 0, $value1$, $value1$);
+            });
+            checkCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, $type$.class, $type$.class)).
+                    invoke(Void.class, 0, $value1$, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, Class.class, $type$.class)).
+                    invoke(array, 0, Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, $type$.class, $type$.class)).
+                    invoke(0, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, Class.class, $type$.class, $type$.class)).
+                    invoke(array, Void.class, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class, $type$.class)).
+                    invoke(null, 0, $value1$, $value1$);
+            });
+            checkCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class, $type$.class)).
+                    invoke(Void.class, 0, $value1$, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class, $type$.class)).
+                    invoke(array, 0, Void.class, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class, $type$.class)).
+                    invoke(0, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class, $type$.class)).
+                    invoke(array, Void.class, $value1$, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invoke(array, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invoke(array, 0, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)).
+                    invoke(null, 0, $value1$);
+            });
+            checkCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
+                    invoke(Void.class, 0, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
+                    invoke(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
+                    invoke(array, Void.class, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
+                    invoke(array, 0, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
+                    invoke(array, 0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Void.class, int.class, $type$.class)).
+                    invoke(null, 0, $value1$);
+            });
+            checkCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
+                    invoke(Void.class, 0, $value1$);
+            });
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invoke(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
+                    invoke(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
+                    invoke(array, Void.class, $value1$);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
+                    invoke(array, 0, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
+                    invoke(array, 0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invoke();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invoke(array, 0, $value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8152645
+ * @summary test field lookup accessibility of MethodHandles and VarHandles
+ * @compile TestFieldLookupAccessibility.java
+ *          pkg/A.java pkg/B_extends_A.java pkg/C.java
+ *          pkg/subpkg/B_extends_A.java pkg/subpkg/C.java
+ * @run testng/othervm TestFieldLookupAccessibility
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import pkg.B_extends_A;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class TestFieldLookupAccessibility {
+
+    // The set of possible field lookup mechanisms
+    enum FieldLookup {
+        MH_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findGetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers());
+            }
+        },
+        MH_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findSetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_STATIC_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticGetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers());
+            }
+        },
+        MH_STATIC_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticSetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_UNREFLECT_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectGetter(f);
+            }
+        },
+        MH_UNREFLECT_GETTER_ACCESSIBLE() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectGetter(cloneAndSetAccessible(f));
+            }
+        },
+        MH_UNREFLECT_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectSetter(f);
+            }
+
+            boolean isAccessible(Field f) {
+                return f.isAccessible() || !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_UNREFLECT_SETTER_ACCESSIBLE() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectSetter(cloneAndSetAccessible(f));
+            }
+        },
+        VH() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers());
+            }
+        },
+        VH_STATIC() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers());
+            }
+        },
+        VH_UNREFLECT() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectVarHandle(f);
+            }
+        };
+
+        // Look up a handle to a field
+        abstract Object lookup(MethodHandles.Lookup l, Field f) throws Exception;
+
+        boolean isAccessible(Field f) {
+            return true;
+        }
+
+        static Field cloneAndSetAccessible(Field f) throws Exception {
+            // Clone to avoid mutating source field
+            f = f.getDeclaringClass().getDeclaredField(f.getName());
+            f.setAccessible(true);
+            return f;
+        }
+    }
+
+    @DataProvider
+    public Object[][] lookupProvider() throws Exception {
+        Stream<List<Object>> baseCases = Stream.of(
+                // Look up from same package
+                List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
+                List.of(pkg.A.class, B_extends_A.lookup(), B_extends_A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.C.lookup(), pkg.C.inaccessibleFields()),
+
+                // Look up from sub-package
+                List.of(pkg.A.class, pkg.subpkg.B_extends_A.lookup(), pkg.subpkg.B_extends_A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.subpkg.C.lookup(), pkg.subpkg.C.inaccessibleFields())
+        );
+
+        // Cross product base cases with the field lookup classes
+        return baseCases.
+                flatMap(l -> Stream.of(FieldLookup.values()).map(fl -> prepend(fl, l))).
+                toArray(Object[][]::new);
+    }
+
+    private static Object[] prepend(Object o, List<Object> l) {
+        List<Object> pl = new ArrayList<>();
+        pl.add(o);
+        pl.addAll(l);
+        return pl.toArray();
+    }
+
+    @Test(dataProvider = "lookupProvider")
+    public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
+        // Add to the expected failures all inaccessible fields due to accessibility modifiers
+        Set<String> expected = new HashSet<>(inaccessibleFields);
+        Map<Field, Throwable> actual = new HashMap<>();
+
+        for (Field f : fields(src)) {
+            // Add to the expected failures all inaccessible fields due to static/final modifiers
+            if (!fl.isAccessible(f)) {
+                expected.add(f.getName());
+            }
+
+            try {
+                fl.lookup(l, f);
+            }
+            catch (Throwable t) {
+                // Lookup failed, add to the actual failures
+                actual.put(f, t);
+            }
+        }
+
+        Set<String> actualFieldNames = actual.keySet().stream().map(Field::getName).
+                collect(Collectors.toSet());
+        if (!actualFieldNames.equals(expected)) {
+            if (actualFieldNames.isEmpty()) {
+                // Setting the accessibility bit of a Field grants access under
+                // all conditions for MethodHander getters and setters
+                if (fl != FieldLookup.MH_UNREFLECT_GETTER_ACCESSIBLE &&
+                    fl != FieldLookup.MH_UNREFLECT_SETTER_ACCESSIBLE) {
+                    Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
+                }
+            }
+            else {
+                Assert.assertEquals(actualFieldNames, expected, "Accessibility failures differ:");
+            }
+        }
+        else {
+            if (!actual.values().stream().allMatch(IllegalAccessException.class::isInstance)) {
+                Assert.fail("Expecting an IllegalArgumentException for all failures " + actual);
+            }
+        }
+    }
+
+    static List<Field> fields(Class<?> src) {
+        return List.of(src.getDeclaredFields());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/pkg/A.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class A {
+    public static Object f_public_static;
+    protected static Object f_protected_static;
+    static /*package*/ Object f_package_static;
+    private static Object f_private_static;
+
+    public static final Object f_public_static_final = null;
+    protected static final Object f_protected_static_final = null;
+    static /*package*/ final Object f_package_static_final = null;
+    private static final Object f_private_static_final = null;
+
+    public Object f_public;
+    protected Object f_protected;
+    /*package*/ Object f_package;
+    private Object f_private;
+
+    public final Object f_public_final = null;
+    protected final Object f_protected_final = null;
+    /*package*/ final Object f_package_final = null;
+    private final Object f_private_final = null;
+
+    //
+
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // All fields of pkg.A are accessible to itself
+        return Set.of();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class B_extends_A extends A {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only private fields of pkg.A are not accessible to subclass pkg.B
+        // Note: protected fields are also package accessible
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_private_static",
+                "f_private_static_final"
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/pkg/C.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class C {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only private fields of pkg.A are not accessible to independent
+        // class pkg.C
+        // Note: protected fields are also package accessible
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_private_static",
+                "f_private_static_final"
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg.subpkg;
+
+
+import pkg.A;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class B_extends_A extends A {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only public and protected fields of pkg.A are accessible to subclass
+        // pkg.subpkg.B
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_package",
+                "f_package_final",
+                "f_private_static",
+                "f_private_static_final",
+                "f_package_static",
+                "f_package_static_final"
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg.subpkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class C {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only public fields of pkg.A are accessible to independent
+        // class pkg.subpkg.C
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_protected",
+                "f_protected_final",
+                "f_package",
+                "f_package_final",
+                "f_private_static",
+                "f_private_static_final",
+                "f_protected_static",
+                "f_protected_static_final",
+                "f_package_static",
+                "f_package_static_final"
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/invoke/VarHandles/generate-vh-tests.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,155 @@
+#!/bin/bash
+
+javac -d . ../../../../../make/src/classes/build/tools/spp/Spp.java
+
+SPP=build.tools.spp.Spp
+
+# Generates variable handle tests for objects and all primitive types
+# This is likely to be a temporary testing approach as it may be more
+# desirable to generate code using ASM which will allow more flexibility
+# in the kinds of tests that are generated.
+
+for type in boolean byte short char int long float double String
+do
+  Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+  args="-K$type -Dtype=$type -DType=$Type"
+
+  case $type in
+    String|int|long)
+      args="$args -KCAS"
+      ;;
+  esac
+
+  case $type in
+    int|long)
+      args="$args -KAtomicAdd"
+      ;;
+  esac
+
+  wrong_primitive_type=boolean
+
+  case $type in
+    boolean)
+      value1=true
+      value2=false
+      value3=false
+      wrong_primitive_type=int
+      ;;
+    byte)
+      value1=(byte)1
+      value2=(byte)2
+      value3=(byte)3
+      ;;
+    short)
+      value1=(short)1
+      value2=(short)2
+      value3=(short)3
+      ;;
+    char)
+      value1=\'a\'
+      value2=\'b\'
+      value3=\'c\'
+      ;;
+    int)
+      value1=1
+      value2=2
+      value3=3
+      ;;
+    long)
+      value1=1L
+      value2=2L
+      value3=3L
+      ;;
+    float)
+      value1=1.0f
+      value2=2.0f
+      value3=3.0f
+      ;;
+    double)
+      value1=1.0d
+      value2=2.0d
+      value3=3.0d
+      ;;
+    String)
+      value1=\"foo\"
+      value2=\"bar\"
+      value3=\"baz\"
+      ;;
+  esac
+
+  args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3 -Dwrong_primitive_type=$wrong_primitive_type"
+
+  echo $args
+  java $SPP -nel $args < X-VarHandleTestAccess.java.template > VarHandleTestAccess${Type}.java
+  java $SPP -nel $args < X-VarHandleTestMethodHandleAccess.java.template > VarHandleTestMethodHandleAccess${Type}.java
+  java $SPP -nel $args < X-VarHandleTestMethodType.java.template > VarHandleTestMethodType${Type}.java
+done
+
+for type in short char int long float double
+do
+  Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+  args="-K$type -Dtype=$type -DType=$Type"
+
+  BoxType=$Type
+  case $type in
+    char)
+      BoxType=Character
+      ;;
+    int)
+      BoxType=Integer
+      ;;
+  esac
+  args="$args -DBoxType=$BoxType"
+
+  case $type in
+    int|long|float|double)
+      args="$args -KCAS"
+      ;;
+  esac
+
+  case $type in
+    int|long)
+      args="$args -KAtomicAdd"
+      ;;
+  esac
+
+  case $type in
+    short)
+      value1=(short)0x0102
+      value2=(short)0x1112
+      value3=(short)0x2122
+      ;;
+    char)
+      value1=(char)0x0102
+      value2=(char)0x1112
+      value3=(char)0x2122
+      ;;
+    int)
+      value1=0x01020304
+      value2=0x11121314
+      value3=0x21222324
+      ;;
+    long)
+      value1=0x0102030405060708L
+      value2=0x1112131415161718L
+      value3=0x2122232425262728L
+      ;;
+    float)
+      value1=0x01020304
+      value2=0x11121314
+      value3=0x21222324
+      ;;
+    double)
+      value1=0x0102030405060708L
+      value2=0x1112131415161718L
+      value3=0x2122232425262728L
+      ;;
+  esac
+
+  args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
+
+  echo $args
+  java $SPP -nel $args < X-VarHandleTestByteArrayView.java.template > VarHandleTestByteArrayAs${Type}.java
+done
+
+rm -fr build
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/reflect/ClassLoaderValue/Driver.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8152115
+ * @summary functional and concurrency test for ClassLoaderValue
+ * @build java.base/java.lang.reflect.ClassLoaderValueTest
+ * @run main Driver
+ */
+public class Driver {
+    public static void main(String[] args) throws Exception {
+        java.lang.reflect.ClassLoaderValueTest.main(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/reflect/ClassLoaderValue/java.base/java/lang/reflect/ClassLoaderValueTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Functional and concurrency test for ClassLoaderValue
+ *
+ * @author Peter Levart
+ */
+public class ClassLoaderValueTest {
+
+    @SuppressWarnings("unchecked")
+    public static void main(String[] args) throws Exception {
+
+        ClassLoaderValue[] clvs = {new ClassLoaderValue<>(),
+                                   new ClassLoaderValue<>()};
+
+        ClassLoader[] lds = {ClassLoader.getSystemClassLoader(),
+                             ClassLoader.getPlatformClassLoader(),
+                             null /* bootstrap class loader */};
+
+        Integer[] keys = new Integer[32];
+        for (int i = 0; i < keys.length; i++) {
+            keys[i] = i + 128;
+        }
+
+        try (AutoCloseable cleanup = () -> {
+            for (ClassLoaderValue<Integer> clv : clvs) {
+                for (ClassLoader ld : lds) {
+                    clv.removeAll(ld);
+                }
+            }
+        }) {
+            // 1st just one sequential pass of single-threaded validation
+            // which is easier to debug if it fails...
+            for (ClassLoaderValue<Integer> clv : clvs) {
+                for (ClassLoader ld : lds) {
+                    writeValidateOps(clv, ld, keys);
+                }
+            }
+            for (ClassLoaderValue<Integer> clv : clvs) {
+                for (ClassLoader ld : lds) {
+                    readValidateOps(clv, ld, keys);
+                }
+            }
+
+            // 2nd the same in concurrent setting that also validates
+            // failure-isolation between threads and data-isolation between
+            // regions - (ClassLoader, ClassLoaderValue) pairs - of the storage
+            testConcurrentIsolation(clvs, lds, keys, TimeUnit.SECONDS.toMillis(3));
+        }
+    }
+
+    static void writeValidateOps(ClassLoaderValue<Integer> clv,
+                                 ClassLoader ld,
+                                 Object[] keys) {
+        for (int i = 0; i < keys.length; i++) {
+            Object k = keys[i];
+            Integer v1 = i;
+            Integer v2 = i + 333;
+            Integer pv;
+            boolean success;
+
+            pv = clv.sub(k).putIfAbsent(ld, v1);
+            assertEquals(pv, null);
+            assertEquals(clv.sub(k).get(ld), v1);
+
+            pv = clv.sub(k).putIfAbsent(ld, v2);
+            assertEquals(pv, v1);
+            assertEquals(clv.sub(k).get(ld), v1);
+
+            success = clv.sub(k).remove(ld, v2);
+            assertEquals(success, false);
+            assertEquals(clv.sub(k).get(ld), v1);
+
+            success = clv.sub(k).remove(ld, v1);
+            assertEquals(success, true);
+            assertEquals(clv.sub(k).get(ld), null);
+
+            pv = clv.sub(k).putIfAbsent(ld, v2);
+            assertEquals(pv, null);
+            assertEquals(clv.sub(k).get(ld), v2);
+
+            pv = clv.sub(k).computeIfAbsent(ld, (_ld, _clv) -> v1);
+            assertEquals(pv, v2);
+            assertEquals(clv.sub(k).get(ld), v2);
+
+            success = clv.sub(k).remove(ld, v1);
+            assertEquals(success, false);
+            assertEquals(clv.sub(k).get(ld), v2);
+
+            success = clv.sub(k).remove(ld, v2);
+            assertEquals(success, true);
+            assertEquals(clv.sub(k).get(ld), null);
+
+            pv = clv.sub(k).computeIfAbsent(ld, (_ld, clv_k) -> {
+                try {
+                    // nested get for same key should throw
+                    clv_k.get(_ld);
+                    throw new AssertionError("Unexpected code path");
+                } catch (IllegalStateException e) {
+                    // expected
+                }
+                try {
+                    // nested putIfAbsent for same key should throw
+                    clv_k.putIfAbsent(_ld, v1);
+                    throw new AssertionError("Unexpected code path");
+                } catch (IllegalStateException e) {
+                    // expected
+                }
+                // nested remove for for same key and any value (even null)
+                // should return false
+                assertEquals(clv_k.remove(_ld, null), false);
+                assertEquals(clv_k.remove(_ld, v1), false);
+                assertEquals(clv_k.remove(_ld, v2), false);
+                try {
+                    // nested computeIfAbsent for same key should throw
+                    clv_k.computeIfAbsent(_ld, (__ld, _clv_k) -> v1);
+                    throw new AssertionError("Unexpected code path");
+                } catch (IllegalStateException e) {
+                    // expected
+                }
+                // if everything above has been handled, we should succeed...
+                return v2;
+            });
+            // ... and the result should be reflected in the CLV
+            assertEquals(pv, v2);
+            assertEquals(clv.sub(k).get(ld), v2);
+
+            success = clv.sub(k).remove(ld, v2);
+            assertEquals(success, true);
+            assertEquals(clv.sub(k).get(ld), null);
+
+            try {
+                clv.sub(k).computeIfAbsent(ld, (_ld, clv_k) -> {
+                    throw new UnsupportedOperationException();
+                });
+                throw new AssertionError("Unexpected code path");
+            } catch (UnsupportedOperationException e) {
+                // expected
+            }
+            assertEquals(clv.sub(k).get(ld), null);
+        }
+    }
+
+    static void readValidateOps(ClassLoaderValue<Integer> clv,
+                                ClassLoader ld,
+                                Object[] keys) {
+        for (int i = 0; i < keys.length; i++) {
+            Object k = keys[i];
+            Integer v1 = i;
+            Integer v2 = i + 333;
+            Integer rv = clv.sub(k).get(ld);
+            if (!(rv == null || rv.equals(v1) || rv.equals(v2))) {
+                throw new AssertionError("Unexpected value: " + rv +
+                                         ", expected one of: null, " + v1 + ", " + v2);
+            }
+        }
+    }
+
+    static void testConcurrentIsolation(ClassLoaderValue<Integer>[] clvs,
+                                        ClassLoader[] lds,
+                                        Object[] keys,
+                                        long millisRuntime) {
+        ExecutorService exe = Executors.newCachedThreadPool();
+        List<Future<?>> futures = new ArrayList<>();
+        AtomicBoolean stop = new AtomicBoolean();
+        for (ClassLoaderValue<Integer> clv : clvs) {
+            for (ClassLoader ld : lds) {
+                // submit a task that exercises a mix of modifying
+                // and reading-validating operations in an isolated
+                // part of the storage. If isolation is violated,
+                // validation operations are expected to fail.
+                futures.add(exe.submit(() -> {
+                    do {
+                        writeValidateOps(clv, ld, keys);
+                    } while (!stop.get());
+                }));
+                // submit a task that just reads from the same part of
+                // the storage as above task. It should not disturb
+                // above task in any way and this task should never
+                // exhibit any failure although above task produces
+                // regular failures during lazy computation
+                futures.add(exe.submit(() -> {
+                    do {
+                        readValidateOps(clv, ld, keys);
+                    } while (!stop.get());
+                }));
+            }
+        }
+        // wait for some time
+        try {
+            Thread.sleep(millisRuntime);
+        } catch (InterruptedException e) {
+            throw new AssertionError(e);
+        }
+        // stop tasks
+        stop.set(true);
+        // collect results
+        AssertionError error = null;
+        for (Future<?> future : futures) {
+            try {
+                future.get();
+            } catch (InterruptedException | ExecutionException e) {
+                if (error == null) error = new AssertionError("Failure");
+                error.addSuppressed(e);
+            }
+        }
+        exe.shutdown();
+        if (error != null) throw error;
+    }
+
+    static void assertEquals(Object actual, Object expected) {
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Expected: " + expected + ", actual: " + actual);
+        }
+    }
+}
--- a/test/java/net/Authenticator/B4933582.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/net/Authenticator/B4933582.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -44,7 +44,7 @@
     ;;
 esac
 
-EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED,java.base/sun.net.www.protocol.http=ALL-UNNAMED"
+EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED -XaddExports:java.base/sun.net.www.protocol.http=ALL-UNNAMED"
 export EXTRAOPTS
 
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
--- a/test/java/net/Inet4Address/DummyNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * A simple name service which throws an exception when invoked
- */
-
-import java.net.UnknownHostException;
-import java.net.InetAddress;
-import sun.net.spi.nameservice.*;
-import java.util.*;
-
-public final class DummyNameService implements NameService {
-
-    public DummyNameService() throws Exception {
-    }
-
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-        throw new UnknownHostException("Dummy name service");
-    }
-
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        throw new UnknownHostException("Dummy name service");
-    }
-}
--- a/test/java/net/Inet4Address/DummyNameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * Descriptor for the dummy name service
- */
-
-import sun.net.spi.nameservice.*;
-
-public final class DummyNameServiceDescriptor implements NameServiceDescriptor {
-
-    /**
-     * Create a new instance of the corresponding name service.
-     */
-    public NameService createNameService() throws Exception {
-        return new DummyNameService();
-    }
-
-    /**
-     * Returns this service provider's name
-     *
-     */
-    public String getProviderName() {
-        return "oracle";
-    }
-
-    /**
-     * Returns this name service type
-     * "dns" "nis" etc
-     */
-    public String getType() {
-        return "dummy";
-    }
-}
--- a/test/java/net/Inet4Address/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-
-DummyNameServiceDescriptor    # name service provider descriptor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/Inet4Address/TestToNumericFormatHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1 @@
+
--- a/test/java/net/Inet4Address/textToNumericFormat.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/net/Inet4Address/textToNumericFormat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
  * @test
  * @bug 4749938 8087190
  * @summary Bug in the parsing IPv4 literal addresses
- * @modules java.base/sun.net.spi.nameservice
- * @compile -XDignore.symbol.file=true DummyNameService.java DummyNameServiceDescriptor.java
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=dummy,oracle textToNumericFormat
+ * @run main/othervm  textToNumericFormat
 */
 
 /**
@@ -68,6 +66,8 @@
                            "1..1.1",
                            "1.1.1.",
                            "..." };
+        String hostsFileName = System.getProperty("test.src", ".") + "/TestToNumericFormatHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
 
         for (int i=0; i<goodAddrs.length; i++) {
             try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/InetAddress/InternalNameServiceTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8134577
+ * @summary Test the internal NameService implementation which is enabled via
+ *          the system property jdk.net.hosts.file. This property specifies
+ *          a file name that contains address host mappings, similar to those in
+ *          /etc/hosts file.
+ * @run main/othervm  InternalNameServiceTest
+ */
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+public class InternalNameServiceTest {
+
+    public static void main(String args[]) throws Exception {
+
+        String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
+        System.setProperty("sun.net.inetaddr.ttl", "0");
+
+        testHostToIPAddressMappings(hostsFileName);
+        testIpAddressToHostNameMappings(hostsFileName);
+    }
+
+    private static void testHostToIPAddressMappings(String hostsFileName)
+            throws Exception, UnknownHostException {
+        System.out.println(" TEST HOST TO  IP ADDRESS MAPPINGS ");
+        InetAddress testAddress;
+        byte[] retrievedIpAddr;
+        byte[] expectedIpAddr1 = { 1, 2, 3, 4 };
+        byte[] expectedIpAddr2 = { 5, 6, 7, 8 };
+        byte[] expectedIpAddrIpv6_1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+
+        // hosts file with
+        // # test hosts file for internal NameService
+        // 1.2.3.4 host.sample-domain
+        // 5.6.7.8 host1.sample-domain
+        // 1.2.3.4 host2.sample-domain  # this is a comment
+        // host3.sample-domain # no ip address
+        //  host4.sample-domain # space as ip address
+        //   host5.sample-domain # double space as ip address
+
+        // add comment to hosts file
+        addMappingToHostsFile("test hosts file for internal NameService ", "#", hostsFileName,
+                false);
+        addMappingToHostsFile("host.sample-domain", "1.2.3.4", hostsFileName,
+                true);
+
+        testAddress = InetAddress.getByName("host.sample-domain");
+        retrievedIpAddr = testAddress.getAddress();
+        if (!Arrays.equals(retrievedIpAddr, expectedIpAddr1)) {
+            throw new RuntimeException(
+                    "retrievedIpAddr not equal to expectedipAddr");
+        }
+
+        addMappingToHostsFile("host1.sample-domain", "5.6.7.8", hostsFileName,
+                true);
+        addMappingToHostsFile("host2.sample-domain", "1.2.3.4", hostsFileName,
+                true);
+
+        testAddress = InetAddress.getByName("host1.sample-domain");
+        retrievedIpAddr = testAddress.getAddress();
+        if (!Arrays.equals(retrievedIpAddr, expectedIpAddr2)) {
+            throw new RuntimeException(
+                    "retrievedIpAddr not equal to expectedIpAddr");
+        }
+
+        testAddress = InetAddress.getByName("host2.sample-domain");
+        retrievedIpAddr = testAddress.getAddress();
+        if (!Arrays.equals(retrievedIpAddr, expectedIpAddr1)) {
+            throw new RuntimeException(
+                    "retrievedIpAddr not equal to expectedIpAddr");
+        }
+
+        try {
+            addMappingToHostsFile("host3.sample-domain", "", hostsFileName,
+                    true);
+            testAddress = InetAddress.getByName("host3.sample-domain");
+            throw new RuntimeException(
+                    "Expected UnknownHostException not thrown");
+        } catch (UnknownHostException uhEx) {
+            System.out.println("UnknownHostException as expected for host host3.sample-domain");
+        }
+
+        try {
+            addMappingToHostsFile("host4.sample-domain", " ", hostsFileName,
+                    true);
+            testAddress = InetAddress.getByName("host4.sample-domain");
+            throw new RuntimeException(
+                    "Expected UnknownHostException not thrown");
+        } catch (UnknownHostException uhEx) {
+            System.out.println("UnknownHostException as expected for host host4.sample-domain");
+        }
+
+        try {
+            addMappingToHostsFile("host5.sample-domain", "  ", hostsFileName,
+                    true);
+            testAddress = InetAddress.getByName("host4.sample-domain");
+            throw new RuntimeException(
+                    "Expected UnknownHostException not thrown");
+        } catch (UnknownHostException uhEx) {
+            System.out.println("UnknownHostException as expected for host host5.sample-domain");
+        }
+
+        // IPV6 tests
+
+        // IPV6 tests
+        addMappingToHostsFile("host-ipv6.sample-domain", "::1", hostsFileName,
+                true);
+        testAddress = InetAddress.getByName("host-ipv6.sample-domain");
+        retrievedIpAddr = testAddress.getAddress();
+        if (!Arrays.equals(retrievedIpAddr, expectedIpAddrIpv6_1)) {
+            System.out.println("retrieved ipv6 addr == " + Arrays.toString(retrievedIpAddr));
+            System.out.println("expected ipv6 addr == " + Arrays.toString(expectedIpAddrIpv6_1));
+            throw new RuntimeException(
+                    "retrieved IPV6 Addr not equal to expected IPV6 Addr");
+        }
+    }
+
+    private static void testIpAddressToHostNameMappings(String hostsFileName)
+            throws Exception {
+        System.out.println(" TEST IP ADDRESS TO HOST MAPPINGS ");
+        InetAddress testAddress;
+        String retrievedHost;
+        String expectedHost = "testHost.testDomain";
+
+        byte[] testHostIpAddr = { 10, 2, 3, 4 };
+        byte[] testHostIpAddr2 = { 10, 5, 6, 7 };
+        byte[] testHostIpAddr3 = { 10, 8, 9, 10 };
+        byte[] testHostIpAddr4 = { 10, 8, 9, 11 };
+
+        // add comment to hosts file
+        addMappingToHostsFile("test hosts file for internal NameService ", "#", hostsFileName,
+                false);
+        addMappingToHostsFile("testHost.testDomain", "10.2.3.4", hostsFileName,
+                true);
+
+        testAddress = InetAddress.getByAddress(testHostIpAddr);
+        System.out.println("*******   testAddress == " + testAddress);
+        retrievedHost = testAddress.getHostName();
+        if (!expectedHost.equals(retrievedHost)) {
+            throw new RuntimeException(
+                    "retrieved host name not equal to expected host name");
+        }
+
+        addMappingToHostsFile("testHost.testDomain", "10.5.6.7", hostsFileName,
+                true);
+
+        testAddress = InetAddress.getByAddress(testHostIpAddr2);
+        System.out.println("*******   testAddress == " + testAddress);
+        retrievedHost = testAddress.getHostName();
+        System.out.println("*******   retrievedHost == " + retrievedHost);
+        if (!expectedHost.equals(retrievedHost)) {
+            throw new RuntimeException("retrieved host name " + retrievedHost
+                    + " not equal to expected host name" + expectedHost);
+        }
+
+        testAddress = InetAddress.getByAddress(testHostIpAddr4);
+        System.out.println("*******   testAddress == " + testAddress);
+        if ("10.8.9.11".equalsIgnoreCase(testAddress.getCanonicalHostName())) {
+            System.out.println("addr = " + addrToString(testHostIpAddr4)
+                    + "  resolve to a host address as expected");
+        } else {
+            System.out.println("addr = " + addrToString(testHostIpAddr4)
+                    + " does not resolve as expected, testAddress == " + testAddress.getCanonicalHostName());
+            throw new RuntimeException("problem with resolving "
+                    + addrToString(testHostIpAddr4));
+        }
+
+        try {
+            addMappingToHostsFile("", "10.8.9.10", hostsFileName, true);
+            testAddress = InetAddress.getByAddress(testHostIpAddr3);
+            System.out.println("*******   testAddress == " + testAddress);
+            retrievedHost = testAddress.getCanonicalHostName();
+        } catch (Throwable t) {
+            throw new RuntimeException("problem with resolving "
+                    + addrToString(testHostIpAddr3));
+        }
+
+    }
+
+    private static String addrToString(byte addr[]) {
+        return Byte.toString(addr[0]) + "." + Byte.toString(addr[1]) + "."
+                + Byte.toString(addr[2]) + "." + Byte.toString(addr[3]);
+    }
+
+    private static void addMappingToHostsFile( String host,
+                                               String addr,
+                                               String hostsFileName,
+                                               boolean append)
+                                               throws Exception {
+        String mapping = addr + " " + host;
+        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
+                new FileWriter(hostsFileName, append)))) {
+            hfPWriter.println(mapping);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/InetAddress/InternalNameServiceWithHostsFileTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8134577
+ * @summary Test the internal NameService implementation which is enabled via
+ *          the system property jdk.net.hosts.file. This property specifies
+ *          a file name that contains address host mappings, similar to those in
+ *          /etc/hosts file. TestHosts-III file  exist, with a set of ipv4 and ipv6
+ *          mappings
+ * @run main/othervm -Dsun.net.inetaddr.ttl=0  InternalNameServiceWithHostsFileTest
+ */
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+public class InternalNameServiceWithHostsFileTest {
+    public static void main(String args[]) throws Exception {
+
+        // System.getProperty("test.src", ".");
+        String hostsFileName = System.getProperty("test.src", ".")
+                + "/TestHosts-III";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
+        System.setProperty("sun.net.inetaddr.ttl", "0");
+
+        // fe80::1
+        byte[] expectedIpv6Address = { (byte) 0xfe, (byte) 0x80, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 1 };
+        // fe00::0
+        byte[] expectedIpv6LocalAddress = { (byte) 0xfe, (byte) 0x00, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+        // 10.2.3.4
+        byte[] expectedIpv4Address = { 10, 2, 3, 4 };
+        //
+        byte[] expectedIpv6LocalhostAddress = { 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+        try {
+            // 10.2.3.4  testHost.testDomain
+            testHostsMapping(expectedIpv4Address, "testHost.testDomain");
+            // ::1     ip6-localhost ip6-loopback
+            testHostsMapping(expectedIpv6LocalhostAddress, "ip6-localhost");
+            // fe00::0 ip6-localnet
+            testHostsMapping(expectedIpv6LocalAddress, "ip6-localnet");
+            // fe80::1 link-local-host
+            testHostsMapping(expectedIpv6Address, "link-local-host");
+
+        } catch (UnknownHostException uhEx) {
+            System.out.println("UHE unexpected caught == " + uhEx.getMessage());
+        }
+    }
+
+    private static void testHostsMapping(byte[] expectedIpAddress, String hostName)
+            throws UnknownHostException {
+        InetAddress testAddress;
+        byte[] rawIpAddress;
+        testAddress = InetAddress.getByName(hostName);
+        System.out
+                .println("############################  InetAddress == "
+                        + testAddress);
+
+        rawIpAddress = testAddress.getAddress();
+        if (!Arrays.equals(rawIpAddress, expectedIpAddress)) {
+            System.out.println("retrieved address == "
+                    + Arrays.toString(rawIpAddress)
+                    + " not equal to expected address == "
+                    + Arrays.toString(expectedIpAddress));
+            throw new RuntimeException(
+                    "retrieved address not equal to expected address");
+        }
+        System.out.println("retrieved address == "
+                + Arrays.toString(rawIpAddress)
+                + " equal to expected address == "
+                + Arrays.toString(expectedIpAddress));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/InetAddress/InternalNameServiceWithNoHostsFileTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8134577
+ * @summary Test the internal NameService implementation which is enabled via
+ *          the system property jdk.net.hosts.file. This property specifies
+ *          a file name that contains address host mappings, similar to those in
+ *          /etc/hosts file. TestHosts-II file doesn't exist, so a UHE should be
+ *          thrown
+ * @run main/othervm -Dsun.net.inetaddr.ttl=0  InternalNameServiceWithNoHostsFileTest
+ */
+
+
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+
+public class InternalNameServiceWithNoHostsFileTest {
+    public static void main(String args[]) throws Exception {
+
+        String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts-II";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
+        System.setProperty("sun.net.inetaddr.ttl", "0");
+        InetAddress testAddress = null;
+
+        try {
+            testAddress = InetAddress.getByName("host.sample-domain");
+            throw new RuntimeException ("UnknownHostException expected");
+        } catch (UnknownHostException uhEx) {
+            System.out.println("UHE caught as expected == " + uhEx.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/InetAddress/TestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,4 @@
+# test hosts file for internal NameService 
+10.2.3.4 testHost.testDomain
+10.5.6.7 testHost.testDomain
+10.8.9.10 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/InetAddress/TestHosts-III	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,11 @@
+# test hosts file for internal NameService
+10.2.3.4  testHost.testDomain
+10.5.6.7        testHost.testDomain
+10.8.9.10
+# The following lines are desirable for IPv6 capable hosts
+::1     ip6-localhost ip6-loopback
+fe80::1 link-local-host
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
--- a/test/java/net/URLPermission/nstest/LookupTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/net/URLPermission/nstest/LookupTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,14 +63,18 @@
     static ServerSocket serverSocket;
 
     public static void main(String args[]) throws Exception {
+
+
         String cmd = args[0];
         if (cmd.equals("-getport")) {
             port = Utils.getFreePort();
             System.out.print(port);
         } else if (cmd.equals("-runtest")) {
             port = Integer.parseInt(args[1]);
-            SimpleNameService.put("allowedAndFound.com", "127.0.0.1");
-            SimpleNameService.put("notAllowedButFound.com", "99.99.99.99");
+            String hostsFileName = System.getProperty("test.src", ".") + "/LookupTestHosts";
+            System.setProperty("jdk.net.hosts.file", hostsFileName);
+            addMappingToHostsFile("allowedAndFound.com", "127.0.0.1", hostsFileName, false);
+            addMappingToHostsFile("notAllowedButFound.com", "99.99.99.99", hostsFileName, true);
             // name "notAllowedAndNotFound.com" is not in map
             // name "allowedButNotfound.com" is not in map
             try {
@@ -124,4 +128,17 @@
             throw new RuntimeException ("Test failed to initialize", e);
         }
     }
+
+    private static void addMappingToHostsFile (String host,
+                                               String addr,
+                                               String hostsFileName,
+                                               boolean append)
+                                             throws Exception {
+        String mapping = addr + " " + host;
+        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
+                new FileWriter(hostsFileName, append)))) {
+            hfPWriter.println(mapping);
 }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/net/URLPermission/nstest/LookupTestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,2 @@
+127.0.0.1 allowedAndFound.com
+99.99.99.99 notAllowedButFound.com
--- a/test/java/net/URLPermission/nstest/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# 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.
-
-SimpleNameServiceDescriptor    # name service provider descriptor
--- a/test/java/net/URLPermission/nstest/SimpleNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-/*
- * A simple name service based on an in-memory HashMap.
- */
-import java.net.UnknownHostException;
-import java.net.InetAddress;
-import sun.net.spi.nameservice.*;
-import java.util.*;
-
-public final class SimpleNameService implements NameService {
-
-    private static LinkedHashMap hosts = new LinkedHashMap();
-
-    private static String addrToString(byte addr[]) {
-        return Byte.toString(addr[0]) + "." +
-               Byte.toString(addr[1]) + "." +
-               Byte.toString(addr[2]) + "." +
-               Byte.toString(addr[3]);
-    }
-
-    // ------------
-
-    public static void put(String host, String addr) {
-        hosts.put(host, addr);
-    }
-
-    public static void put(String host, byte addr[]) {
-        hosts.put(host, addrToString(addr));
-    }
-
-    public static void remove(String host) {
-        hosts.remove(host);
-    }
-
-    public static int entries () {
-        return hosts.size();
-    }
-
-    public static int lookupCalls() {
-        return lookupCalls;
-    }
-
-    static int lookupCalls = 0;
-
-    // ------------
-
-    public SimpleNameService() throws Exception {
-    }
-
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-
-        lookupCalls ++;
-
-        String value = (String)hosts.get(host);
-        if (value == null) {
-            throw new UnknownHostException(host);
-        }
-        StringTokenizer st = new StringTokenizer(value, ".");
-        byte addr[] = new byte[4];
-        for (int i=0; i<4; i++) {
-            addr[i] = (byte)Integer.parseInt(st.nextToken());
-        }
-        InetAddress[] res = new InetAddress[1];
-        res[0] = InetAddress.getByAddress(host, addr);
-        return res;
-    }
-
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        String addrString = addrToString(addr);
-        Iterator i = hosts.keySet().iterator();
-        while (i.hasNext()) {
-            String host = (String)i.next();
-            String value = (String)hosts.get(host);
-            if (value.equals(addrString)) {
-                return host;
-            }
-        }
-        throw new UnknownHostException();
-    }
-}
--- a/test/java/net/URLPermission/nstest/SimpleNameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-/*
- * Descriptor for the simple name service
- */
-import sun.net.spi.nameservice.*;
-
-public final class SimpleNameServiceDescriptor implements NameServiceDescriptor {
-    /**
-     * Create a new instance of the corresponding name service.
-     */
-    public NameService createNameService() throws Exception {
-        return new SimpleNameService();
-    }
-
-    /**
-     * Returns this service provider's name
-     *
-     */
-    public String getProviderName() {
-        return "sun";
-    }
-
-    /**
-     * Returns this name service type
-     * "dns" "nis" etc
-     */
-    public String getType() {
-        return "simple";
-    }
-}
--- a/test/java/net/URLPermission/nstest/lookup.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/net/URLPermission/nstest/lookup.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,8 @@
 
 # @test
 # @library /lib/testlibrary
-# @modules java.base/sun.net.spi.nameservice
 # @build jdk.testlibrary.*
-# @compile -XDignore.symbol.file=true SimpleNameService.java
-#            LookupTest.java SimpleNameServiceDescriptor.java
+# @compile -XDignore.symbol.file=true LookupTest.java
 # @run shell/timeout=50 lookup.sh
 #
 
@@ -58,7 +56,6 @@
 POLICY
 
 ${TESTJAVA}/bin/java ${TESTVMOPTS} \
-    -XaddExports:java.base/sun.net.spi.nameservice=ALL-UNNAMED \
     -Djava.security.policy=file:./policy \
-    -Dsun.net.spi.nameservice.provider.1=simple,sun \
+    -Dtest.src=${TESTSRC} \
     -cp ${TESTCLASSPATH}${PS}${TESTSRC} LookupTest -runtest ${port}
--- a/test/java/nio/Buffer/Basic-X.java.template	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/Basic-X.java.template	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -336,6 +336,103 @@
 
     }
 
+    private static void testAlign(final ByteBuffer b, boolean direct) {
+        // index out-of bounds
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+
+        // unit size values
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        for (int us = 1; us < 65; us++) {
+            int _us = us;
+            if ((us & (us - 1)) != 0) {
+                // unit size not a power of two
+                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+            } else {
+                if (direct || us <= 8) {
+                    b.alignmentOffset(0, us);
+                } else {
+                    // unit size > 8 with non-direct buffer
+                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                }
+            }
+        }
+
+        // Probe for long misalignment at index zero for a newly created buffer
+        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
+        if (direct) {
+            // Freshly created direct byte buffers should be aligned at index 0
+            // for ref and primitive values (see Unsafe.allocateMemory)
+            if (longMisalignmentAtZero != 0)
+                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        } else {
+            // For heap byte buffers misalignment may occur on 32-bit systems
+            // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
+            // Note the GC will preserve alignment of the base address of the
+            // array
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
+                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        }
+
+        // Ensure test buffer is correctly aligned at index 0
+        if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+            fail("Test input buffer not correctly aligned at index 0", b);
+
+        // Test misalignment values
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int i = 0; i < us * 2; i++) {
+                int am = b.alignmentOffset(i, us);
+                int expectedAm = (longMisalignmentAtZero + i) % us;
+
+                if (am != expectedAm)
+                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+            }
+        }
+
+        // Created aligned slice to test against
+        int ap = 8 - longMisalignmentAtZero;
+        int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+        ByteBuffer ab = b.position(ap).limit(al).
+                slice();
+        if (ab.limit() == 0)
+            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.alignmentOffset(0, 8) != 0)
+            fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int p = 1; p < 16; p++) {
+                int l = ab.limit() - p;
+
+                ByteBuffer as = ab.slice().position(p).limit(l).
+                        alignedSlice(us);
+
+                ck(as, 0, as.position());
+                ck(as, as.capacity(), as.limit());
+                if (b.isDirect() != as.isDirect())
+                    fail("Lost direction", as);
+                if (b.isReadOnly() != as.isReadOnly())
+                    fail("Lost read-only", as);
+
+                if (as.alignmentOffset(0, us) != 0)
+                    fail("Buffer not correctly aligned at index 0", as);
+
+                if (as.alignmentOffset(as.limit(), us) != 0)
+                    fail("Buffer not correctly aligned at limit", as);
+
+                int p_mod = ab.alignmentOffset(p, us);
+                int l_mod = ab.alignmentOffset(l, us);
+                // Round up position
+                p = (p_mod > 0) ? p + (us - p_mod) : p;
+                // Round down limit
+                l = l - l_mod;
+
+                int ec = l - p;
+                if (as.limit() != ec)
+                    fail("Buffer capacity incorrect, expected: " + ec, as);
+            }
+        }
+    }
 #end[byte]
 
     private static void fail(String problem,
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+#if[byte]
+        // Test alignment
+
+        testAlign(b, direct);
+#end[byte]
     }
 
 #if[char]
--- a/test/java/nio/Buffer/Basic.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/Basic.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
  * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
  *      4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
  *      6221101 6234263 6535542 6591971 6593946 6795561 7190219 7199551 8065556
+ *      8149469
+ * @modules java.base/jdk.internal.misc
  * @author Mark Reinhold
  */
 
--- a/test/java/nio/Buffer/BasicByte.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicByte.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -336,6 +336,103 @@
 
     }
 
+    private static void testAlign(final ByteBuffer b, boolean direct) {
+        // index out-of bounds
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+
+        // unit size values
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        for (int us = 1; us < 65; us++) {
+            int _us = us;
+            if ((us & (us - 1)) != 0) {
+                // unit size not a power of two
+                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+            } else {
+                if (direct || us <= 8) {
+                    b.alignmentOffset(0, us);
+                } else {
+                    // unit size > 8 with non-direct buffer
+                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                }
+            }
+        }
+
+        // Probe for long misalignment at index zero for a newly created buffer
+        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
+        if (direct) {
+            // Freshly created direct byte buffers should be aligned at index 0
+            // for ref and primitive values (see Unsafe.allocateMemory)
+            if (longMisalignmentAtZero != 0)
+                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        } else {
+            // For heap byte buffers misalignment may occur on 32-bit systems
+            // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
+            // Note the GC will preserve alignment of the base address of the
+            // array
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
+                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        }
+
+        // Ensure test buffer is correctly aligned at index 0
+        if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+            fail("Test input buffer not correctly aligned at index 0", b);
+
+        // Test misalignment values
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int i = 0; i < us * 2; i++) {
+                int am = b.alignmentOffset(i, us);
+                int expectedAm = (longMisalignmentAtZero + i) % us;
+
+                if (am != expectedAm)
+                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+            }
+        }
+
+        // Created aligned slice to test against
+        int ap = 8 - longMisalignmentAtZero;
+        int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+        ByteBuffer ab = b.position(ap).limit(al).
+                slice();
+        if (ab.limit() == 0)
+            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.alignmentOffset(0, 8) != 0)
+            fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int p = 1; p < 16; p++) {
+                int l = ab.limit() - p;
+
+                ByteBuffer as = ab.slice().position(p).limit(l).
+                        alignedSlice(us);
+
+                ck(as, 0, as.position());
+                ck(as, as.capacity(), as.limit());
+                if (b.isDirect() != as.isDirect())
+                    fail("Lost direction", as);
+                if (b.isReadOnly() != as.isReadOnly())
+                    fail("Lost read-only", as);
+
+                if (as.alignmentOffset(0, us) != 0)
+                    fail("Buffer not correctly aligned at index 0", as);
+
+                if (as.alignmentOffset(as.limit(), us) != 0)
+                    fail("Buffer not correctly aligned at limit", as);
+
+                int p_mod = ab.alignmentOffset(p, us);
+                int l_mod = ab.alignmentOffset(l, us);
+                // Round up position
+                p = (p_mod > 0) ? p + (us - p_mod) : p;
+                // Round down limit
+                l = l - l_mod;
+
+                int ec = l - p;
+                if (as.limit() != ec)
+                    fail("Buffer capacity incorrect, expected: " + ec, as);
+            }
+        }
+    }
 
 
     private static void fail(String problem,
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+        // Test alignment
+
+        testAlign(b, direct);
+
     }
 
 
--- a/test/java/nio/Buffer/BasicChar.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicChar.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              CharBuffer xb, CharBuffer yb,
                              char x, char y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/BasicDouble.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicDouble.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              DoubleBuffer xb, DoubleBuffer yb,
                              double x, double y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/BasicFloat.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicFloat.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              FloatBuffer xb, FloatBuffer yb,
                              float x, float y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/BasicInt.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicInt.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              IntBuffer xb, IntBuffer yb,
                              int x, int y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/BasicLong.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicLong.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              LongBuffer xb, LongBuffer yb,
                              long x, long y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/BasicShort.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/BasicShort.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              ShortBuffer xb, ShortBuffer yb,
                              short x, short y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/test/java/nio/Buffer/CopyDirectMemory.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/Buffer/CopyDirectMemory.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
  * @summary Test view buffer bulk operations for large buffers.
  * @bug 4463011
  *
+ * @modules java.base/jdk.internal.misc
  * @build Basic
  * @run main CopyDirectMemory
  */
--- a/test/java/nio/channels/Selector/SelectAndClose.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/channels/Selector/SelectAndClose.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 
 /* @test
  * @bug 5004077
+ * @key intermittent
  * @summary Check blocking of select and close
  */
 
--- a/test/java/nio/channels/SocketChannel/Connect.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/channels/SocketChannel/Connect.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4650679
+ * @bug 4650679 8037360
  * @summary Unit test for socket channels
  * @library ..
  */
@@ -42,9 +42,7 @@
             test1(echoServer);
         }
         try {
-            TestServers.RefusingServer refusingServer
-                = TestServers.RefusingServer.startNewServer();
-            test1(refusingServer);
+            test1(TestServers.RefusingServer.newRefusingServer());
             throw new Exception("Refused connection throws no exception");
         } catch (ConnectException ce) {
             // Correct result
--- a/test/java/nio/channels/TestServers.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/nio/channels/TestServers.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,13 +80,12 @@
             return address;
         }
 
-        public static RefusingServer startNewServer() throws IOException {
-            ServerSocket socket = new ServerSocket(0, 100,
-                    InetAddress.getLocalHost());
-            RefusingServer server = new RefusingServer(socket.getInetAddress(),
-                    socket.getLocalPort());
-            socket.close();
-            return server;
+        public static RefusingServer newRefusingServer() throws IOException {
+            // The port 1 is reserved for TCPMUX(RFC 1078), which is seldom used,
+            // and it's not used on all the test platform through JPRT.
+            // So we choose to use it as a refusing "server"'s "listen" port,
+            // it's much more stable than "open->close a server socket".
+            return new RefusingServer(InetAddress.getLocalHost(), 1);
         }
     }
 
--- a/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -51,6 +51,10 @@
 mkdir -p ext
 $COMPILEJAVA/bin/jar ${TESTTOOLVMOPTS} cf ext/ext.jar -C $TESTCLASSES ExtLoadedImpl.class -C $TESTCLASSES ExtLoadedImpl_Stub.class -C $TESTCLASSES CheckLoader.class
 
-TESTVMOPTS="${TESTVMOPTS}  -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
+TESTVMOPTS="${TESTVMOPTS} \
+ -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
 $TESTJAVA/bin/java ${TESTVMOPTS} -cp classes -Dtest.src=$TESTSRC -Dtest.classes=$TESTCLASSES -Djava.security.policy=$TESTSRC/security.policy -Djava.ext.dirs=ext ExtLoadedImplTest
 
--- a/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java	Mon Apr 11 11:19:33 2016 -0700
@@ -138,9 +138,11 @@
             p.put("java.security.policy", TestParams.defaultGroupPolicy);
             CommandEnvironment cmd = new ActivationGroupDesc.CommandEnvironment(
                     null,
-                    new String[] { "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
-                            + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
-                            + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
+                    new String[] {
+                        "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
 
             ActivationGroupDesc groupDesc =
                 new ActivationGroupDesc("MyActivationGroupImpl",
--- a/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java	Mon Apr 11 11:19:33 2016 -0700
@@ -120,9 +120,12 @@
             //
             System.err.println("Create activation group, in a new VM");
             CommandEnvironment cmd = new ActivationGroupDesc.CommandEnvironment(null,
-                    new String[] { "-XaddExports:java.base/sun.security.provider=ALL-UNNAMED,"
-                            + "java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,"
-                            + "java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
+                    new String[] {
+                        "-XaddExports:java.base/sun.security.provider=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED",
+                        "-XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
 
             ActivationGroupDesc groupDesc =
                 new ActivationGroupDesc(p, cmd);
--- a/test/java/rmi/registry/readTest/readTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/registry/readTest/readTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -98,7 +98,11 @@
     ;;
 esac
 # trailing / after code base is important for rmi codebase property.
-TESTVMOPTS="${TESTVMOPTS}  -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
+TESTVMOPTS="${TESTVMOPTS} \
+ -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED \
+ -XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp $TEST_CLASSPATH ${ARGS} -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 &
 TEST_PID=$!
 #bulk of testcase - let it run for a while
--- a/test/java/rmi/transport/checkFQDN/CheckFQDN.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/transport/checkFQDN/CheckFQDN.java	Mon Apr 11 11:19:33 2016 -0700
@@ -123,9 +123,10 @@
                                     propOption + property +
                                     equal +
                                     propertyValue + extraProp +
-                                    " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
-                                    + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
-                                    + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
+                                    " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED" +
+                                    " -XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED" +
+                                    " -XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED" +
+                                    " -XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                                     " -Drmi.registry.port=" +
                                     REGISTRY_PORT,
                                     "");
--- a/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Mon Apr 11 11:19:33 2016 -0700
@@ -74,10 +74,10 @@
         try {
             String options = " -Djava.security.policy=" +
                 TestParams.defaultPolicy +
-                " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED," +
-                "java.rmi/sun.rmi.server=ALL-UNNAMED," +
-                "java.rmi/sun.rmi.transport=ALL-UNNAMED," +
-                "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
+                " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED" +
+                " -XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED" +
+                " -XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED" +
+                " -XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                 " -Djava.rmi.dgc.leaseValue=500000" +
                 "  -Dsun.rmi.dgc.checkInterval=" +
                 (HOLD_TARGET_TIME - 5000) +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/text/Format/DateFormat/DateFormatSymbolsCloneTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8151431
+ * @summary Make sure that clone() of a DateFormatSymbols subclass is not
+ *          called from DateFormatSymbols constructor.
+ */
+import java.text.DateFormatSymbols;
+
+public class DateFormatSymbolsCloneTest extends DateFormatSymbols {
+    private int value;
+
+    public DateFormatSymbolsCloneTest() {
+        value = 1;
+    }
+
+    @Override
+    public Object clone() {
+        if (this.value == 0) {
+            throw new RuntimeException("clone() should not be called from a DateFormatSymbols constructor");
+        }
+        return super.clone();
+    }
+
+    public static void main(String[] args) {
+        new DateFormatSymbolsCloneTest();
+    }
+}
--- a/test/java/time/tck/java/time/chrono/TCKChronology.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/time/tck/java/time/chrono/TCKChronology.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,11 +68,16 @@
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.time.ZoneId;
 import java.time.Clock;
 import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
 import java.time.chrono.Chronology;
+import java.time.chrono.Era;
 import java.time.chrono.HijrahChronology;
 import java.time.chrono.HijrahEra;
 import java.time.chrono.IsoChronology;
@@ -97,6 +102,14 @@
 @Test
 public class TCKChronology {
 
+    private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1);
+    private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1);
+
+    private static final int YDIFF_MEIJI = 1867;
+    private static final int YDIFF_SHOWA = 1925;
+    private static final int YDIFF_HEISEI = 1988;
+    private static final int YDIFF_MINGUO = 1911;
+    private static final int YDIFF_THAIBUDDHIST = 543;
     //-----------------------------------------------------------------------
     // regular data factory for ID and calendarType of available calendars
     //-----------------------------------------------------------------------
@@ -323,7 +336,7 @@
         }
     }
 
-    @Test(expectedExceptions=DateTimeException.class)
+    @Test(expectedExceptions = DateTimeException.class)
     public void test_lookupLocale() {
         Locale.Builder builder = new Locale.Builder().setLanguage("en").setRegion("CA");
         builder.setUnicodeLocaleKeyword("ca", "xxx");
@@ -337,4 +350,78 @@
         Chronology chrono = Chronology.of("FooFoo");
     }
 
+    @DataProvider(name = "epochSecond_dataProvider")
+    Object[][]  data_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {JapaneseChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {JapaneseChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, 1434, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {MinguoChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {ThaiBuddhistChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "epochSecond_dataProvider")
+    public void test_epochSecond(Chronology chrono, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        ChronoLocalDate chronoLd = chrono.date(y, m, d);
+        assertEquals(chrono.epochSecond(y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(LocalDate.from(chronoLd), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @DataProvider(name = "era_epochSecond_dataProvider")
+    Object[][]  data_era_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, JapaneseEra.MEIJI, 1873 - YDIFF_MEIJI, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {JapaneseChronology.INSTANCE, JapaneseEra.SHOWA, 1928 - YDIFF_SHOWA, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {JapaneseChronology.INSTANCE, JapaneseEra.HEISEI, 1989 - YDIFF_HEISEI, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, HijrahEra.AH, 1434, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, MinguoEra.BEFORE_ROC, 1873 - YDIFF_MINGUO, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, MinguoEra.ROC, 1928 - YDIFF_MINGUO, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {MinguoChronology.INSTANCE, MinguoEra.ROC, 1989 - YDIFF_MINGUO, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1873 + YDIFF_THAIBUDDHIST, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1928 + YDIFF_THAIBUDDHIST, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1989 + YDIFF_THAIBUDDHIST, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "era_epochSecond_dataProvider")
+    public void test_epochSecond(Chronology chrono, Era era, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        ChronoLocalDate chronoLd = chrono.date(era, y, m, d);
+        assertEquals(chrono.epochSecond(era, y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(LocalDate.from(chronoLd), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @DataProvider(name = "bad_epochSecond_dataProvider")
+    Object[][]  bad_data_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, 1873, 13, 7, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, 1434, 9, 32, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1873, 9, 7, 31, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1928, 2, 28, -1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1928, 2, 28, 1, 60, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1989, 1, 8, 1, 2, -2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "bad_epochSecond_dataProvider", expectedExceptions = DateTimeException.class)
+    public void test_bad_epochSecond(Chronology chrono, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        chrono.epochSecond(y, m, d, h, min, s, offset);
+    }
+
 }
--- a/test/java/time/tck/java/time/chrono/TCKIsoChronology.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/time/tck/java/time/chrono/TCKIsoChronology.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,10 +63,16 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.time.ZoneId;
+import java.time.OffsetDateTime;
+import java.time.Year;
 import java.time.ZonedDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.chrono.Chronology;
+import java.time.chrono.Era;
+import java.time.chrono.HijrahEra;
 import java.time.chrono.IsoChronology;
+import java.time.chrono.IsoEra;
 import java.time.format.ResolverStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalAccessor;
@@ -87,6 +93,8 @@
 public class TCKIsoChronology {
     // Can only work with IsoChronology here
     // others may be in separate module
+    private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1);
+    private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1);
 
     @Test
     public void factory_from_TemporalAccessor_dateWithChronlogy() {
@@ -675,9 +683,114 @@
         }
     }
 
+    @DataProvider(name = "epochSecond_dataProvider")
+    Object[][] data_epochSecond() {
+        return new Object[][] {
+                {2008, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {2008, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {2008, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {2009, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {2009, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {2009, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1968, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {1968, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {1968, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {1969, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {1969, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1970, 1, 1, 1, 2, 2, OFFSET_P0100},
+                {1970, 1, 1, 1, 2, 2, OFFSET_M0100},
+                {-4, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {-1, 3, 3 , 1, 2, 2, OFFSET_P0100},
+        };
+    }
+
+    @Test(dataProvider = "epochSecond_dataProvider")
+    public void test_epochSecond_1(int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(y, m, d, h, min, s, 0, offset).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_2() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(2008, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+        assertEquals(IsoChronology.INSTANCE.epochSecond(1969, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_max() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MAX_VALUE, 12, 31, 23, 59, 59, ZoneOffset.MIN),
+                     OffsetDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 59, 0, ZoneOffset.MIN).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_min() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MIN_VALUE, 1, 1, 0, 0, 0, ZoneOffset.MAX),
+                     OffsetDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0, 0, 0, ZoneOffset.MAX).toEpochSecond());
+    }
+
+    @DataProvider(name = "bad_epochSecond_dataProvider")
+    Object[][]  bad_data_epochSecond() {
+        return new Object[][] {
+            {2009, 13, 1, 1, 1, 1, OFFSET_P0100},
+            {2009, 2, 29, 1, 1, 1, OFFSET_P0100},
+            {2009, 1, 1, 25, 1, 1, OFFSET_P0100},
+            {2009, 1, 1, 1, 60, 1, OFFSET_P0100},
+            {2009, 1, 1, 1, 1, -11, OFFSET_P0100},
+        };
+    }
+    @Test(dataProvider = "bad_epochSecond_dataProvider", expectedExceptions = DateTimeException.class)
+    public void test_epochSecond_bad(int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        IsoChronology.INSTANCE.epochSecond(y, m, d, h, min, s, offset);
+    }
+
+    @DataProvider(name = "era_epochSecond_dataProvider")
+    Object[][] data_era_epochSecond() {
+        return new Object[][] {
+                {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 2008, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 2009, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 1968, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 1969, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.BCE, 5, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {IsoEra.BCE, 2, 3, 3 , 1, 2, 2, OFFSET_P0100},
+        };
+    }
+
+    @Test(dataProvider = "era_epochSecond_dataProvider")
+    public void test_era_epochSecond_1(Era era, int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(era, y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(IsoChronology.INSTANCE.date(era, y, m, d), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @Test
+    public void test_era_epochSecond_2() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+        assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+    }
+
+    @Test(expectedExceptions = ClassCastException.class)
+    public void test_era_epochSecond_bad() {
+        IsoChronology.INSTANCE.epochSecond(HijrahEra.AH, 2009, 2, 29, 1, 2, 2, OFFSET_P0100);
+    }
+
+
     //-----------------------------------------------------------------------
     private static LocalDate date(int y, int m, int d) {
         return LocalDate.of(y, m, d);
     }
-
 }
--- a/test/java/util/Locale/LocaleProviders.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/Locale/LocaleProviders.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -122,7 +122,8 @@
 tznp8013086
 EOF
 
-EXTRAOPTS="-XaddExports:java.base/sun.util.locale=ALL-UNNAMED,java.base/sun.util.locale.provider=ALL-UNNAMED"
+EXTRAOPTS="-XaddExports:java.base/sun.util.locale=ALL-UNNAMED \
+ -XaddExports:java.base/sun.util.locale.provider=ALL-UNNAMED"
 
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d ${SPIDIR}${FS}dest \
     ${SPIDIR}${FS}src${FS}tznp.java \
--- a/test/java/util/PluggableLocale/ExecTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/PluggableLocale/ExecTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -93,7 +93,8 @@
 esac
 
 
-EXTRA_OPTS="-XaddExports:java.base/sun.util.locale.provider=ALL-UNNAMED,java.base/sun.util.resources=ALL-UNNAMED"
+EXTRA_OPTS="-XaddExports:java.base/sun.util.locale.provider=ALL-UNNAMED \
+ -XaddExports:java.base/sun.util.resources=ALL-UNNAMED"
 
 # compile
 cp ${TESTSRC}${FS}ProviderTest.java .
--- a/test/java/util/ResourceBundle/Bug6299235Test.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/ResourceBundle/Bug6299235Test.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -25,6 +25,7 @@
 # @test
 # @bug 6299235
 # @summary test Bug 6299235 to make sure the third-party provided sun resources could be picked up.
+# @modules java.desktop
 # @build Bug6299235Test
 # @run shell Bug6299235Test.sh
 
--- a/test/java/util/concurrent/locks/LockSupport/ParkLoops.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/concurrent/locks/LockSupport/ParkLoops.java	Mon Apr 11 11:19:33 2016 -0700
@@ -37,9 +37,11 @@
  * @summary Stress test looks for lost unparks
  * @library /lib/testlibrary/
  * @modules java.management
+ * @run main/timeout=1200 ParkLoops
  */
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
@@ -53,6 +55,7 @@
 import jdk.testlibrary.Utils;
 
 public final class ParkLoops {
+    static final long TEST_TIMEOUT_SECONDS = Utils.adjustTimeout(1000);
     static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
     static final int THREADS = 4;
     static final int ITERS = 30_000;
@@ -130,7 +133,7 @@
             pool.submit(unparker);
         }
         try {
-          if (!done.await(LONG_DELAY_MS, MILLISECONDS)) {
+          if (!done.await(TEST_TIMEOUT_SECONDS, SECONDS)) {
             dumpAllStacks();
             throw new AssertionError("lost unpark");
           }
--- a/test/java/util/concurrent/tck/CompletableFutureTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/concurrent/tck/CompletableFutureTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -3952,6 +3952,38 @@
                                  Monad.plus(godot, Monad.unit(5L)));
     }
 
+    /**
+     * A single CompletableFuture with many dependents.
+     * A demo of scalability - runtime is O(n).
+     */
+    public void testManyDependents() throws Throwable {
+        final int n = 1_000;
+        final CompletableFuture<Void> head = new CompletableFuture<>();
+        final CompletableFuture<Void> complete = CompletableFuture.completedFuture((Void)null);
+        final AtomicInteger count = new AtomicInteger(0);
+        for (int i = 0; i < n; i++) {
+            head.thenRun(() -> count.getAndIncrement());
+            head.thenAccept((x) -> count.getAndIncrement());
+            head.thenApply((x) -> count.getAndIncrement());
+
+            head.runAfterBoth(complete, () -> count.getAndIncrement());
+            head.thenAcceptBoth(complete, (x, y) -> count.getAndIncrement());
+            head.thenCombine(complete, (x, y) -> count.getAndIncrement());
+            complete.runAfterBoth(head, () -> count.getAndIncrement());
+            complete.thenAcceptBoth(head, (x, y) -> count.getAndIncrement());
+            complete.thenCombine(head, (x, y) -> count.getAndIncrement());
+
+            head.runAfterEither(new CompletableFuture<Void>(), () -> count.getAndIncrement());
+            head.acceptEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
+            head.applyToEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
+            new CompletableFuture<Void>().runAfterEither(head, () -> count.getAndIncrement());
+            new CompletableFuture<Void>().acceptEither(head, (x) -> count.getAndIncrement());
+            new CompletableFuture<Void>().applyToEither(head, (x) -> count.getAndIncrement());
+        }
+        head.complete(null);
+        assertEquals(5 * 3 * n, count.get());
+    }
+
 //     static <U> U join(CompletionStage<U> stage) {
 //         CompletableFuture<U> f = new CompletableFuture<>();
 //         stage.whenComplete((v, ex) -> {
--- a/test/java/util/concurrent/tck/JSR166TestCase.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/java/util/concurrent/tck/JSR166TestCase.java	Mon Apr 11 11:19:33 2016 -0700
@@ -211,10 +211,13 @@
     private static final int suiteRuns =
         Integer.getInteger("jsr166.suiteRuns", 1);
 
-    private static float systemPropertyValue(String name, float defaultValue) {
+    /**
+     * Returns the value of the system property, or NaN if not defined.
+     */
+    private static float systemPropertyValue(String name) {
         String floatString = System.getProperty(name);
         if (floatString == null)
-            return defaultValue;
+            return Float.NaN;
         try {
             return Float.parseFloat(floatString);
         } catch (NumberFormatException ex) {
@@ -226,16 +229,25 @@
 
     /**
      * The scaling factor to apply to standard delays used in tests.
+     * May be initialized from any of:
+     * - the "jsr166.delay.factor" system property
+     * - the "test.timeout.factor" system property (as used by jtreg)
+     *   See: http://openjdk.java.net/jtreg/tag-spec.html
+     * - hard-coded fuzz factor when using a known slowpoke VM
      */
-    private static final float delayFactor =
-        systemPropertyValue("jsr166.delay.factor", 1.0f);
+    private static final float delayFactor = delayFactor();
 
-    /**
-     * The timeout factor as used in the jtreg test harness.
-     * See: http://openjdk.java.net/jtreg/tag-spec.html
-     */
-    private static final float jtregTestTimeoutFactor
-        = systemPropertyValue("test.timeout.factor", 1.0f);
+    private static float delayFactor() {
+        float x;
+        if (!Float.isNaN(x = systemPropertyValue("jsr166.delay.factor")))
+            return x;
+        if (!Float.isNaN(x = systemPropertyValue("test.timeout.factor")))
+            return x;
+        String prop = System.getProperty("java.vm.version");
+        if (prop != null && prop.matches(".*debug.*"))
+            return 4.0f; // How much slower is fastdebug than product?!
+        return 1.0f;
+    }
 
     public JSR166TestCase() { super(); }
     public JSR166TestCase(String name) { super(name); }
@@ -526,6 +538,7 @@
                 "StampedLockTest",
                 "SubmissionPublisherTest",
                 "ThreadLocalRandom8Test",
+                "TimeUnit8Test",
             };
             addNamedTestClasses(suite, java8TestClassNames);
         }
@@ -616,7 +629,7 @@
      * http://openjdk.java.net/jtreg/command-help.html
      */
     protected long getShortDelay() {
-        return (long) (50 * delayFactor * jtregTestTimeoutFactor);
+        return (long) (50 * delayFactor);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/logging/Logger/getLogger/TestInferCaller.java	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * @test
+ * @bug 8152389
+ * @summary Verify the correct behavior of LogRecord.inferCaller() in particular
+ *          when a message is directly logged through the root logger.
+ * @run main/othervm TestInferCaller
+ * @author danielfuchs
+ */
+public class TestInferCaller {
+
+    static final class LogEvent {
+        public final String className;
+        public final String methodName;
+        public final LogRecord record;
+
+        public LogEvent(String className, String methodName, LogRecord record) {
+            this.className = className;
+            this.methodName = methodName;
+            this.record = record;
+        }
+
+    }
+
+    static final class TestHandler extends Handler {
+
+        public static final Queue<LogEvent> PUBLISHED = new LinkedList<LogEvent>();
+
+        public TestHandler() {
+            initLevel(Level.ALL);
+        }
+
+        @Override
+        public void close() throws SecurityException { }
+        @Override
+        public void publish(LogRecord record) {
+            LogEvent event = new LogEvent(record.getSourceClassName(),
+                                          record.getSourceMethodName(),
+                                          record);
+            PUBLISHED.add(event);
+        }
+        @Override
+        public void flush() {}
+
+        private void initLevel(Level newLevel) {
+            super.setLevel(newLevel);
+        }
+
+    }
+
+    public void test1(Logger logger) {
+        System.out.println("test1: " + loggerName(logger));
+
+        AtomicInteger count = new AtomicInteger();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        logger.setLevel(Level.ALL);
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+        logger.severe("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        LogEvent event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.warning("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.info("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.config("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.fine("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.finer("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+
+        logger.finest("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test1", "message " + count.get());
+    }
+
+    void test2(Logger logger) {
+        AtomicInteger count = new AtomicInteger();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        logger.setLevel(Level.ALL);
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+        for (Level l : Arrays.asList(Level.SEVERE, Level.WARNING, Level.INFO,
+                Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST)) {
+            System.out.println("test2: " + loggerName(logger) + " " + l);
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+            logger.log(l, "message " + count.incrementAndGet());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            LogEvent event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            logger.log(l, "message " + count.incrementAndGet(), "param");
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            logger.log(l, "message " + count.incrementAndGet(), new Object[] {"foo", "bar"});
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            logger.log(l, "message " + count.incrementAndGet(), new RuntimeException());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            // JDK 8 & 9 only (uses lambda)
+            logger.log(l, () -> "message " + count.incrementAndGet());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            // JDK 8 & 9 only (uses lambda)
+            logger.log(l, new RuntimeException(), () -> "message " + count.incrementAndGet());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            // JDK 9 only: new API
+            logger.logrb(l, (ResourceBundle)null, "message " + count.incrementAndGet(), (Object[]) null);
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+            // JDK 9 only: new API
+            logger.logrb(l, (ResourceBundle)null, "message " + count.incrementAndGet(), new RuntimeException());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), "test2", "message " + count.get());
+
+        }
+    }
+
+    void test3(Logger logger) {
+        System.out.println("test3: " + loggerName(logger));
+        AtomicInteger count = new AtomicInteger();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        logger.setLevel(Level.ALL);
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+        testReflection(logger, count, "severe", "testReflection");
+        testReflection(logger, count, "warning", "testReflection");
+        testReflection(logger, count, "info", "testReflection");
+        testReflection(logger, count, "config", "testReflection");
+        testReflection(logger, count, "fine", "testReflection");
+        testReflection(logger, count, "finer", "testReflection");
+        testReflection(logger, count, "finest", "testReflection");
+    }
+
+    void testReflection(Logger logger, AtomicInteger count, String logm, String method) {
+        try {
+            Method m = Logger.class.getMethod(logm, String.class);
+            m.invoke(logger, "message " + count.incrementAndGet());
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            LogEvent event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), method, "message " + count.get());
+
+            Method m2 = Method.class.getMethod("invoke", Object.class, new Object[0].getClass());
+            m2.invoke(m, logger, new Object[] { "message " + count.incrementAndGet() });
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), method, "message " + count.get());
+
+            m2.invoke(m2, m, new Object[] {logger, new Object[] { "message " + count.incrementAndGet() }});
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), method, "message " + count.get());
+
+            m2.invoke(m2, m2, new Object[] { m, new Object[] {logger, new Object[] { "message " + count.incrementAndGet() }}});
+            assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+            event = TestHandler.PUBLISHED.remove();
+            assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+            checkEvent(event, this.getClass().getName(), method, "message " + count.get());
+
+        } catch (Error | RuntimeException x ) {
+            throw x;
+        } catch (Exception x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    // JDK 8 & 9 only (uses lambda)
+    public void test4(Logger logger) {
+        System.out.println("test4: " + loggerName(logger));
+        AtomicInteger count = new AtomicInteger();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        logger.setLevel(Level.ALL);
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+        logger.severe(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        LogEvent event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.warning(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.info(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.config(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.fine(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.finer(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+
+        logger.finest(() -> "message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), "test4", "message " + count.get());
+    }
+
+    // JDK 8 & 9 only  (uses lambda)
+    void test5(Logger logger) {
+        System.out.println("test5: " + loggerName(logger));
+        AtomicInteger count = new AtomicInteger();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        logger.setLevel(Level.ALL);
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+
+        testLambda(count, logger::severe, "testLambda");
+        testLambda(count, logger::warning, "testLambda");
+        testLambda(count, logger::info, "testLambda");
+        testLambda(count, logger::config, "testLambda");
+        testLambda(count, logger::fine, "testLambda");
+        testLambda(count, logger::finer, "testLambda");
+        testLambda(count, logger::finest, "testLambda");
+    }
+
+    // JDK 8 & 9 only (uses lambda)
+    void testLambda(AtomicInteger count, Consumer<String> logm, String method) {
+        logm.accept("message " + count.incrementAndGet());
+        assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: ");
+        LogEvent event = TestHandler.PUBLISHED.remove();
+        assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: ");
+        checkEvent(event, this.getClass().getName(), method, "message " + count.get());
+    }
+
+    private static String loggerName(Logger logger) {
+        String name = logger.getName();
+        if (name == null) return "<anonymous>";
+        if (name.isEmpty()) return "<RootLogger>";
+        return "\"" + name + "\"";
+    }
+
+    public void test(Logger logger) {
+        test1(logger);
+        test2(logger);
+        test3(logger);
+
+        // JDK 8 & 9 only (uses lambda)
+        test4(logger);
+        test5(logger);
+    }
+
+    public static void main(String[] args) {
+        TestInferCaller test = new TestInferCaller();
+        Logger root = Logger.getLogger("");
+        for (Handler h : root.getHandlers()) {
+            h.setLevel(Level.OFF);
+        }
+        root.addHandler(new TestHandler());
+
+        for (Logger logger : Arrays.asList(root, Logger.getGlobal(),
+                Logger.getAnonymousLogger(), Logger.getLogger("foo.bar"))) {
+            System.out.println("Testing with: " + loggerName(logger) + " " + logger.getClass());
+            test.test(logger);
+        }
+    }
+
+    private static void assertEquals(int expected, int actual, String what) {
+        if (expected != actual) {
+            throw new RuntimeException(what
+                    + "\n\texpected: " + expected
+                    + "\n\tactual:   " + actual);
+        }
+    }
+
+    private static void assertEquals(String expected, String actual, String what) {
+        if (!Objects.equals(expected, actual)) {
+            throw new RuntimeException(what
+                    + "\n\texpected: " + expected
+                    + "\n\tactual:   " + actual);
+        }
+    }
+
+    private void checkEvent(LogEvent event, String className, String methodName, String message) {
+        assertEquals(className, event.className, "Bad class name: ");
+        assertEquals(className, event.record.getSourceClassName(), "Bad source class name: ");
+        assertEquals(methodName, event.methodName, "Bad method name: ");
+        assertEquals(methodName, event.record.getSourceMethodName(), "Bad source method name: ");
+        assertEquals(message, event.record.getMessage(), "Bad message: ");
+    }
+
+
+}
--- a/test/javax/net/ssl/DTLS/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/DTLS/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -4,6 +4,4 @@
     java.security.jgss/sun.security.krb5.internal.ccache \
     java.security.jgss/sun.security.krb5.internal \
     java.security.jgss/sun.security.krb5.internal.ktab \
-    java.base/sun.net.spi.nameservice \
-    java.base/sun.security.util \
-    java.base/sun.misc
+    java.base/sun.security.util
--- a/test/javax/net/ssl/DTLSv10/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/DTLSv10/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -4,6 +4,4 @@
     java.security.jgss/sun.security.krb5.internal.ccache \
     java.security.jgss/sun.security.krb5.internal \
     java.security.jgss/sun.security.krb5.internal.ktab \
-    java.base/sun.net.spi.nameservice \
-    java.base/sun.security.util \
-    java.base/sun.misc
+    java.base/sun.security.util
--- a/test/javax/net/ssl/ServerName/SSLEngineExplorer.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLEngineExplorer.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../SSLEngine ../templates
- * @modules java.base/sun.misc
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorer SSLv2Hello,SSLv3
  * @run main/othervm SSLEngineExplorer SSLv3
--- a/test/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../SSLEngine ../templates
- * @modules java.base/sun.misc
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerMatchedSNI www.example.com
  *     www\.example\.com
--- a/test/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../SSLEngine ../templates
- * @modules java.base/sun.misc
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerUnmatchedSNI www.example.com
  *                                                 www\.example\.org
--- a/test/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../SSLEngine ../templates
- * @modules java.base/sun.misc
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerWithCli
  */
--- a/test/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../SSLEngine ../templates
- * @modules java.base/sun.misc
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerWithSrv
  */
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorer.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorer.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorer SSLv2Hello,SSLv3
  * @run main/othervm SSLSocketExplorer SSLv3
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerFailure SSLv2Hello,SSLv3
  * @run main/othervm SSLSocketExplorerFailure SSLv3
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerMatchedSNI www.example.com
  *     www\.example\.com
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerUnmatchedSNI www.example.com
  *                                                 www\.example\.org
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerWithCliSNI
  */
--- a/test/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java	Mon Apr 11 11:19:33 2016 -0700
@@ -31,7 +31,6 @@
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  * @library ../templates
- * @modules java.base/sun.misc
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerWithSrvSNI
  */
--- a/test/javax/net/ssl/TLS/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/TLS/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -4,6 +4,5 @@
     java.security.jgss/sun.security.krb5 \
     java.security.jgss/sun.security.krb5.internal.ccache \
     java.security.jgss/sun.security.krb5.internal \
-    java.base/sun.net.spi.nameservice \
     java.base/sun.security.util \
     jdk.crypto.ec/sun.security.ec
--- a/test/javax/net/ssl/TLSv1/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/TLSv1/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -4,5 +4,4 @@
     java.security.jgss/sun.security.krb5.internal.ccache \
     java.security.jgss/sun.security.krb5.internal \
     java.security.jgss/sun.security.krb5.internal.ktab \
-    java.base/sun.net.spi.nameservice \
     java.base/sun.security.util
--- a/test/javax/net/ssl/TLSv11/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/net/ssl/TLSv11/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -4,5 +4,4 @@
     java.security.jgss/sun.security.krb5.internal.ccache \
     java.security.jgss/sun.security.krb5.internal \
     java.security.jgss/sun.security.krb5.internal.ktab \
-    java.base/sun.net.spi.nameservice \
     java.base/sun.security.util
--- a/test/javax/security/auth/Subject/SubjectNullTests.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/javax/security/auth/Subject/SubjectNullTests.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,8 +24,7 @@
 /*
  * @test
  * @bug 8015081
- * @modules java.base/sun.misc
- *          java.management
+ * @modules java.management
  *          java.security.jgss
  * @compile Subject.java
  * @compile SubjectNullTests.java
--- a/test/jdk/internal/ref/Cleaner/ExitOnThrow.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/jdk/internal/ref/Cleaner/ExitOnThrow.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
  * @bug 4954921 8009259
  * @library /test/lib/share/classes
  * @modules java.base/jdk.internal.ref
+ *          java.base/jdk.internal.misc
  * @build jdk.test.lib.*
  * @build jdk.test.lib.process.*
  * @run main ExitOnThrow
--- a/test/jdk/modules/etc/VerifyModuleDelegation.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/jdk/modules/etc/VerifyModuleDelegation.java	Mon Apr 11 11:19:33 2016 -0700
@@ -26,7 +26,7 @@
  * @summary Verify the defining class loader of each module never delegates
  *          to its child class loader. Also sanity check java.compact2
  *          requires.
- * @run testng VerifyModuleDelegation
+ * @run testng/othervm -Djdk.launcher.addmods=ALL-SYSTEM VerifyModuleDelegation
  */
 
 import java.lang.module.ModuleDescriptor;
--- a/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -51,7 +51,8 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
-EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED \
+ -XaddExports:java.management/sun.management.jmxremote=ALL-UNNAMED"
 export EXTRAOPTIONS
 
 # Call the common generic test
--- a/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -49,7 +49,8 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
-EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED \
+ -XaddExports:java.management/sun.management.jmxremote=ALL-UNNAMED"
 export EXTRAOPTIONS
 
 # Call the common generic test
--- a/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -48,7 +48,8 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
-EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED \
+ -XaddExports:java.management/sun.management.jmxremote=ALL-UNNAMED"
 export EXTRAOPTIONS
 
 # Call the common generic test
--- a/test/sun/misc/CopyMemory.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/misc/CopyMemory.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,7 +24,8 @@
 /* @test
  * @bug 6565543
  * @summary Minimal test for unsafe.copyMemory() and unsafe.setMemory()
- * @modules java.base/sun.nio.ch java.base/sun.misc
+ * @modules java.base/sun.nio.ch
+ *          jdk.unsupported
  * @key randomness
  */
 
--- a/test/sun/misc/Safe.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/misc/Safe.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,7 +25,7 @@
  * @bug 4495577
  * @summary Ensure that sun.misc.Unsafe cannot (easily)
  *          be accessed from user code
- * @modules java.base/sun.misc
+ * @modules jdk.unsupported
  */
 
 
--- a/test/sun/misc/SunMiscSignalTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/misc/SunMiscSignalTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -44,6 +44,8 @@
 /*
  * @test
  * @library /test/lib/share/classes
+ * @modules jdk.unsupported
+ *          java.base/jdk.internal.misc
  * @build jdk.test.lib.Platform jdk.test.lib.Utils
  * @run testng/othervm -Xrs -DXrs=true SunMiscSignalTest
  * @run testng/othervm SunMiscSignalTest
--- a/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-
-Simple1NameServiceDescriptor
-Simple2NameServiceDescriptor
--- a/test/sun/net/InetAddress/nameservice/chaining/Providers.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 4762344
- * @summary 2nd nameservice provider is non functional
- * @modules java.base/sun.net.spi.nameservice
- * @compile -XDignore.symbol.file=true SimpleNameService.java
- *                                     Simple1NameServiceDescriptor.java
- *                                     Simple2NameServiceDescriptor.java
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun Providers
- */
-
-import java.net.*;
-import java.util.*;
-
-
-public class Providers {
-    private static String[][] hostnames = new String[][] {
-            // both providers know this host, but with different address
-            new String[] {"blade", "10.0.0.1"},
-            // provider1 knwos this host
-            new String[] {"blade.domain1", "10.0.0.2"},
-            // provider2 knows this host
-            new String[] {"blade.domain2", "20.0.0.2"}
-        };
-    private static String[][] hostaddrs = new String[][] {
-            new String[] {"10.0.0.1", "blade"},
-            new String[] {"10.0.0.2", "blade.domain1"},
-            new String[] {"20.0.0.2", "blade.domain2"}
-        };
-
-    public static void main(String[] args) throws Exception {
-        for (int i = 0; i < hostnames.length; i++) {
-            doLookup(hostnames[i][0], hostnames[i][1]);
-        }
-        for (int i = 0; i < hostaddrs.length; i++) {
-            doReverseLookup(hostaddrs[i][0], hostaddrs[i][1]);
-        }
-    }
-
-    private static void doLookup(String host, String addr) throws Exception {
-        String res = InetAddress.getByName(host).getHostAddress();
-        if (!res.equals(addr)) {
-            throw new RuntimeException("Test failed: wrong address for host " + host);
-        }
-    }
-
-    private static void doReverseLookup(String addr, String host) throws Exception {
-        StringTokenizer tokenizer = new StringTokenizer(addr, ".");
-        byte addrs[] = new byte[4];
-        for (int i = 0; i < 4; i++) {
-            addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
-        }
-        String res = InetAddress.getByAddress(addrs).getHostName();
-        if (!res.equals(host)) {
-            throw new RuntimeException("Test failed: wrong host name for address " + addr);
-        }
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import sun.net.spi.nameservice.*;
-
-
-public class Simple1NameServiceDescriptor implements NameServiceDescriptor {
-    public NameService createNameService() {
-        SimpleNameService ns = new SimpleNameService();
-
-        // both providers know this host, but the address is different
-        ns.put("blade", "10.0.0.1");
-        // only this provider knows this host
-        ns.put("blade.domain1", "10.0.0.2");
-
-        return ns;
-    }
-
-    public String getProviderName() {
-        return "sun";
-    }
-
-    public String getType() {
-        return "simple1";
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import sun.net.spi.nameservice.*;
-
-
-public class Simple2NameServiceDescriptor implements NameServiceDescriptor {
-    public NameService createNameService() {
-        SimpleNameService ns = new SimpleNameService();
-        // both providers know this host, but the address of it is different
-        ns.put("blade", "20.0.0.1");
-        // only this provider knows this host
-        ns.put("blade.domain2", "20.0.0.2");
-
-        return ns;
-    }
-
-    public String getProviderName() {
-        return "sun";
-    }
-
-    public String getType() {
-        return "simple2";
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import java.net.*;
-import java.util.*;
-import sun.net.spi.nameservice.*;
-
-
-public class SimpleNameService implements NameService {
-    // host name <-> host addr mapping
-    private HashMap<String, String> hosts = new LinkedHashMap<String, String>();
-
-    public void put(String host, String addr) {
-        hosts.put(host, addr);
-    }
-
-    private static String addrToString(byte addr[]) {
-        return Byte.toString(addr[0]) + "." +
-               Byte.toString(addr[1]) + "." +
-               Byte.toString(addr[2]) + "." +
-               Byte.toString(addr[3]);
-    }
-
-    public SimpleNameService() {
-    }
-
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-        String addr = hosts.get(host);
-        if (addr == null) {
-            throw new UnknownHostException(host);
-        }
-
-        StringTokenizer tokenizer = new StringTokenizer(addr, ".");
-        byte addrs[] = new byte[4];
-        for (int i = 0; i < 4; i++) {
-            addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
-        }
-        InetAddress[] ret = new InetAddress[1];
-        ret[0] = InetAddress.getByAddress(host, addrs);
-        return ret;
-    }
-
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        String addrString = addrToString(addr);
-        Iterator i = hosts.keySet().iterator();
-        while (i.hasNext()) {
-            String host = (String)i.next();
-            String value = (String)hosts.get(host);
-            if (value.equals(addrString)) {
-                return host;
-            }
-        }
-        throw new UnknownHostException();
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/deadlock/Hang.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 7012768
- * @modules java.base/sun.net.spi.nameservice
- * @compile -XDignore.symbol.file=true ThrowingNameService.java
- *          ThrowingNameServiceDescriptor.java
- * @run main/othervm/timeout=30 -Dsun.net.spi.nameservice.provider.1=throwing,sun Hang
- * @summary InetAddress lookupTable leaks/deadlocks when using unsupported
- *          name service spi
- */
-
-import java.net.InetAddress;
-
-public class Hang {
-    public static void main(String[] args) throws Exception {
-        try {
-            // 1st attempt - IllegalStateException caught below
-            InetAddress.getByName("host.company.com");
-        } catch (IllegalStateException e) { }
-
-        // 2nd attempt - Stuck here forever if bug exists
-        InetAddress.getByName("host.company.com");
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-
-ThrowingNameServiceDescriptor
--- a/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import sun.net.spi.nameservice.NameService;
-
-public class ThrowingNameService implements NameService {
-    static boolean firstCall = true;
-
-    @Override
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-        if (firstCall) {
-            firstCall = false;
-            // throw unchecked exception first time round
-            throw new IllegalStateException();
-        }
-
-        // return any valid address
-        return new InetAddress[] { InetAddress.getLoopbackAddress() };
-    }
-
-    @Override
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        throw new IllegalStateException();
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import sun.net.spi.nameservice.*;
-
-public class ThrowingNameServiceDescriptor implements NameServiceDescriptor {
-    public NameService createNameService() {
-        return new ThrowingNameService();
-    }
-
-    @Override
-    public String getProviderName() {
-        return "sun";
-    }
-
-    @Override
-    public String getType() {
-        return "throwing";
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/dns/cname.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/net/InetAddress/nameservice/dns/cname.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -66,8 +66,8 @@
 np="-Dsun.net.spi.nameservice.provider.1=dns,sun"
 sm="-Djava.security.manager -Djava.security.policy=${POLICY}"
 
-go "$np" "$HOST"
-go "$np $sm" "$HOST"
+go "" "$HOST"
+go "$sm" "$HOST"
 
 
 #
--- a/test/sun/net/InetAddress/nameservice/simple/CacheTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/net/InetAddress/nameservice/simple/CacheTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,14 +26,14 @@
  * @summary Check that InetAddress doesn't continue to throw UHE
  *          after the name service has recovered and the negative ttl
  *          on the initial lookup has expired.
- * @modules java.base/sun.net.spi.nameservice
- * @compile -XDignore.symbol.file=true SimpleNameService.java
- *                                     SimpleNameServiceDescriptor.java
- * @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun CacheTest
+ * @run main/othervm/timeout=200 CacheTest
  */
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.security.Security;
+import java.io.PrintWriter;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
 
 public class CacheTest {
 
@@ -59,6 +59,8 @@
             return;
 
         }
+        String hostsFileName = System.getProperty("test.src", ".") + "/CacheTestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
 
         /*
          * The following outlines how the test works :-
@@ -78,7 +80,7 @@
          */
 
         // name service needs to resolve this.
-        SimpleNameService.put("theclub", "129.156.220.219");
+        addMappingToHostsFile("theclub", "129.156.220.219", hostsFileName, false);
 
         // this lookup will succeed
         InetAddress.getByName("theclub");
@@ -89,12 +91,12 @@
         try {
             InetAddress.getByName("luster");
             throw new RuntimeException("Test internal error " +
-                " - luster is bring resolved by name service");
+                " - luster is being resolved by name service");
         } catch (UnknownHostException x) {
         }
 
         // name service now needs to know about luster
-        SimpleNameService.put("luster", "10.5.18.21");
+        addMappingToHostsFile("luster", "10.5.18.21", hostsFileName, true);
 
         // wait for the cache entry to expire and lookup should
         // succeed.
@@ -102,4 +104,16 @@
         InetAddress.getByName("luster");
     }
 
+    private static void addMappingToHostsFile ( String host,
+                                                String addr,
+                                                String hostsFileName,
+                                                boolean append)
+                                                throws Exception {
+        String mapping = addr + " " + host;
+        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
+                new FileWriter(hostsFileName, append)))) {
+            hfPWriter.println(mapping);
 }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/InetAddress/nameservice/simple/CacheTestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,2 @@
+129.156.220.219 theclub
+10.5.18.21 luster
--- a/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,35 +25,40 @@
  * @bug 6442088
  * @summary Change default DNS caching behavior for code not running under
  *          security manager.
- * @modules java.base/sun.net.spi.nameservice
- * @compile -XDignore.symbol.file=true SimpleNameService.java
- *                                     SimpleNameServiceDescriptor.java
- * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun DefaultCaching
+ * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20  DefaultCaching
  */
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.security.Security;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.io.BufferedWriter;
 
 public class DefaultCaching {
 
     public static void main(String args[]) throws Exception {
 
+        String hostsFileName = System.getProperty("test.src", ".") + "/DefaultCachingHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
+        // initial mapping
         // name service needs to resolve this.
-        SimpleNameService.put("theclub", "129.156.220.219");
+        addMappingToHostsFile("theclub", "129.156.220.219", hostsFileName, false);
 
         test ("theclub", "129.156.220.219", true);      // lk: 1
         test ("luster", "1.16.20.2", false);            // lk: 2
 
         // name service now needs to know about luster
-        SimpleNameService.put("luster", "10.5.18.21");
+        addMappingToHostsFile("luster", "10.5.18.21", hostsFileName, true);
 
         test ("luster", "1.16.20.2", false);            // lk: 2
         sleep (10+1);
         test("luster", "10.5.18.21", true, 3);          // lk: 3
         sleep (5);
 
-        SimpleNameService.put("foo", "10.5.18.22");
-        SimpleNameService.put("theclub", "129.156.220.1");
+        // new mapping for theclub and rewrite existing foo and luster mappings
+        addMappingToHostsFile("theclub", "129.156.220.1", hostsFileName, false);
+        addMappingToHostsFile("foo", "10.5.18.22", hostsFileName, true);
+        addMappingToHostsFile("luster", "10.5.18.21", hostsFileName, true);
 
         test ("theclub", "129.156.220.219", true, 3);
         test ("luster", "10.5.18.21", true, 3);
@@ -84,10 +89,6 @@
     static void test (String host, String address,
                         boolean shouldSucceed, int count) {
         test (host, address, shouldSucceed);
-        int got = SimpleNameService.lookupCalls();
-        if (got != count) {
-            throw new RuntimeException ("lookups exp/got: " + count+"/"+got);
-        }
     }
 
     static void sleep (int seconds) {
@@ -114,4 +115,16 @@
         }
     }
 
+
+    private static void addMappingToHostsFile (String host,
+                                               String addr,
+                                               String hostsFileName,
+                                               boolean append)
+                                             throws Exception {
+        String mapping = addr + " " + host;
+        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
+                new FileWriter(hostsFileName, append)))) {
+            hfPWriter.println(mapping);
 }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/InetAddress/nameservice/simple/DefaultCachingHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,3 @@
+129.156.220.1 theclub
+10.5.18.22 foo
+10.5.18.21 luster
--- a/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-
-SimpleNameServiceDescriptor    # name service provider descriptor
--- a/test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * A simple name service based on an in-memory HashMap.
- */
-import java.net.UnknownHostException;
-import java.net.InetAddress;
-import sun.net.spi.nameservice.*;
-import java.util.*;
-
-public final class SimpleNameService implements NameService {
-
-    private static LinkedHashMap hosts = new LinkedHashMap();
-
-    private static String addrToString(byte addr[]) {
-        return Byte.toString(addr[0]) + "." +
-               Byte.toString(addr[1]) + "." +
-               Byte.toString(addr[2]) + "." +
-               Byte.toString(addr[3]);
-    }
-
-    // ------------
-
-    public static void put(String host, String addr) {
-        hosts.put(host, addr);
-    }
-
-    public static void put(String host, byte addr[]) {
-        hosts.put(host, addrToString(addr));
-    }
-
-    public static void remove(String host) {
-        hosts.remove(host);
-    }
-
-    public static int entries () {
-        return hosts.size();
-    }
-
-    public static int lookupCalls() {
-        return lookupCalls;
-    }
-
-    static int lookupCalls = 0;
-
-    // ------------
-
-    public SimpleNameService() throws Exception {
-    }
-
-    public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-
-        lookupCalls ++;
-
-        String value = (String)hosts.get(host);
-        if (value == null) {
-            throw new UnknownHostException(host);
-        }
-        StringTokenizer st = new StringTokenizer(value, ".");
-        byte addr[] = new byte[4];
-        for (int i=0; i<4; i++) {
-            addr[i] = (byte)Integer.parseInt(st.nextToken());
-        }
-        InetAddress[] res = new InetAddress[1];
-        res[0] = InetAddress.getByAddress(host, addr);
-        return res;
-    }
-
-    public String getHostByAddr(byte[] addr) throws UnknownHostException {
-        String addrString = addrToString(addr);
-        Iterator i = hosts.keySet().iterator();
-        while (i.hasNext()) {
-            String host = (String)i.next();
-            String value = (String)hosts.get(host);
-            if (value.equals(addrString)) {
-                return host;
-            }
-        }
-        throw new UnknownHostException();
-    }
-}
--- a/test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * Descriptor for the simple name service
- */
-import sun.net.spi.nameservice.*;
-
-public final class SimpleNameServiceDescriptor implements NameServiceDescriptor {
-    /**
-     * Create a new instance of the corresponding name service.
-     */
-    public NameService createNameService() throws Exception {
-        return new SimpleNameService();
-    }
-
-    /**
-     * Returns this service provider's name
-     *
-     */
-    public String getProviderName() {
-        return "sun";
-    }
-
-    /**
-     * Returns this name service type
-     * "dns" "nis" etc
-     */
-    public String getType() {
-        return "simple";
-    }
-}
--- a/test/sun/net/www/ftptest/FtpCommandHandler.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/net/www/ftptest/FtpCommandHandler.java	Mon Apr 11 11:19:33 2016 -0700
@@ -442,7 +442,9 @@
             // cmd.setSoTimeout(2000);
             in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
             out = new PrintStream(cmd.getOutputStream(), true, "ISO8859_1");
-            out.println("220 Java FTP test server (j2se 6.0) ready.");
+            out.println("---------------------------------\n220 Java FTP test server"
+                    + " (j2se 6.0) ready.\n \n                Please send commands\n"
+                    + "-----------------------------\n\n\n");
             out.flush();
             if (auth.authType() == 0) // No auth needed
                 logged = true;
--- a/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 7194897
  * @summary JSR 292: Cannot create more than 16 instances of an anonymous class
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.misc
  *          java.management
  * @library /lib/testlibrary
  * @author  Robert Field
@@ -37,7 +37,7 @@
  */
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class ManyNewInstanceAnonTest {
 
--- a/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Mon Apr 11 11:19:33 2016 -0700
@@ -68,9 +68,10 @@
         // (neither on standard output, nor on standard err streams).
         JavaVM vm = new JavaVM(
                 DoRMIStuff.class.getName(),
-                "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
-                + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
-                + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
+                "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED"
+                + " -XaddExports:java.rmi/sun.rmi.server=ALL-UNNAMED"
+                + " -XaddExports:java.rmi/sun.rmi.transport=ALL-UNNAMED"
+                + " -XaddExports:java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
                 + " -Djava.util.logging.config.file="
                 + loggingPropertiesFile, "", out, err);
         vm.execute();
--- a/test/sun/security/krb5/auto/BogusKDC.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/BogusKDC.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,7 +82,7 @@
         // and wrong port for slave KDC
         try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) {
             w.write(String.format(KRB5_CONF_TEMPLATE,
-                    KDC.KDCNameService.NOT_EXISTING_HOST, WRONG_KDC_PORT));
+                    KDC.NOT_EXISTING_HOST, WRONG_KDC_PORT));
             w.flush();
         }
 
@@ -98,7 +98,7 @@
         // but correct port for slave KDC
         try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) {
             w.write(String.format(KRB5_CONF_TEMPLATE,
-                    KDC.KDCNameService.NOT_EXISTING_HOST, kdc.getPort()));
+                    KDC.NOT_EXISTING_HOST, kdc.getPort()));
             w.flush();
         }
 
--- a/test/sun/security/krb5/auto/HttpNegotiateServer.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/HttpNegotiateServer.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,8 +24,7 @@
 /*
  * @test
  * @bug 6578647 6829283
- * @modules java.base/sun.net.spi.nameservice
- *          java.base/sun.security.util
+ * @modules java.base/sun.security.util
  *          java.security.jgss/sun.security.jgss
  *          java.security.jgss/sun.security.krb5
  *          java.security.jgss/sun.security.krb5.internal
--- a/test/sun/security/krb5/auto/KDC.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/KDC.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,6 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import sun.net.spi.nameservice.NameService;
-import sun.net.spi.nameservice.NameServiceDescriptor;
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.ccache.CredentialsCache;
@@ -129,6 +127,8 @@
     public static final int DEFAULT_LIFETIME = 39600;
     public static final int DEFAULT_RENEWTIME = 86400;
 
+    public static String NOT_EXISTING_HOST = "not.existing.host";
+
     // Under the hood.
 
     // The random generator to generate random keys (including session keys)
@@ -219,7 +219,8 @@
     };
 
     static {
-        System.setProperty("sun.net.spi.nameservice.provider.1", "ns,mock");
+        String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
     }
 
     /**
@@ -1448,45 +1449,6 @@
         }
     }
 
-    public static class KDCNameService implements NameServiceDescriptor {
-
-        public static String NOT_EXISTING_HOST = "not.existing.host";
-
-        @Override
-        public NameService createNameService() throws Exception {
-            NameService ns = new NameService() {
-                @Override
-                public InetAddress[] lookupAllHostAddr(String host)
-                        throws UnknownHostException {
-                    // Everything is localhost except NOT_EXISTING_HOST
-                    if (NOT_EXISTING_HOST.equals(host)) {
-                        throw new UnknownHostException("Unknown host name: "
-                                + NOT_EXISTING_HOST);
-                    }
-                    return new InetAddress[]{
-                        InetAddress.getByAddress(host, new byte[]{127,0,0,1})
-                    };
-                }
-                @Override
-                public String getHostByAddr(byte[] addr)
-                        throws UnknownHostException {
-                    // No reverse lookup, PrincipalName use original string
-                    throw new UnknownHostException();
-                }
-            };
-            return ns;
-        }
-
-        @Override
-        public String getProviderName() {
-            return "mock";
-        }
-
-        @Override
-        public String getType() {
-            return "ns";
-        }
-    }
 
     // Calling private methods thru reflections
     private static final Field getPADataField;
--- a/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-KDC$KDCNameService
--- a/test/sun/security/krb5/auto/NoAddresses.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/NoAddresses.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 7032354
+ * @run main/othervm NoAddresses setup
  * @run main/othervm NoAddresses 1
  * @run main/othervm NoAddresses 2
  * @run main/othervm/fail NoAddresses 3
@@ -34,12 +35,24 @@
 import org.ietf.jgss.ChannelBinding;
 import sun.security.jgss.GSSUtil;
 import sun.security.krb5.Config;
+import java.io.PrintWriter;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
 
 public class NoAddresses {
 
     public static void main(String[] args)
             throws Exception {
 
+        if (args[0].equalsIgnoreCase("setup")) {
+            // add a mapping of test host name to 127.0.0.1 to test's hosts file
+            InetAddress localHost = InetAddress.getLocalHost();
+            String localHostName = localHost.getHostName();
+            String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+            String loopBackAddress = "127.0.0.1";
+            System.setProperty("jdk.net.hosts.file", hostsFileName);
+            addMappingToHostsFile(localHostName, loopBackAddress, hostsFileName, true);
+        } else {
         OneKDC kdc = new OneKDC(null);
         kdc.writeJAASConf();
         KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
@@ -79,3 +92,16 @@
         Context.handshake(c, s);
     }
 }
+
+    private static void addMappingToHostsFile (String host,
+                                               String addr,
+                                               String hostsFileName,
+                                               boolean append)
+                                             throws Exception {
+        String mapping = addr + " " + host;
+        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
+                new FileWriter(hostsFileName, append)))) {
+            hfPWriter.println(mapping);
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/Renew.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/Renew.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,7 @@
  * @bug 8058290
  * @summary JAAS Krb5LoginModule has suspect ticket-renewal logic,
  *          relies on clockskew grace
- * @modules java.base/sun.net.spi.nameservice
- *          java.base/sun.security.util
+ * @modules java.base/sun.security.util
  *          java.security.jgss/sun.security.krb5
  *          java.security.jgss/sun.security.krb5.internal
  *          java.security.jgss/sun.security.krb5.internal.ccache
--- a/test/sun/security/krb5/auto/Renewal.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/Renewal.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,8 +45,11 @@
 
     static OneKDC kdc;
     static String clazz = "sun.security.krb5.internal.tools.Kinit";
+    static String hostsFileName = null;
 
     public static void main(String[] args) throws Exception {
+        hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
 
         kdc = new OneKDC(null);
         kdc.writeJAASConf();
@@ -95,7 +98,7 @@
         count++;
         p.args(OneKDC.USER, new String(OneKDC.PASS))
                 .inheritIO()
-                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .prop("jdk.net.hosts.file", hostsFileName)
                 .prop("java.security.krb5.conf", OneKDC.KRB5_CONF)
                 .env("KRB5CCNAME", "ccache" + count)
                 .start();
@@ -114,10 +117,11 @@
     }
 
     static void checkKinitRenew() throws Exception {
+
         Proc p = Proc.create(clazz)
                 .args("-R")
                 .inheritIO()
-                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .prop("jdk.net.hosts.file", hostsFileName)
                 .prop("java.security.krb5.conf", OneKDC.KRB5_CONF)
                 .env("KRB5CCNAME", "ccache" + count)
                 .start();
--- a/test/sun/security/krb5/auto/SSLwithPerms.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/SSLwithPerms.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,19 +84,21 @@
             ).getBytes());
             fos.close();
 
+            String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+
             Proc pc = Proc.create("SSLwithPerms")
                     .args("client")
                     .inheritIO()
                     .prop("java.security.manager", "")
                     .prop("java.security.krb5.conf", KRB5_CONF)
-                    .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                    .prop("jdk.net.hosts.file", hostsFileName)
                     .prop("javax.net.ssl", "handshake")
                     .prop("sun.security.krb5.debug", "true")
                     .perm(new SecurityPermission("setProperty.jdk.tls.disabledAlgorithms"))
                     .perm(new PropertyPermission("sun.security.krb5.principal", "read"))
                     .perm(new FilePermission("port", "read"))
+                    .perm(new FilePermission(hostsFileName, "read"))
                     .perm(new FilePermission(KTAB, "read"))
-                    .perm(new RuntimePermission("accessClassInPackage.sun.net.spi.nameservice"))
                     .perm(new AuthPermission("modifyPrincipals"))
                     .perm(new AuthPermission("modifyPrivateCredentials"))
                     .perm(new AuthPermission("doAs"))
@@ -110,11 +112,13 @@
                     .prop("java.security.manager", "")
                     .prop("java.security.krb5.conf", KRB5_CONF)
                     .prop("java.security.auth.login.config", JAAS_CONF)
+                    .prop("jdk.net.hosts.file", hostsFileName)
                     .prop("javax.net.ssl", "handshake")
                     .prop("sun.security.krb5.debug", "true")
                     .perm(new SecurityPermission("setProperty.jdk.tls.disabledAlgorithms"))
                     .perm(new AuthPermission("createLoginContext.ssl"))
                     .perm(new AuthPermission("doAs"))
+                    .perm(new FilePermission(hostsFileName, "read"))
                     .perm(new FilePermission("port", "write"))
                     .perm(new SocketPermission("127.0.0.1", "accept"))
                     .perm(new ServicePermission("host/host.realm@REALM", "accept"))
--- a/test/sun/security/krb5/auto/TEST.properties	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/TEST.properties	Mon Apr 11 11:19:33 2016 -0700
@@ -1,6 +1,4 @@
 modules java.base/jdk.internal.misc \
-        java.base/sun.misc \
-        java.base/sun.net.spi.nameservice \
         java.base/sun.security.util \
         java.security.jgss/sun.security.jgss \
         java.security.jgss/sun.security.krb5 \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/TestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,16 @@
+127.0.0.1 host.rabbit.hole
+127.0.0.1 kdc.rabbit.hole
+127.0.0.1 kdc.snake.hole
+127.0.0.1 kdc.web.domain
+127.0.0.1 host.web.domain
+127.0.0.1 host.proxy.domain
+127.0.0.1 kdc.proxy.domain
+127.0.0.1 client.rabbit.hole
+127.0.0.1 localhost
+127.0.0.1 host.r3.local
+127.0.0.1 kdc.r1
+127.0.0.1 kdc.r2
+127.0.0.1 kdc.r3
+127.0.0.1 host.realm
+127.0.0.1 realm
+127.0.0.1 irlga09
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/principalProperty/TestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,1 @@
+127.0.0.1 localhost
--- a/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy	Mon Apr 11 11:19:33 2016 -0700
@@ -11,6 +11,7 @@
   	permission javax.security.auth.AuthPermission "modifyPrincipals";
   	permission javax.security.auth.AuthPermission "getSubject";
   	permission java.util.PropertyPermission "*", "read,write";
+  	permission java.io.FilePermission "/-", "read,write,delete";
   	permission java.io.FilePermission "*", "read,write,delete";
   	permission java.lang.RuntimePermission "accessDeclaredMembers";
   	permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
--- a/test/sun/security/krb5/auto/unbound.ssl.policy	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/auto/unbound.ssl.policy	Mon Apr 11 11:19:33 2016 -0700
@@ -1,6 +1,7 @@
 grant {
     permission java.util.PropertyPermission "*", "read,write";
     permission java.net.SocketPermission "*:*", "listen,resolve,accept,connect";
+    permission java.io.FilePermission "/-", "read";
     permission java.io.FilePermission "*", "read,write,delete";
     permission java.lang.RuntimePermission "accessDeclaredMembers";
     permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
--- a/test/sun/security/krb5/canonicalize/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Test
--- a/test/sun/security/krb5/canonicalize/Test.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/canonicalize/Test.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,20 +24,19 @@
  * @test
  * @bug 6682516
  * @summary SPNEGO_HTTP_AUTH/WWW_KRB and SPNEGO_HTTP_AUTH/WWW_SPNEGO failed on all non-windows platforms
- * @modules java.base/sun.net.spi.nameservice
- *          java.security.jgss/sun.security.krb5
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Djava.security.krb5.conf=krb5.conf Test
+ * @modules java.security.jgss/sun.security.krb5
+ * @run main/othervm  -Djava.security.krb5.conf=krb5.conf Test
  */
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import sun.net.spi.nameservice.NameService;
-import sun.net.spi.nameservice.NameServiceDescriptor;
 import sun.security.krb5.PrincipalName;
 
-public class Test implements NameServiceDescriptor {
+public class Test {
     public static void main(String[] args) throws Exception {
         // This config file is generated using Kerberos.app on a Mac
+        String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
         System.setProperty("java.security.krb5.realm", "THIS.REALM");
         System.setProperty("java.security.krb5.kdc", "localhost");
 
@@ -64,42 +63,4 @@
             throw new Exception("Output is " + pn);
         }
     }
-
-    @Override
-    public NameService createNameService() throws Exception {
-        NameService ns = new NameService() {
-            @Override
-            public InetAddress[] lookupAllHostAddr(String host)
-                    throws UnknownHostException {
-                // All c<n>.* goes to 127.0.0.n
-                int i = Integer.valueOf(host.split("\\.")[0].substring(1));
-                return new InetAddress[]{
-                    InetAddress.getByAddress(host, new byte[]{127,0,0,(byte)i})
-                };
             }
-            @Override
-            public String getHostByAddr(byte[] addr)
-                    throws UnknownHostException {
-                int i = addr[3];
-                switch (i) {
-                    case 1: return "c1.this.domain";        // Good
-                    case 2: return "127.0.0.2";             // Only IP
-                    case 3: return "d3.this.domain";        // name change
-                    default:
-                        throw new UnknownHostException();
-                }
-            }
-        };
-        return ns;
-    }
-
-    @Override
-    public String getProviderName() {
-        return "mock";
-    }
-
-    @Override
-    public String getType() {
-        return "ns";
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/canonicalize/TestHosts	Mon Apr 11 11:19:33 2016 -0700
@@ -0,0 +1,6 @@
+127.0.0.1 c1.this.domain
+127.0.0.1 c1
+127.0.0.2 127.0.0.2
+127.0.0.2 c2
+127.0.0.3 c3
+127.0.0.1 c1.this
--- a/test/sun/security/krb5/tools/ktcheck.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/krb5/tools/ktcheck.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -61,7 +61,8 @@
 EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf"
 KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f"
 CHECK="${TESTJAVA}${FS}bin${FS}java -cp ${TESTCLASSES} ${TESTVMOPTS} ${EXTRA_OPTIONS} \
-        -XaddExports:java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED,java.security.jgss/sun.security.krb5=ALL-UNNAMED \
+        -XaddExports:java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED \
+        -XaddExports:java.security.jgss/sun.security.krb5=ALL-UNNAMED \
         KtabCheck $KEYTAB"
 
 echo ${EXTRA_OPTIONS}
--- a/test/sun/security/pkcs/pkcs8/PKCS8Test.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/pkcs/pkcs8/PKCS8Test.java	Mon Apr 11 11:19:33 2016 -0700
@@ -30,7 +30,6 @@
  *          java.base/sun.security.util
  *          java.base/sun.security.provider
  *          java.base/sun.security.x509
- *          java.base/sun.misc
  * @compile -XDignore.symbol.file PKCS8Test.java
  * @run main PKCS8Test
  */
--- a/test/sun/security/pkcs/pkcs9/UnknownAttribute.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/pkcs/pkcs9/UnknownAttribute.java	Mon Apr 11 11:19:33 2016 -0700
@@ -25,8 +25,7 @@
  * @test
  * @bug 8011867
  * @summary Accept unknown PKCS #9 attributes
- * @modules java.base/sun.misc
- *          java.base/sun.security.pkcs
+ * @modules java.base/sun.security.pkcs
  *          java.base/sun.security.util
  */
 
--- a/test/sun/security/tools/jarsigner/TsacertOptionTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/tools/jarsigner/TsacertOptionTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -30,8 +30,7 @@
  * @bug 8024302 8026037
  * @summary The test signs and verifies a jar file with -tsacert option
  * @library /lib/testlibrary
- * @modules java.base/sun.misc
- *          java.base/sun.security.pkcs
+ * @modules java.base/sun.security.pkcs
  *          java.base/sun.security.timestamp
  *          java.base/sun.security.util
  *          java.base/sun.security.x509
--- a/test/sun/security/tools/jarsigner/ts.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/tools/jarsigner/ts.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -24,8 +24,7 @@
 # @test
 # @bug 6543842 6543440 6939248 8009636 8024302
 # @summary checking response of timestamp
-# @modules java.base/sun.misc
-#          java.base/sun.security.pkcs
+# @modules java.base/sun.security.pkcs
 #          java.base/sun.security.timestamp
 #          java.base/sun.security.x509
 #          java.base/sun.security.util
@@ -95,7 +94,10 @@
         $KT -alias ca -gencert -ext eku:critical=cs | \
         $KT -alias tsbad3 -importcert
 
-EXTRAOPTS="-XaddExports:java.base/sun.misc=ALL-UNNAMED,java.base/sun.security.pkcs=ALL-UNNAMED,java.base/sun.security.timestamp=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED"
+EXTRAOPTS="-XaddExports:java.base/sun.security.pkcs=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.timestamp=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.x509=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.util=ALL-UNNAMED"
 $JAVAC ${EXTRAOPTS} -d . ${TESTSRC}/TimestampCheck.java
 $JAVA ${TESTVMOPTS} ${EXTRAOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck
 
--- a/test/sun/security/tools/keytool/autotest.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/tools/keytool/autotest.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -100,7 +100,9 @@
 
 echo "Using NSS lib at $LIBNAME"
 
-EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED"
+EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.x509=ALL-UNNAMED"
 
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
         ${TESTSRC}${FS}KeyToolTest.java || exit 10
--- a/test/sun/security/tools/keytool/standard.sh	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/tools/keytool/standard.sh	Mon Apr 11 11:19:33 2016 -0700
@@ -57,7 +57,9 @@
     ;;
 esac
 
-EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED"
+EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+ -XaddExports:java.base/sun.security.x509=ALL-UNNAMED"
 
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
 
--- a/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java	Mon Apr 11 11:19:33 2016 -0700
@@ -44,14 +44,11 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
-import sun.net.spi.nameservice.NameService;
-import sun.net.spi.nameservice.NameServiceDescriptor;
 
 /*
  * @test
  * @bug 8134708
  * @summary Check if LDAP resources from CRLDP and AIA extensions can be loaded
- * @modules java.base/sun.net.spi.nameservice
  * @run main/othervm ExtensionsWithLDAP
  */
 public class ExtensionsWithLDAP {
@@ -149,7 +146,8 @@
         System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
 
         // register a local name service
-        System.setProperty("sun.net.spi.nameservice.provider.1", "ns,localdns");
+        String hostsFileName = System.getProperty("test.src", ".") + "/ExtensionsWithLDAPHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
 
         X509Certificate trustedCert = loadCertificate(CA_CERT);
         X509Certificate eeCert = loadCertificate(EE_CERT);
@@ -201,48 +199,8 @@
     }
 
     // a local name service which log requested host names
-    public static class LocalNameService implements NameServiceDescriptor {
+    public static class LocalNameService {
 
         static final List<String> requestedHosts = new ArrayList<>();
-
-        @Override
-        public NameService createNameService() throws Exception {
-            System.out.println("LocalNameService: createNameService() called");
-            NameService ns = new NameService() {
-
-                @Override
-                public InetAddress[] lookupAllHostAddr(String host)
-                        throws UnknownHostException {
-
-                    System.out.println("LocalNameService: "
-                            + "NameService.lookupAllHostAddr(): " + host);
-
-                    requestedHosts.add(host);
-
-                    throw new UnknownHostException();
                 }
-
-                @Override
-                public String getHostByAddr(byte[] addr)
-                        throws UnknownHostException {
-                    System.out.println("LocalNameService: "
-                            + "NameService.getHostByAddr(): "
-                            + Arrays.toString(addr));
-                    throw new UnknownHostException("No reverse lookup");
                 }
-            };
-            return ns;
-        }
-
-        @Override
-        public String getProviderName() {
-            return "localdns";
-        }
-
-        @Override
-        public String getType() {
-            return "ns";
-        }
-    }
-
-}
--- a/test/sun/security/x509/URICertStore/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor	Mon Apr 11 21:07:34 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-ExtensionsWithLDAP$LocalNameService
--- a/test/sun/security/x509/X500Name/NullX500Name.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/sun/security/x509/X500Name/NullX500Name.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,8 +24,7 @@
 /* @test
  * @bug 4118818
  * @summary allow null X.500 Names
- * @modules java.base/sun.misc
- *          java.base/sun.security.util
+ * @modules java.base/sun.security.util
  *          java.base/sun.security.x509
  */
 
--- a/test/tools/jimage/VerifyJimage.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/jimage/VerifyJimage.java	Mon Apr 11 11:19:33 2016 -0700
@@ -49,6 +49,7 @@
  * @test
  * @summary Verify jimage
  * @modules java.base/jdk.internal.jimage
+ * @run main/othervm -Djdk.launcher.addmods=ALL-SYSTEM VerifyJimage
  */
 
 /**
--- a/test/tools/launcher/modules/addexports/AddExportsTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/launcher/modules/addexports/AddExportsTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -71,7 +71,7 @@
         boolean compiled = CompilerUtils.compile(
                 SRC_DIR.resolve(TEST1_MODULE),
                 MODS_DIR.resolve(TEST1_MODULE),
-                "-XaddExports:java.base/sun.misc=m1");
+                "-XaddExports:java.base/jdk.internal.misc=m1");
         assertTrue(compiled, "module " + TEST1_MODULE + " did not compile");
 
         // javac -d upgrademods/java.transaction src/java.transaction/**
@@ -118,16 +118,16 @@
 
 
     /**
-     * Run class path application that uses sun.misc.Unsafe
+     * Run class path application that uses jdk.internal.misc.Unsafe
      */
     public void testUnnamedModule() throws Exception {
 
-        // java -XaddExports:java.base/sun.misc=ALL-UNNAMED \
+        // java -XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED \
         //      -cp mods/$TESTMODULE jdk.test.UsesUnsafe
 
         String classpath = MODS_DIR.resolve(TEST1_MODULE).toString();
         int exitValue
-            = executeTestJava("-XaddExports:java.base/sun.misc=ALL-UNNAMED",
+            = executeTestJava("-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
                               "-cp", classpath,
                               TEST1_MAIN_CLASS)
                 .outputTo(System.out)
@@ -139,16 +139,16 @@
 
 
     /**
-     * Run named module that uses sun.misc.Unsafe
+     * Run named module that uses jdk.internal.misc.Unsafe
      */
     public void testNamedModule() throws Exception {
 
-        //  java -XaddExports:java.base/sun.misc=test \
+        //  java -XaddExports:java.base/jdk.internal.misc=test \
         //       -mp mods -m $TESTMODULE/$MAIN_CLASS
 
         String mid = TEST1_MODULE + "/" + TEST1_MAIN_CLASS;
         int exitValue =
-            executeTestJava("-XaddExports:java.base/sun.misc=" + TEST1_MODULE,
+            executeTestJava("-XaddExports:java.base/jdk.internal.misc=" + TEST1_MODULE,
                             "-mp", MODS_DIR.toString(),
                             "-m", mid)
                 .outputTo(System.out)
@@ -240,13 +240,13 @@
     public Object[][] badValues() {
         return new Object[][]{
 
-            { "java.base/sun.misc",                  null }, // missing target
-            { "java.base/sun.misc=sun.monkey",       null }, // unknown target
-            { "java.monkey/sun.monkey=ALL-UNNAMED",  null }, // unknown module
-            { "java.base/sun.monkey=ALL-UNNAMED",    null }, // unknown package
-            { "java.monkey/sun.monkey=ALL-UNNAMED",  null }, // unknown module/package
-            { "java.base=ALL-UNNAMED",               null }, // missing package
-            { "java.base/=ALL-UNNAMED",              null }  // missing package
+            { "java.base/jdk.internal.misc",            null }, // missing target
+            { "java.base/jdk.internal.misc=sun.monkey", null }, // unknown target
+            { "java.monkey/sun.monkey=ALL-UNNAMED",     null }, // unknown module
+            { "java.base/sun.monkey=ALL-UNNAMED",       null }, // unknown package
+            { "java.monkey/sun.monkey=ALL-UNNAMED",     null }, // unknown module/package
+            { "java.base=ALL-UNNAMED",                  null }, // missing package
+            { "java.base/=ALL-UNNAMED",                 null }  // missing package
 
         };
     }
--- a/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java	Mon Apr 11 11:19:33 2016 -0700
@@ -24,7 +24,7 @@
 package jdk.test1;
 
 import java.lang.reflect.Field;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class Main {
     public static void main(String[] args) throws Exception {
--- a/test/tools/launcher/modules/limitmods/LimitModsTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/launcher/modules/limitmods/LimitModsTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -103,9 +103,10 @@
     public void testWithAddMods() throws Exception {
         int exitValue;
 
-        // java -limitmods java.base -addmods java.logging -listmods
+        // java -limitmods java.base -addmods java.logging,jdk.unsupported -listmods
         exitValue = executeTestJava("-limitmods", "java.base",
-                                    "-addmods", "java.logging",
+                                    "-addmods",
+                                    "java.logging,jdk.unsupported",  // TODO: add bug No.
                                     "-listmods")
             .outputTo(System.out)
             .errorTo(System.out)
--- a/test/tools/launcher/modules/patch/PatchTest.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/launcher/modules/patch/PatchTest.java	Mon Apr 11 11:19:33 2016 -0700
@@ -128,18 +128,15 @@
         // value for -Xpatch
         String patchPath = PATCHES1_DIR + File.pathSeparator + PATCHES2_DIR;
 
-        // value for -XaddExports
-        String addExportsValue = "java.base/java.lang2=test"
-                + ",jdk.naming.dns/com.sun.jndi.dns=test"
-                + ",jdk.naming.dns/com.sun.jndi.dns2=test"
-                + ",jdk.compiler/com.sun.tools.javac2=test";
-
         // the argument to the test is the list of classes overridden or added
         String arg = Stream.of(CLASSES).collect(Collectors.joining(","));
 
         int exitValue
             =  executeTestJava("-Xpatch:" + patchPath,
-                               "-XaddExports:" + addExportsValue,
+                               "-XaddExports:java.base/java.lang2=test",
+                               "-XaddExports:jdk.naming.dns/com.sun.jndi.dns=test",
+                               "-XaddExports:jdk.naming.dns/com.sun.jndi.dns2=test",
+                               "-XaddExports:jdk.compiler/com.sun.tools.javac2=test",
                                "-addmods", "jdk.naming.dns,jdk.compiler",
                                "-mp", MODS_DIR.toString(),
                                "-m", "test/jdk.test.Main", arg)
--- a/test/tools/pack200/ModuleAttributes.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/pack200/ModuleAttributes.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,38 +39,10 @@
     }
 
     public void run() throws Exception {
-        File file = createModuleJar();
+        File file = Utils.createRtJar(".*module-info\\.class");
         Utils.testWithRepack(file,
                 "--effort=1",
                 "--unknown-attribute=error");
-    }
-
-    File createModuleJar() throws IOException {
-        File libDir = new File(Utils.JavaHome, "lib");
-        File modules = new File(libDir, "modules");
-        File outDir = new File("out");
-
-        List<String> cmdList = new ArrayList<>();
-        cmdList.add(Utils.getJimageCmd());
-        cmdList.add("extract");
-        cmdList.add(modules.getAbsolutePath());
-        cmdList.add("--dir");
-        cmdList.add(outDir.getName());
-        Utils.runExec(cmdList);
-
-        FileFilter filter = (File file) -> file.getName().equals("module-info.class");
-        List<File> mfiles = Utils.findFiles(outDir, filter);
-
-        List<String> contents = new ArrayList<>(mfiles.size());
-        mfiles.stream().forEach((f) -> {
-            contents.add(f.getAbsolutePath());
-        });
-
-        File listFile = new File("mfiles.list");
-        Utils.createFile(listFile, contents);
-        File testFile = new File("test.jar");
-        Utils.jar("cvf", testFile.getName(), "@" + listFile.getName());
-        Utils.recursiveDelete(outDir);
-        return testFile;
+        Utils.cleanup();
     }
 }
--- a/test/tools/pack200/Pack200Props.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/pack200/Pack200Props.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,13 +31,13 @@
  */
 
 import java.io.File;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.jar.Pack200;
 import java.util.jar.Pack200.Packer;
+import java.util.logging.Logger;
 
 /*
  * Run this against a large jar file, by default the packer should generate only
@@ -46,20 +46,22 @@
 
 public class Pack200Props {
 
-    public static void main(String... args) throws IOException {
+    final static Logger log = Logger.getLogger("Pack200Props");
+
+    public static void main(String... args) throws Exception {
         verifyDefaults();
         File out = new File("test" + Utils.PACK_FILE_EXT);
         out.delete();
         verifySegmentLimit(out);
+        log.info("cleanup");
         Utils.cleanup();
     }
 
-    static void verifySegmentLimit(File outFile) throws IOException {
-        File sdkHome = Utils.JavaSDK;
+    static void verifySegmentLimit(File outFile) throws Exception {
+        log.info("creating jar");
         File testJar = Utils.createRtJar();
 
-        System.out.println("using pack200: " + Utils.getPack200Cmd());
-
+        log.info("using pack200: " + Utils.getPack200Cmd());
         List<String> cmdsList = new ArrayList<>();
         cmdsList.add(Utils.getPack200Cmd());
         cmdsList.add("-J-Xshare:off");
@@ -71,6 +73,7 @@
         cmdsList.add(testJar.getAbsolutePath());
         List<String> outList = Utils.runExec(cmdsList);
 
+        log.info("verifying");
         int count = 0;
         for (String line : outList) {
             System.out.println(line);
@@ -78,6 +81,7 @@
                 count++;
             }
         }
+        log.info("fini");
         if (count == 0) {
             throw new RuntimeException("no segments or no output ????");
         } else if (count > 1) {
@@ -86,6 +90,7 @@
     }
 
     private static void verifyDefaults() {
+        log.info("start");
         Map<String, String> expectedDefaults = new HashMap<>();
         Packer p = Pack200.newPacker();
         expectedDefaults.put("com.sun.java.util.jar.pack.disable.native",
@@ -121,6 +126,7 @@
                 }
             }
         }
+        log.info("fini");
         if (errors > 0) {
             throw new RuntimeException(errors +
                     " error(s) encountered in default properties verification");
--- a/test/tools/pack200/PackChecksum.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/pack200/PackChecksum.java	Mon Apr 11 11:19:33 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,65 +31,136 @@
 
 /*
  * @test
- * @bug 8000650
+ * @bug 8000650 8150469
  * @summary unpack200.exe should check gzip crc
  * @compile -XDignore.symbol.file Utils.java PackChecksum.java
  * @run main PackChecksum
  * @author kizune
  */
 public class PackChecksum {
+    final int TRAILER_LEN = 8;
+    final List<String> cmdsList = new ArrayList<>();
+    static enum Case {
+        CRC32,
+        ISIZE,
+        BOTH;
 
+    };
     public static void main(String... args) throws Exception {
-        testChecksum();
+        new PackChecksum().run();
+    }
+    void run() throws Exception {
+        testBrokenTrailer(Case.CRC32); // negative
+        testBrokenTrailer(Case.ISIZE); // negative
+        testBrokenTrailer(Case.BOTH);  // negative
+        testMultipleSegments();
     }
 
-    static void testChecksum() throws Exception {
+    void testMultipleSegments() throws Exception {
+        File inputJar = new File("input.jar");
+        Utils.copyFile(Utils.getGoldenJar(), inputJar);
+        cmdsList.clear();
+
+        File testPack = new File("out.jar.pack.gz");
+
+        cmdsList.clear();
+        cmdsList.add(Utils.getPack200Cmd());
+        // force multiple segments
+        cmdsList.add("--segment-limit=100");
+        cmdsList.add(testPack.getName());
+        cmdsList.add(inputJar.getName());
+        Utils.runExec(cmdsList);
 
+        File destFile = new File("dst.jar");
+        cmdsList.clear();
+        cmdsList.add(Utils.getUnpack200Cmd());
+        cmdsList.add(testPack.getName());
+        cmdsList.add(destFile.getName());
+        try {
+            Utils.runExec(cmdsList);
+            if (!destFile.exists()) {
+                throw new Exception("file not created: " + destFile);
+            }
+        } finally {
+            if (inputJar.exists())
+                inputJar.delete();
+            if (testPack.exists())
+                testPack.delete();
+            if (destFile.exists())
+                destFile.delete();
+        }
+    }
+
+    void testBrokenTrailer(Case type) throws Exception {
+        System.out.println("Testing: case " + type);
         // Create a fresh .jar file
         File testFile = new File("src_tools.jar");
         File testPack = new File("src_tools.pack.gz");
         generateJar(testFile);
-        List<String> cmdsList = new ArrayList<>();
 
+        cmdsList.clear();
         // Create .pack file
         cmdsList.add(Utils.getPack200Cmd());
         cmdsList.add(testPack.getName());
         cmdsList.add(testFile.getName());
         Utils.runExec(cmdsList);
 
-        // Mess up with the checksum of the packed file
+        // mutate the checksum of the packed file
         RandomAccessFile raf = new RandomAccessFile(testPack, "rw");
-        raf.seek(raf.length() - 8);
-        int val = raf.readInt();
-        val = Integer.MAX_VALUE - val;
-        raf.seek(raf.length() - 8);
-        raf.writeInt(val);
+
+        switch (type) {
+            case CRC32:
+                raf.seek(raf.length() - TRAILER_LEN);
+                raf.writeInt(0x0dea0a0d);
+                break;
+            case ISIZE:
+                raf.seek(raf.length() - (TRAILER_LEN/2));
+                raf.writeInt(0x0b0e0e0f);
+                break;
+            default:
+                raf.seek(raf.length() - (TRAILER_LEN));
+                raf.writeLong(0x0dea0a0d0b0e0e0fL);
+                break;
+        }
+
         raf.close();
 
         File dstFile = new File("dst_tools.jar");
+        if (dstFile.exists()) {
+            dstFile.delete();
+        }
         cmdsList.clear();
         cmdsList.add(Utils.getUnpack200Cmd());
         cmdsList.add(testPack.getName());
         cmdsList.add(dstFile.getName());
 
-        boolean passed = false;
+        boolean processFailed = false;
         try {
             Utils.runExec(cmdsList);
         } catch (RuntimeException re) {
             // unpack200 should exit with non-zero exit code
-            passed = true;
-        }
+            processFailed = true;
+        } finally {
+            // tidy up
+            if (testFile.exists())
+                testFile.delete();
+
+            if (testPack.exists())
+                testPack.delete();
 
-        // tidy up
-        if (testFile.exists()) testFile.delete();
-        if (testPack.exists()) testPack.delete();
-        if (dstFile.exists()) dstFile.delete();
-        if (!passed) {
-            throw new Exception("File with incorrect CRC unpacked without the error.");
+            if (!processFailed) {
+                throw new Exception("case " + type +
+                        ": file with incorrect CRC, unpacked without the error.");
+            }
+            if (dstFile.exists()) {
+                dstFile.delete();
+                throw new Exception("case " + type +
+                        ":  file exists: " + dstFile);
+            }
         }
     }
 
-    static void generateJar(File result) throws IOException {
+    void generateJar(File result) throws IOException {
         if (result.exists()) {
             result.delete();
         }
--- a/test/tools/pack200/Utils.java	Mon Apr 11 21:07:34 2016 +0300
+++ b/test/tools/pack200/Utils.java	Mon Apr 11 11:19:33 2016 -0700
@@ -32,22 +32,33 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.PrintStream;
+import java.net.URI;
+import java.net.URL;
 import java.nio.charset.Charset;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Pack200;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import static java.nio.file.StandardCopyOption.*;
 import static java.nio.file.StandardOpenOption.*;
 
+
 /**
  *
  * @author ksrini
@@ -544,10 +555,6 @@
         return getAjavaCmd("jar");
     }
 
-    static String getJimageCmd() {
-        return getAjavaCmd("jimage");
-    }
-
     static String getAjavaCmd(String cmdStr) {
         File binDir = new File(JavaHome, "bin");
         File unpack200File = IsWindows
@@ -562,29 +569,88 @@
         return cmd;
     }
 
-    static File createRtJar() throws IOException {
-        File libDir = new File(JavaHome, "lib");
-        File modules = new File(libDir, "modules");
-        List<String> cmdList = new ArrayList<>();
-        cmdList.add(getJimageCmd());
-        cmdList.add("extract");
-        cmdList.add(modules.getAbsolutePath());
-        cmdList.add("--dir");
-        cmdList.add("out");
-        runExec(cmdList);
-
+    // used to get all classes
+    static File createRtJar() throws Exception {
         File rtJar = new File("rt.jar");
-        cmdList.clear();
-        cmdList.add(getJarCmd());
-        // cmdList.add("cvf"); too noisy
-        cmdList.add("cf");
-        cmdList.add(rtJar.getName());
-        cmdList.add("-C");
-        cmdList.add("out");
-        cmdList.add(".");
-        runExec(cmdList);
+        new JrtToZip(".*\\.class", rtJar).run();
+        return rtJar;
+    }
 
-        recursiveDelete(new File("out"));
+    // used to select the contents
+    static File createRtJar(String pattern) throws Exception {
+        File rtJar = new File("rt.jar");
+        new JrtToZip(pattern, rtJar).run();
         return rtJar;
     }
+
+    /*
+     * A helper class to create a pseudo rt.jar.
+     */
+    static class JrtToZip {
+
+        final File outFile;
+        final Pattern pattern;
+
+        public static void main(String[] args) throws Exception {
+            new JrtToZip(args[0], new File(args[1])).run();
+        }
+
+        JrtToZip(String pattern, File outFile) throws Exception {
+            this.pattern = Pattern.compile(pattern);
+            this.outFile = outFile;
+        }
+
+        void run() throws Exception {
+            URI uri = URI.create("jar:" + outFile.toURI());
+            Map<String, String> env = new HashMap<>();
+            env.put("create", "true");
+            try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
+                toZipfs(zipfs);
+            }
+        }
+
+        void toZipfs(FileSystem zipfs) throws Exception {
+            FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
+            for (Path root : jrtfs.getRootDirectories()) {
+                Files.walkFileTree(root, new FileVisitor<Path>() {
+                    @Override
+                    public FileVisitResult preVisitDirectory(Path dir,
+                            BasicFileAttributes attrs) throws IOException {
+                        // ignore unneeded directory
+                        if (dir.startsWith("/packages"))
+                            return FileVisitResult.SKIP_SUBTREE;
+
+                        // pre-create required directories
+                        Path zpath = zipfs.getPath(dir.toString());
+                        Files.createDirectories(zpath);
+                        return FileVisitResult.CONTINUE;
+                    }
+
+                    @Override
+                    public FileVisitResult visitFile(Path file,
+                            BasicFileAttributes attrs) throws IOException {
+                        Matcher matcher = pattern.matcher(file.toString());
+                        if (matcher.matches()) {
+                            // System.out.println("x: " + file);
+                            Path zpath = zipfs.getPath(file.toString());
+                            Files.copy(file, zpath, REPLACE_EXISTING);
+                        }
+                        return FileVisitResult.CONTINUE;
+                    }
+
+                    @Override
+                    public FileVisitResult visitFileFailed(Path file,
+                            IOException exc) throws IOException {
+                        return FileVisitResult.CONTINUE;
+                    }
+
+                    @Override
+                    public FileVisitResult postVisitDirectory(Path dir,
+                            IOException exc) throws IOException {
+                        return FileVisitResult.CONTINUE;
+                    }
+                });
+            }
+        }
+    }
 }