changeset 14242:b37554a7984d

Merge
author ddehaven
date Mon, 11 Apr 2016 11:19:33 -0700
parents 061cb940b183 bb8379287f37
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);
+            return Objects.equals(reverseProxyCache.sub(c).get(c.getClassLoader()),
+                                  Boolean.TRUE);
         }
 
-        /**
-         * 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);
-        }
-
-        /**
-         * 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);
         }
-    }
 
-    /**
-     * 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;
+        // ProxyBuilder instance members start here....
+
+        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 {
 
-    private static NameService createNSProvider(String provider) {
-        if (provider == null)
-            return null;
+        /**
+         * 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;
 
-        NameService nameService = null;
-        if (provider.equals("default")) {
-            // initialize the default name service
-            nameService = new NameService() {
+        /**
+         * 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;
+
+    }
+
+    /**
+     * 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);
+
+        }
+
+    }
+
+    /**
+     * 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);
                 }
-                public String getHostByAddr(byte[] addr)
-                    throws UnknownHostException {
-                    return impl.getHostByAddr(addr);
+            }
+            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;
+                            }
+                        }
+                    }
                 }
-            };
-        } 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);
-                                    }
+            } 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;
         }
 
-        return nameService;
+        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;
+        }
+
+        /** 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);
         DateFormatSymbo