changeset 1559:c8e1ede2e7ad

Merge
author lana
date Wed, 02 Dec 2015 09:37:26 -0800
parents 9d52f9bb589c a1ef259a183f
children 5401b88e6ec6
files make/BuildNashorn.gmk make/build.xml samples/Main.class src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NamedOperation.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NoSuchDynamicMethodException.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/Operation.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/StandardOperation.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AccessibleMembersLookup.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanIntrospector.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CheckRestrictedPackage.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethodLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/GuardedInvocationComponent.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassIntrospector.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/messages.properties src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package-info.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/AccessControlContextFactory.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/InternalTypeUtilities.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocationTransformer.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinkerExporter.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodHandleTransformer.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package-info.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeGuardingDynamicLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/DefaultInternalObjectFilter.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Guards.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Lookup.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/SimpleLinkRequest.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/TypeUtilities.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/package-info.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package-info.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ChainedCallSite.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleRelinkableCallSite.java src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/messages.properties src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package-info.java test/script/basic/JDK-8059934.js
diffstat 220 files changed, 16466 insertions(+), 14054 deletions(-) [+]
line wrap: on
line diff
--- a/make/BuildNashorn.gmk	Sun Nov 29 20:30:01 2015 -0800
+++ b/make/BuildNashorn.gmk	Wed Dec 02 09:37:26 2015 -0800
@@ -34,7 +34,7 @@
 include TextFileProcessing.gmk
 
 JDK_CLASSES := $(call PathList, $(strip $(addprefix $(JDK_OUTPUTDIR)/modules/, \
-      java.base java.logging java.scripting)))
+      java.base java.logging java.scripting jdk.dynalink)))
 
 NASHORN_JAR := $(IMAGES_OUTPUTDIR)/nashorn.jar
 
--- a/make/build.xml	Sun Nov 29 20:30:01 2015 -0800
+++ b/make/build.xml	Wed Dec 02 09:37:26 2015 -0800
@@ -52,6 +52,14 @@
     <available property="testng.already.present" file="${file.reference.testng.jar}"/>
     <antcall target="get-testng"/>
     <available property="testng.available" file="${file.reference.testng.jar}"/>
+
+    <!-- check if asmtools-6.0.jar is avaiable, and download it if it isn't -->
+    <!--
+    <available property="asmtools.already.present" file="${file.reference.asmtools.jar}"/>
+    <antcall target="get-asmtools"/>
+    <available property="asmtools.available" file="${file.reference.asmtools.jar}"/>
+    -->
+
     <!-- check if Jemmy ang testng.jar are avaiable -->
     <condition property="jemmy.jfx.testng.available" value="true">
       <and>
@@ -155,7 +163,7 @@
     <copy todir="${build.classes.dir}/jdk/nashorn/tools/resources">
        <fileset dir="${nashorn.module.src.dir}/jdk/nashorn/tools/resources/"/>
     </copy>
-    <copy file="${nashorn.module.src.dir}/jdk/internal/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/internal/dynalink/support"/>
+    <copy file="${dynalink.module.src.dir}/jdk/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/dynalink/support"/>
     <copy file="${nashorn.module.src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${build.classes.dir}/jdk/nashorn/internal/codegen"/>
 
     <echo message="version_string=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
@@ -244,6 +252,7 @@
       <classpath>
         <pathelement location="${build.classes.dir}"/>
       </classpath>
+      <fileset dir="${dynalink.module.src.dir}" includes="**/*.java"/>
       <fileset dir="${nashorn.module.src.dir}" includes="**/*.java"/>
       <fileset dir="${nashorn.shell.module.src.dir}" includes="**/*.java"/>
       <link href="http://docs.oracle.com/javase/8/docs/api/"/>
@@ -263,6 +272,18 @@
     </javadoc>
   </target>
 
+  <!-- generate javadoc only for Dynalink API classes -->
+  <target name="dynalinkapi" depends="jar">
+    <javadoc destdir="${dist.javadoc.dir}" use="yes"
+        windowtitle="Dynalink"
+        additionalparam="-quiet" failonerror="true" useexternalfile="true">
+      <classpath>
+        <pathelement location="${build.classes.dir}"/>
+      </classpath>
+      <fileset dir="${dynalink.module.src.dir}" includes="**/*.java" excludes="jdk/dynalink/internal/*.java"/>
+      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+    </javadoc>
+  </target>
 
   <!-- generate shell.html for shell tool documentation -->
   <target name="shelldoc" depends="jar">
@@ -321,14 +342,20 @@
 
     <!-- tests that check nashorn internals and internal API -->
     <jar jarfile="${nashorn.internal.tests.jar}">
-      <fileset dir="${build.test.classes.dir}" excludes="**/api/**"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/internal/**"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/test/tools/**"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/models/**"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/jdk/dynalink/test/Trusted**"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/META-INF/**"/>
     </jar>
 
-    <!-- tests that check nashorn script engine (jsr-223) API -->
+    <!-- tests that check nashorn script engine (jsr-223) API and dynalink API -->
     <jar jarfile="${nashorn.api.tests.jar}">
+      <fileset dir="${build.test.classes.dir}" includes="**/jdk/dynalink/**" excludes="**/jdk/dynalink/test/Trusted**"/>
       <fileset dir="${build.test.classes.dir}" includes="**/api/**"/>
       <fileset dir="${build.test.classes.dir}" includes="**/META-INF/**"/>
       <fileset dir="${build.test.classes.dir}" includes="**/resources/*.js"/>
+      <fileset dir="${build.test.classes.dir}" includes="**/UnnamedPackage**"/>
     </jar>
 
   </target>
@@ -432,6 +459,8 @@
   <!-- only to be invoked as dependency of "test" target -->
   <target name="-test-classes-all" depends="jar" unless="test.class">
       <fileset id="test.classes" dir="${build.test.classes.dir}">
+          <include name="**/dynalink/test/*Test.class"/>
+          <include name="**/dynalink/beans/test/*Test.class"/>
           <include name="**/api/javaaccess/test/*Test.class"/>
           <include name="**/api/scripting/test/*Test.class"/>
           <include name="**/api/tree/test/*Test.class"/>
@@ -603,7 +632,7 @@
 
   <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <!-- use just build.test.classes.dir to avoid referring to TestNG -->
-    <java classname="${parallel.test.runner}" dir="${basedir}" fork="true">
+    <java classname="${parallel.test.runner}" dir="${basedir}" fork="true" failonerror="true">
       <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <!-- avoid too many typeinfo cache files. Each script is run only once anyway -->
@@ -773,6 +802,20 @@
     <delete dir="${test.lib}${file.separator}testng-6.8"/>
   </target>
 
+  <!-- download and install asmtools.jar -->
+  <target name="get-asmtools" unless="asmtools.already.present">
+    <get src="https://adopt-openjdk.ci.cloudbees.com/view/OpenJDK/job/asmtools/lastSuccessfulBuild/artifact/asmtools-6.0.tar.gz" dest="${test.lib}" skipexisting="true" ignoreerrors="true"/>
+    <untar src="${test.lib}${file.separator}asmtools-6.0.tar.gz" dest="${test.lib}" compression="gzip"/>
+    <!-- they are tar.gz'ing a .zip file! -->
+    <unzip src="${test.lib}${file.separator}asmtools-6.0.zip" dest="${test.lib}">
+      <patternset>
+        <include name="asmtools-6.0/lib/asmtools.jar"/>
+      </patternset>
+    </unzip>
+    <move file="${test.lib}${file.separator}asmtools-6.0${file.separator}lib${file.separator}asmtools.jar" tofile="${test.lib}${file.separator}asmtools.jar"/>
+    <delete dir="${test.lib}${file.separator}asmtools-6.0"/>
+  </target>
+
   <!-- run all tests -->
   <target name="alltests" depends="externals, update-externals, test, test262parallel, testmarkdown, perf"/>
 
--- a/make/nbproject/project.xml	Sun Nov 29 20:30:01 2015 -0800
+++ b/make/nbproject/project.xml	Wed Dec 02 09:37:26 2015 -0800
@@ -50,6 +50,10 @@
                     <location>../src/jdk.scripting.nashorn/share/classes</location>
                 </source-folder>
                 <source-folder>
+                    <label>../src/jdk.scripting.nashorn.shell/share/classes</label>
+                    <location>../src/jdk.scripting.nashorn.shell/share/classes</location>
+                </source-folder>
+                <source-folder>
                     <label>../test/src</label>
                     <type>java</type>
                     <location>../test/src</location>
@@ -74,8 +78,14 @@
                     <encoding>UTF-8</encoding>
                 </source-folder>
                 <source-folder>
-                    <label>../src/jdk.scripting.nashorn.shell/share/classes</label>
-                    <location>../src/jdk.scripting.nashorn.shell/share/classes</location>
+                    <label>../src/jdk.dynalink/share/classes</label>
+                    <type>java</type>
+                    <location>../src/jdk.dynalink/share/classes</location>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
+                <source-folder>
+                    <label>../src/jdk.dynalink/share/classes</label>
+                    <location>../src/jdk.dynalink/share/classes</location>
                 </source-folder>
             </folders>
             <ide-actions>
@@ -153,6 +163,10 @@
                         <label>../src/jdk.scripting.nashorn.shell/share/classes</label>
                         <location>../src/jdk.scripting.nashorn.shell/share/classes</location>
                     </source-folder>
+                    <source-folder style="packages">
+                        <label>../src/jdk.dynalink/share/classes</label>
+                        <location>../src/jdk.dynalink/share/classes</location>
+                    </source-folder>
                     <source-file>
                         <location>build.xml</location>
                     </source-file>
@@ -189,6 +203,10 @@
                 <package-root>../src/jdk.scripting.nashorn.shell/share/classes</package-root>
                 <source-level>1.8</source-level>
             </compilation-unit>
+            <compilation-unit>
+                <package-root>../src/jdk.dynalink/share/classes</package-root>
+                <source-level>1.8</source-level>
+            </compilation-unit>
         </java-data>
     </configuration>
 </project>
--- a/make/project.properties	Sun Nov 29 20:30:01 2015 -0800
+++ b/make/project.properties	Wed Dec 02 09:37:26 2015 -0800
@@ -85,6 +85,7 @@
 
 # jars refererred
 file.reference.testng.jar=${test.lib}${file.separator}testng.jar
+file.reference.asmtools.jar=${test.lib}${file.separator}asmtools-60.jar
 
 # Set testng verbose level
 # From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed)
@@ -211,6 +212,12 @@
 # file containing test262 tests to be excluded
 # test262-test-sys-prop.test.js.excludes.file=${test262.dir}/test/config/excludelist.xml
 
+# list of test262 files to be excluded
+test262-test-sys-prop.test.js.exclude.list=\
+    ${test262.suite.dir}/ch07/7.4/S7.4_A6.js \
+    ${test262.suite.dir}/ch07/7.8/7.8.5/S7.8.5_A1.4_T2.js \
+    ${test262.suite.dir}/ch15/15.2/15.2.3/15.2.3.6/15.2.3.6-4-170.js 
+
 # list of test262 test dirs to be excluded
 test262-test-sys-prop.test.js.exclude.dir=\
     ${test262.suite.dir}/intl402/ \
@@ -269,10 +276,12 @@
     ${nashorn.internal.tests.jar}${path.separator}\
     ${nashorn.api.tests.jar}
 
+dynalink.module.src.dir=src/jdk.dynalink/share/classes
 nashorn.module.src.dir=src/jdk.scripting.nashorn/share/classes
 nashorn.shell.module.src.dir=src/jdk.scripting.nashorn.shell/share/classes
 
-src.dir=${nashorn.module.src.dir}${path.separator}\
+src.dir=${dynalink.module.src.dir}${path.separator}\
+        ${nashorn.module.src.dir}${path.separator}\
         ${nashorn.shell.module.src.dir}${path.separator}\
         ${jdk.jline.src.dir}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/DOMLinkerExporter.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.Guards;
+import jdk.dynalink.linker.support.Lookup;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+/**
+ * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
+ * This linker handles XML DOM Element objects specially. This linker links
+ * special properties starting with "_" and treats those as child element names
+ * to access. This kind of child element access makes it easy to write XML DOM
+ * accessing scripts. See for example ./dom_linker_gutenberg.js.
+ */
+public final class DOMLinkerExporter extends GuardingDynamicLinkerExporter {
+    static {
+        System.out.println("pluggable dynalink DOM linker loaded");
+    }
+
+    // return List of child Elements of the given Element matching the given name.
+    private static List<Element> getChildElements(Element elem, String name) {
+        NodeList nodeList = elem.getChildNodes();
+        List<Element> childElems = new ArrayList<>();
+        int len = nodeList.getLength();
+        for (int i = 0; i < len; i++) {
+            Node node = nodeList.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE &&
+                ((Element)node).getTagName().equals(name)) {
+                childElems.add((Element)node);
+            }
+        }
+        return childElems;
+    }
+
+    // method that returns either unique child element matching given name
+    // or a list of child elements of that name (if there are more than one matches).
+    public static Object getElementsByName(Object elem, final String name) {
+        List<Element> elems = getChildElements((Element)elem, name);
+        return elems.size() == 1? elems.get(0) : elems;
+    }
+
+    // method to extract text context under a given DOM Element
+    public static Object getElementText(Object elem) {
+        NodeList nodeList = ((Element)elem).getChildNodes();
+        int len = nodeList.getLength();
+        StringBuilder text = new StringBuilder();
+        for (int i = 0; i < len; i++) {
+            Node node = nodeList.item(i);
+            if (node.getNodeType() == Node.TEXT_NODE) {
+                text.append(node.getNodeValue());
+            }
+        }
+        return text.toString();
+    }
+
+    private static final MethodHandle ELEMENTS_BY_NAME;
+    private static final MethodHandle ELEMENT_TEXT;
+    private static final MethodHandle IS_ELEMENT;
+    static {
+        ELEMENTS_BY_NAME = Lookup.PUBLIC.findStatic(DOMLinkerExporter.class,
+            "getElementsByName",
+            MethodType.methodType(Object.class, Object.class, String.class));
+        ELEMENT_TEXT = Lookup.PUBLIC.findStatic(DOMLinkerExporter.class,
+            "getElementText",
+            MethodType.methodType(Object.class, Object.class));
+        IS_ELEMENT = Guards.isInstance(Element.class, MethodType.methodType(Boolean.TYPE, Object.class));
+    }
+
+    @Override
+    public List<GuardingDynamicLinker> get() {
+        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
+        linkers.add(new TypeBasedGuardingDynamicLinker() {
+            @Override
+            public boolean canLinkType(final Class<?> type) {
+                return Element.class.isAssignableFrom(type);
+            }
+
+            @Override
+            public GuardedInvocation getGuardedInvocation(LinkRequest request,
+                LinkerServices linkerServices) throws Exception {
+                final Object self = request.getReceiver();
+                if (! (self instanceof Element)) {
+                    return null;
+                }
+
+                CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                Operation op = desc.getOperation();
+                Object name = NamedOperation.getName(op);
+                boolean getProp = CompositeOperation.contains(
+                        NamedOperation.getBaseOperation(op),
+                        StandardOperation.GET_PROPERTY);
+                if (getProp && name instanceof String) {
+                    String nameStr = (String)name;
+
+                    // Treat names starting with "_" as special names.
+                    // Everything else is linked other dynalink bean linker!
+                    // This avoids collision with Java methods of org.w3c.dom.Element class
+                    // Assumption is that Java APIs won't start with "_" character!!
+                    if (nameStr.equals("_")) {
+                        // short-hand to get text content under a given DOM Element
+                        return new GuardedInvocation(ELEMENT_TEXT, IS_ELEMENT);
+                    } else if (nameStr.startsWith("_")) {
+                        return new GuardedInvocation(
+                            MethodHandles.insertArguments(ELEMENTS_BY_NAME, 1, nameStr.substring(1)),
+                            IS_ELEMENT);
+                    }
+
+                }
+
+                return null;
+            }
+        });
+        return linkers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,2 @@
+DOMLinkerExporter
+UnderscoreNameLinkerExporter
--- a/samples/Main.asm	Sun Nov 29 20:30:01 2015 -0800
+++ b/samples/Main.asm	Wed Dec 02 09:37:26 2015 -0800
@@ -38,66 +38,128 @@
 //
 // See also: https://wiki.openjdk.java.net/display/CodeTools/asmtools
 //
-// NOTE: Uses nashorn internals and so *may* break with later nashorn!
+// NOTE: Uses dynalink API defined by JEP-276 (http://openjdk.java.net/jeps/276)
 
 super public class Main
 	version 52:0
 {
 
+private static final Field linker:"Ljdk/dynalink/DynamicLinker;";
 
+/*
+   static {
+        // create dynalink linker factory
+        final DynamicLinkerFactory factory = new DynamicLinkerFactory();
+
+        // create standard linker that can handle Java POJOs
+        linker = factory.createLinker();
+   }
+*/
+static Method "<clinit>":"()V"
+        stack 2 locals 1
+{
+    new     class jdk/dynalink/DynamicLinkerFactory;
+    dup;
+    invokespecial   Method jdk/dynalink/DynamicLinkerFactory."<init>":"()V";
+    astore_0;
+    aload_0;
+    invokevirtual   Method jdk/dynalink/DynamicLinkerFactory.createLinker:"()Ljdk/dynalink/DynamicLinker;";
+    putstatic       Field linker:"Ljdk/dynalink/DynamicLinker;";
+    return;
+}
+
+/*
+    // Bootstrap method used with invokedynamic methods
+
+    public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+        // use dynalink linker to perform the actual linking
+        return linker.link(
+            new SimpleRelinkableCallSite(
+                new CallSiteDescriptor(
+                    MethodHandles.publicLookup(), 
+                    new NamedOperation(StandardOperation.GET_PROPERTY, name), type)
+            )
+        );
+    }
+
+ */
+public static Method bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+        stack 10 locals 3
+{
+    getstatic       Field linker:"Ljdk/dynalink/DynamicLinker;";
+    new     class jdk/dynalink/support/SimpleRelinkableCallSite;
+    dup;
+    new     class jdk/dynalink/CallSiteDescriptor;
+    dup;
+    invokestatic    Method java/lang/invoke/MethodHandles.publicLookup:"()Ljava/lang/invoke/MethodHandles$Lookup;";
+    new     class jdk/dynalink/NamedOperation;
+    dup;
+    getstatic       Field jdk/dynalink/StandardOperation.GET_PROPERTY:"Ljdk/dynalink/StandardOperation;";
+    aload_1;
+    invokespecial   Method jdk/dynalink/NamedOperation."<init>":"(Ljdk/dynalink/Operation;Ljava/lang/Object;)V";
+    aload_2;
+    invokespecial   Method jdk/dynalink/CallSiteDescriptor."<init>":"(Ljava/lang/invoke/MethodHandles$Lookup;Ljdk/dynalink/Operation;Ljava/lang/invoke/MethodType;)V";
+    invokespecial   Method jdk/dynalink/support/SimpleRelinkableCallSite."<init>":"(Ljdk/dynalink/CallSiteDescriptor;)V";
+    invokevirtual   Method jdk/dynalink/DynamicLinker.link:"(Ljdk/dynalink/RelinkableCallSite;)Ljdk/dynalink/RelinkableCallSite;";
+    checkcast       class java/lang/invoke/CallSite;
+    areturn;
+}
+
+// default constructor that does nothing!
 public Method "<init>":"()V"
 	stack 1 locals 1
 {
-		aload_0;
-		invokespecial	Method java/lang/Object."<init>":"()V";
-		return;
+    aload_0;
+    invokespecial	Method java/lang/Object."<init>":"()V";
+    return;
 }
 
 public static Method main:"([Ljava/lang/String;)V"
 	stack 2 locals 2
 {
-                // List l = new ArrayList();
-		new	class java/util/ArrayList;
-		dup;
-		invokespecial	Method java/util/ArrayList."<init>":"()V";
-		astore_1;
-		aload_1;
+    // List l = new ArrayList();
+    new	class java/util/ArrayList;
+    dup;
+    invokespecial	Method java/util/ArrayList."<init>":"()V";
+    astore_1;
+    aload_1;
 
-                // l.add("hello");
-		ldc	String "hello";
-		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
-		pop;
+    // l.add("hello");
+    ldc	String "hello";
+    invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+    pop;
 
-                // l.add("world");
-		aload_1;
-		ldc	String "world";
-		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
-		pop;
+    // l.add("world");
+    aload_1;
+    ldc	String "world";
+    invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+    pop;
 
-                // printLength(l);
-		aload_1;
-		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+    // printLength(l);
+    aload_1;
+    invokestatic	Method printLength:"(Ljava/lang/Object;)V";
 
-                // printLength(args); // args is argument of main method
-		aload_0;
-		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
-		return;
+    // printLength(args); // args is argument of main method
+    aload_0;
+    invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+    return;
 }
 
 private static Method printLength:"(Ljava/lang/Object;)V"
 	stack 2 locals 1
 {
-		getstatic	Field java/lang/System.out:"Ljava/io/PrintStream;";
-		aload_0;
+    getstatic	Field java/lang/System.out:"Ljava/io/PrintStream;";
+    aload_0;
 
-                // Using nashorn embedded dynalink linker with the following invokedynamic
-                // 'length' property on a bean - arrays, lists supported
+    // Using bootstrap method in this class with the following invokedynamic
+    // which uses dynalink linker. Dynalink's bean linker handles Java beans.
+    // 'length' property on a bean - arrays, lists supported
 
-                invokedynamic   InvokeDynamic REF_invokeStatic:jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;":"dyn:getProp|getElem|getMethod:length":"(Ljava/lang/Object;)Ljava/lang/Object;" int 0;
+    invokedynamic   InvokeDynamic REF_invokeStatic:Main.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;":"length":"(Ljava/lang/Object;)Ljava/lang/Object;";
 
-                // print 'length' value
-		invokevirtual	Method java/io/PrintStream.println:"(Ljava/lang/Object;)V";
-		return;
+    // print 'length' value
+    invokevirtual	Method java/io/PrintStream.println:"(Ljava/lang/Object;)V";
+    return;
 }
 
 } // end Class Main
Binary file samples/Main.class has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/UnderscoreNameLinkerExporter.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.SimpleLinkRequest;
+
+/**
+ * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
+ * This linker translater underscore_separated method names to CamelCase names
+ * used in Java APIs.
+ */
+public final class UnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter {
+    static {
+        System.out.println("pluggable dynalink underscore name linker loaded");
+    }
+
+    private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)");
+
+    // translate underscore_separated name as a CamelCase name
+    private static String translateToCamelCase(String name) {
+        Matcher m = UNDERSCORE_NAME.matcher(name);
+        StringBuilder buf = new StringBuilder();
+        while (m.find()) {
+            m.appendReplacement(buf, m.group(1).toUpperCase());
+        }
+        m.appendTail(buf);
+        return buf.toString();
+    }
+
+    // locate the first standard operation from the call descriptor
+    private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
+        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
+        if (base instanceof StandardOperation) {
+            return (StandardOperation)base;
+        } else if (base instanceof CompositeOperation) {
+            final CompositeOperation cop = (CompositeOperation)base;
+            for(int i = 0; i < cop.getOperationCount(); ++i) {
+                final Operation op = cop.getOperation(i);
+                if (op instanceof StandardOperation) {
+                    return (StandardOperation)op;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public List<GuardingDynamicLinker> get() {
+        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
+        linkers.add(new GuardingDynamicLinker() {
+            @Override
+            public GuardedInvocation getGuardedInvocation(LinkRequest request,
+                LinkerServices linkerServices) throws Exception {
+                final Object self = request.getReceiver();
+                CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                Operation op = desc.getOperation();
+                Object name = NamedOperation.getName(op);
+                // is this a named GET_METHOD?
+                boolean isGetMethod = getFirstStandardOperation(desc) == StandardOperation.GET_METHOD;
+                if (isGetMethod && name instanceof String) {
+                    String str = (String)name;
+                    if (str.indexOf('_') == -1) {
+                        return null;
+                    }
+
+                    String nameStr = translateToCamelCase(str);
+                    // create a new call descriptor to use translated name
+                    CallSiteDescriptor newDesc = new CallSiteDescriptor(
+                        desc.getLookup(),
+                        new NamedOperation(NamedOperation.getBaseOperation(op), nameStr),
+                        desc.getMethodType());
+                    // create a new Link request to link the call site with translated name
+                    LinkRequest newRequest = new SimpleLinkRequest(newDesc,
+                        request.isCallSiteUnstable(), request.getArguments());
+                    // return guarded invocation linking the translated request
+                    return linkerServices.getGuardedInvocation(newRequest);
+                }
+
+                return null;
+            }
+        });
+        return linkers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dom_linker.js	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,48 @@
+#! simple dom linker example
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script assumes you've built jdk9 or using latest
+// jdk9 image and put the 'bin' directory in the PATH
+
+$EXEC.throwOnError=true
+
+// compile DOMLinkerExporter
+`javac -cp ../dist/nashorn.jar DOMLinkerExporter.java`
+
+// make a jar file out of pluggable linker
+`jar cvf dom_linker.jar DOMLinkerExporter*.class META-INF/`
+
+// run a sample script that uses pluggable linker
+// but make sure classpath points to the pluggable linker jar!
+
+`jjs -cp dom_linker.jar dom_linker_gutenberg.js`
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dom_linker_gutenberg.js	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,117 @@
+#// Usage: jjs -cp dom_linker.jar -scripting dom_linker_gutenberg.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script depends on DOM Element dynalink linker!
+// Without that linker, this script will fail to run!
+
+// Simple example that demonstrates reading XML Rss feed
+// to generate a HTML file from script and show it by browser.
+// Uses XML DOM parser along with DOM element pluggable dynalink linker
+// for ease of navigation of DOM (child) elements by name.
+
+// Java classes used
+var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory");
+var Node = Java.type("org.w3c.dom.Node");
+var File = Java.type("java.io.File");
+var FileWriter = Java.type("java.io.FileWriter");
+var PrintWriter = Java.type("java.io.PrintWriter");
+
+// parse XML from uri and return Document
+function parseXML(uri) {
+    var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder();
+    return docBuilder["parse(java.lang.String)"](uri);
+}
+
+// generate HTML using here-doc and string interpolation
+function getBooksHtml() {
+    var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss");
+    // wrap document root Element as script convenient object
+    var rss = doc.documentElement;
+
+    var str = <<HEAD
+
+<html>
+<title>${rss._channel._title._}</title>
+<body>
+<h1>${rss._channel._description._}</h1>
+<p>
+Published on ${rss._channel._pubDate._}
+</p>
+
+HEAD
+
+    var items = rss._channel._item;
+    for each (var i in items) {
+        str += <<LIST
+
+<dl>
+<dt><a href="${i._link._}">${i._title._}</a></dt>
+<dd>${i._description._}</dd>
+</dl>
+
+LIST
+    }
+    str += <<END
+
+</body>
+</html>
+
+END
+    return str;
+}
+
+// write the string to the given file
+function writeTo(file, str) {
+    var w = new PrintWriter(new FileWriter(file));
+    try {
+        w.print(str);
+    } finally {
+        w.close();
+    }
+}
+
+// generate books HTML
+var str = getBooksHtml();
+
+// write to file. __DIR__ is directory where
+// this script is stored.
+var file = new File(__DIR__ + "books.html");
+writeTo(file, str);
+
+// show it by desktop browser
+try {
+    var Desktop = Java.type("java.awt.Desktop");
+    Desktop.desktop.browse(file.toURI());
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/underscore.js	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,42 @@
+#// Usage: jjs -cp underscore_linker.jar -scripting underscore.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script depends on underscore name to CamelCase name 
+// translator dynalink linker! Without that linker, this script
+// will fail to run!
+
+var S = java.util.stream.Stream
+S.of(45, 54654,546,435).for_each(print)
+print("hello".char_at(2))
+print(4354.45.value_of())
+print(java.lang.System.get_properties())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/underscore_linker.js	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,50 @@
+# underscore name translator dynalink linker example
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script assumes you've built jdk9 or using latest
+// jdk9 image and put the 'bin' directory in the PATH
+
+$EXEC.throwOnError=true
+
+// compile UnderscoreNameLinkerExporter
+`javac -cp ../dist/nashorn.jar UnderscoreNameLinkerExporter.java`
+
+// make a jar file out of pluggable linker
+`jar cvf underscore_linker.jar UnderscoreNameLinkerExporter*.class META-INF/`
+
+// run a sample script that uses pluggable linker
+// but make sure classpath points to the pluggable linker jar!
+
+`jjs -cp underscore_linker.jar underscore.js`
+print($OUT)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.Objects;
+
+/**
+ * Call site descriptors contain all the information necessary for linking a
+ * call site. This information is normally passed as parameters to bootstrap
+ * methods and consists of the {@code MethodHandles.Lookup} object on the caller
+ * class in which the call site occurs, the dynamic operation at the call
+ * site, and the method type of the call site. {@code CallSiteDescriptor}
+ * objects are used in Dynalink to capture and store these parameters for
+ * subsequent use by the {@link DynamicLinker}.
+ * <p>
+ * The constructors of built-in {@link RelinkableCallSite} implementations all
+ * take a call site descriptor.
+ * <p>
+ * Call site descriptors must be immutable. You can use this class as-is or you
+ * can subclass it, especially if you need to add further information to the
+ * descriptors (typically, values passed in additional parameters to the
+ * bootstrap method. Since the descriptors must be immutable, you can set up a
+ * cache for equivalent descriptors to have the call sites share them.
+ */
+public class CallSiteDescriptor {
+    private final MethodHandles.Lookup lookup;
+    private final Operation operation;
+    private final MethodType methodType;
+
+    /**
+     * The name of a runtime permission to invoke the {@link #getLookup()}
+     * method.
+     */
+    public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup";
+
+    private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(GET_LOOKUP_PERMISSION_NAME);
+
+    /**
+     * Creates a new call site descriptor.
+     * @param lookup the lookup object describing the class the call site belongs to.
+     * @param operation the dynamic operation at the call site.
+     * @param methodType the method type of the call site.
+     */
+    public CallSiteDescriptor(final Lookup lookup, final Operation operation, final MethodType methodType) {
+        this.lookup = Objects.requireNonNull(lookup, "lookup");
+        this.operation = Objects.requireNonNull(operation, "name");
+        this.methodType = Objects.requireNonNull(methodType, "methodType");
+    }
+
+    /**
+     * Returns the operation at the call site.
+     * @return the operation at the call site.
+     */
+    public final Operation getOperation() {
+        return operation;
+    }
+
+    /**
+     * The type of the method at the call site.
+     *
+     * @return type of the method at the call site.
+     */
+    public final MethodType getMethodType() {
+        return methodType;
+    }
+
+    /**
+     * Returns the lookup that should be used to find method handles to set as
+     * targets of the call site described by this descriptor. When creating
+     * descriptors from a {@link java.lang.invoke} bootstrap method, it should
+     * be the lookup passed to the bootstrap.
+     * @return the lookup that should be used to find method handles to set as
+     * targets of the call site described by this descriptor.
+     * @throws SecurityException if the lookup isn't the
+     * {@link MethodHandles#publicLookup()} and a security manager is present,
+     * and a check for {@code RuntimePermission("dynalink.getLookup")} fails.
+     */
+    public final Lookup getLookup() {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null && lookup != MethodHandles.publicLookup()) {
+            sm.checkPermission(GET_LOOKUP_PERMISSION);
+        }
+        return lookup;
+    }
+
+    /**
+     * Returns the value of {@link #getLookup()} without a security check. Can
+     * be used by subclasses to access the lookup quickly.
+     * @return same as returned value of {@link #getLookup()}.
+     */
+    protected final Lookup getLookupPrivileged() {
+        return lookup;
+    }
+
+    /**
+     * Creates a new call site descriptor from this descriptor, which is
+     * identical to this, except it changes the method type. Invokes
+     * {@link #changeMethodTypeInternal(MethodType)} and checks that it returns
+     * a descriptor of the same class as this descriptor.
+     *
+     * @param newMethodType the new method type
+     * @return a new call site descriptor, with the method type changed.
+     * @throws RuntimeException if {@link #changeMethodTypeInternal(MethodType)}
+     * returned a descriptor of different class than this object.
+     * @throws NullPointerException if {@link #changeMethodTypeInternal(MethodType)}
+     * returned null.
+     */
+    public final CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
+        final CallSiteDescriptor changed = Objects.requireNonNull(
+                changeMethodTypeInternal(newMethodType),
+                "changeMethodTypeInternal() must not return null.");
+
+        if (getClass() != changed.getClass()) {
+            throw new RuntimeException(
+                    "changeMethodTypeInternal() must return an object of the same class it is invoked on.");
+        }
+
+        return changed;
+    }
+
+    /**
+     * Creates a new call site descriptor from this descriptor, which is
+     * identical to this, except it changes the method type. Subclasses must
+     * override this method to return an object of their exact class.
+     *
+     * @param newMethodType the new method type
+     * @return a new call site descriptor, with the method type changed.
+     */
+    protected CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) {
+        return new CallSiteDescriptor(lookup, operation, newMethodType);
+    }
+
+    /**
+     * Returns true if this call site descriptor is equal to the passed object.
+     * It is considered equal if the other object is of the exact same class,
+     * their operations and method types are equal, and their lookups have the
+     * same {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and
+     * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()}.
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj == null) {
+            return false;
+        } else if (obj.getClass() != getClass()) {
+            return false;
+        }
+        final CallSiteDescriptor other = (CallSiteDescriptor)obj;
+        return operation.equals(other.operation) &&
+               methodType.equals(other.methodType) &&
+               lookupsEqual(lookup, other.lookup);
+    }
+
+    /**
+     * Compares two lookup objects for value-based equality. They are considered
+     * equal if they have the same
+     * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and
+     * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()}.
+     * @param l1 first lookup
+     * @param l2 second lookup
+     * @return true if the two lookups are equal, false otherwise.
+     */
+    private static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
+        return l1.lookupClass() == l2.lookupClass() && l1.lookupModes() == l2.lookupModes();
+    }
+
+    /**
+     * Returns a value-based hash code of this call site descriptor computed
+     * from its operation, method type, and lookup object's lookup class and
+     * lookup modes.
+     * @return value-based hash code for this call site descriptor.
+     */
+    @Override
+    public int hashCode() {
+        return operation.hashCode() + 31 * methodType.hashCode() + 31 * 31 * lookupHashCode(lookup);
+    }
+
+    /**
+     * Returns a value-based hash code for the passed lookup object. It is
+     * based on the lookup object's
+     * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and
+     * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()} values.
+     * @param lookup the lookup object.
+     * @return a hash code for the object..
+     */
+    private static int lookupHashCode(final Lookup lookup) {
+        return lookup.lookupClass().hashCode() + 31 * lookup.lookupModes();
+    }
+
+    /**
+     * Returns the string representation of this call site descriptor, of the
+     * format {@code name(parameterTypes)returnType@lookup}.
+     */
+    @Override
+    public String toString() {
+        final String mt = methodType.toString();
+        final String l = lookup.toString();
+        final String o = operation.toString();
+        final StringBuilder b = new StringBuilder(o.length() + mt.length() + 1 + l.length());
+        return b.append(o).append(mt).append('@').append(l).toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.internal.InternalTypeUtilities;
+
+/**
+ * A dual map that can either strongly or weakly reference a given class depending on whether the class is visible from
+ * a class loader or not.
+ *
+ * @param <T> the type of the values in the map
+ */
+abstract class ClassMap<T> {
+    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext("getClassLoader");
+
+    private final ConcurrentMap<Class<?>, T> map = new ConcurrentHashMap<>();
+    private final Map<Class<?>, Reference<T>> weakMap = new WeakHashMap<>();
+    private final ClassLoader classLoader;
+
+    /**
+     * Creates a new class map. It will use strong references for all keys and values where the key is a class visible
+     * from the class loader, and will use weak keys and soft values for all other classes.
+     *
+     * @param classLoader the classloader that determines strong referenceability.
+     */
+    ClassMap(final ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Compute the value associated with the given class. It is possible that the method will be invoked several times
+     * (or even concurrently) for the same class parameter.
+     *
+     * @param clazz the class to compute the value for
+     * @return the return value. Must not be null.
+     */
+    abstract T computeValue(Class<?> clazz);
+
+    /**
+     * Returns the value associated with the class
+     *
+     * @param clazz the class
+     * @return the value associated with the class
+     */
+    T get(final Class<?> clazz) {
+        // Check in fastest first - objects we're allowed to strongly reference
+        final T v = map.get(clazz);
+        if(v != null) {
+            return v;
+        }
+        // Check objects we're not allowed to strongly reference
+        Reference<T> ref;
+        synchronized(weakMap) {
+            ref = weakMap.get(clazz);
+        }
+        if(ref != null) {
+            final T refv = ref.get();
+            if(refv != null) {
+                return refv;
+            }
+        }
+        // Not found in either place; create a new value
+        final T newV = computeValue(clazz);
+        assert newV != null;
+
+        final Boolean canReferenceDirectly = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                return InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader());
+            }
+        }, GET_CLASS_LOADER_CONTEXT);
+
+        // If allowed to strongly reference, put it in the fast map
+        if(canReferenceDirectly) {
+            final T oldV = map.putIfAbsent(clazz, newV);
+            return oldV != null ? oldV : newV;
+        }
+        // Otherwise, put it into the weak map
+        synchronized(weakMap) {
+            ref = weakMap.get(clazz);
+            if(ref != null) {
+                final T oldV = ref.get();
+                if(oldV != null) {
+                    return oldV;
+                }
+            }
+            weakMap.put(clazz, new SoftReference<>(newV));
+            return newV;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/CompositeOperation.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2015 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Describes an operation that is composed of at least two other operations. The
+ * component operations are treated as alternatives to each other in order of
+ * preference. The semantics of the composite operation is "first successful".
+ * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be
+ * interpreted as <i>get the property named "color" on the object, but if the
+ * property does not exist, then get the collection element named "color"
+ * instead</i>.
+ * <p>
+ * Composite operations are helpful in implementation of languages that
+ * don't distinguish between one or more of the property, method, and element
+ * namespaces, or when expressing operations against objects that can be
+ * considered both ordinary objects and collections, e.g. Java
+ * {@link java.util.Map} objects. A composite operation
+ * {@code GET_PROPERTY|GET_ELEMENT:empty} against a Java map will always match
+ * the {@link java.util.Map#isEmpty()} property, but
+ * {@code GET_ELEMENT|GET_PROPERTY:empty} will actually match a map element with
+ * key {@code "empty"} if the map contains that key, and only fall back to the
+ * {@code isEmpty()} property getter if the map does not contain the key. If
+ * the source language mandates this semantics, it can be easily achieved using
+ * composite operations.
+ * <p>
+ * Even if the language itself doesn't distinguish between some of the
+ * namespaces, it can be helpful to map different syntaxes to different
+ * compositions. E.g. the source expression {@code obj.color} could map to
+ * {@code GET_PROPERTY|GET_ELEMENT|GET_METHOD:color}, but a different source
+ * expression that looks like collection element access {@code obj[key]} could
+ * be expressed instead as {@code GET_ELEMENT|GET_PROPERTY|GET_METHOD}.
+ * Finally, if the retrieved value is subsequently called, then it makes sense
+ * to bring {@code GET_METHOD} to the front of the list: the getter part of the
+ * source expression {@code obj.color()} should be
+ * {@code GET_METHOD|GET_PROPERTY|GET_ELEMENT:color} and the one for
+ * {@code obj[key]()} should be {@code GET_METHOD|GET_ELEMENT|GET_PROPERTY}.
+ * <p>
+ * The elements of a composite operation can not be composites or named
+ * operations, but rather simple operations such are elements of
+ * {@link StandardOperation}. A composite operation itself can serve as the base
+ * operation of a named operation, though; a typical way to construct e.g. the
+ * {@code GET_ELEMENT|GET_PROPERTY:empty} from above would be:
+ * <pre>
+ * Operation getElementOrPropertyEmpty = new NamedOperation(
+ *     new CompositeOperation(
+ *         StandardOperation.GET_ELEMENT,
+ *         StandardOperation.GET_PROPERTY),
+ *     "empty");
+ * </pre>
+ * <p>
+ * Not all compositions make sense. Typically, any combination in any order of
+ * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and
+ * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and
+ * {@code SET_ELEMENT}; other standard operations should not be combined. The
+ * constructor will allow any combination of operations, though.
+ */
+public final class CompositeOperation implements Operation {
+    private final Operation[] operations;
+
+    /**
+     * Constructs a new composite operation.
+     * @param operations the components for this composite operation. The passed
+     * array will be cloned.
+     * @throws IllegalArgumentException if less than two components are
+     * specified, or any component is itself a {@link CompositeOperation} or a
+     * {@link NamedOperation}.
+     * @throws NullPointerException if either the operations array or any of its
+     * elements are {@code null}.
+     */
+    public CompositeOperation(final Operation... operations) {
+        Objects.requireNonNull(operations, "operations array is null");
+        if (operations.length < 2) {
+            throw new IllegalArgumentException("Must have at least two operations");
+        }
+        final Operation[] clonedOps = operations.clone();
+        for(int i = 0; i < clonedOps.length; ++i) {
+            final Operation op = clonedOps[i];
+            if (op == null) {
+                throw new NullPointerException("operations[" + i + "] is null");
+            } else if (op instanceof NamedOperation) {
+                throw new IllegalArgumentException("operations[" + i + "] is a NamedOperation");
+            } else if (op instanceof CompositeOperation) {
+                throw new IllegalArgumentException("operations[" + i + "] is a CompositeOperation");
+            }
+        }
+        this.operations = clonedOps;
+    }
+
+    /**
+     * Returns the component operations in this composite operation. The
+     * returned array is a copy and changes to it don't have effect on this
+     * object.
+     * @return the component operations in this composite operation.
+     */
+    public Operation[] getOperations() {
+        return operations.clone();
+    }
+
+    /**
+     * Returns the number of component operations in this composite operation.
+     * @return the number of component operations in this composite operation.
+     */
+    public int getOperationCount() {
+        return operations.length;
+    }
+
+    /**
+     * Returns the i-th component operation in this composite operation.
+     * @param i the operation index
+     * @return the i-th component operation in this composite operation.
+     * @throws IndexOutOfBoundsException if the index is out of range.
+     */
+    public Operation getOperation(final int i) {
+        try {
+            return operations[i];
+        } catch (final ArrayIndexOutOfBoundsException e) {
+            throw new IndexOutOfBoundsException(Integer.toString(i));
+        }
+    }
+
+    /**
+     * Returns true if this composite operation contains an operation equal to
+     * the specified operation.
+     * @param operation the operation being searched for. Must not be null.
+     * @return true if the if this composite operation contains an operation
+     * equal to the specified operation.
+     */
+    public boolean contains(final Operation operation) {
+        Objects.requireNonNull(operation);
+        for(final Operation component: operations) {
+            if (component.equals(operation)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the other object is also a composite operation and their
+     * component operations are equal.
+     * @param obj the object to compare to
+     * @return true if this object is equal to the other one, false otherwise.
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof CompositeOperation) {
+            return Arrays.equals(operations, ((CompositeOperation)obj).operations);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the hash code of this composite operation. Defined to be equal
+     * to {@code java.util.Arrays.hashCode(operations)}.
+     */
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(operations);
+    };
+
+    /**
+     * Returns the string representation of this composite operation. Defined to
+     * be the {@code toString} of its component operations, each separated by
+     * the vertical line character (e.g. {@code "GET_PROPERTY|GET_ELEMENT"}).
+     * @return the string representation of this composite operation.
+     */
+    @Override
+    public String toString() {
+        final StringBuilder b = new StringBuilder();
+        b.append(operations[0]);
+        for(int i = 1; i < operations.length; ++i) {
+            b.append('|').append(operations[i]);
+        }
+        return b.toString();
+    }
+
+    /**
+     * Returns the components of the passed operation if it is a composite
+     * operation, otherwise returns an array containing the operation itself.
+     * This allows for returning an array of component even if it is not known
+     * whether the operation is itself a composite (treating a non-composite
+     * operation as if it were a single-element composite of itself).
+     * @param op the operation whose components are retrieved.
+     * @return if the passed operation is a composite operation, returns its
+     * {@link #getOperations()}, otherwise returns the operation itself.
+     */
+    public static Operation[] getOperations(final Operation op) {
+        return op instanceof CompositeOperation
+                ? ((CompositeOperation)op).operations.clone()
+                : new Operation[] { op };
+    }
+
+    /**
+     * Returns true if the specified potentially composite operation is a
+     * {@link CompositeOperation} and contains an operation equal to the
+     * specified operation. If {@code composite} is not a
+     * {@link CompositeOperation}, then the two operations are compared for
+     * equality.
+     * @param composite the potentially composite operation. Must not be null.
+     * @param operation the operation being searched for. Must not be null.
+     * @return true if the if the passed operation is a
+     * {@link CompositeOperation} and contains a component operation equal to
+     * the specified operation, or if it is not a {@link CompositeOperation} and
+     * is equal to {@code operation}.
+     */
+    public static boolean contains(final Operation composite, final Operation operation) {
+        if (composite instanceof CompositeOperation) {
+            return ((CompositeOperation)composite).contains(operation);
+        }
+        return composite.equals(Objects.requireNonNull(operation));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.util.Objects;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardedInvocationTransformer;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.Lookup;
+import jdk.dynalink.linker.support.SimpleLinkRequest;
+import jdk.dynalink.support.ChainedCallSite;
+import jdk.dynalink.support.SimpleRelinkableCallSite;
+
+/**
+ * The linker for {@link RelinkableCallSite} objects. A dynamic linker is a main
+ * objects when using Dynalink, it coordinates linking of call sites with
+ * linkers of available language runtimes that are represented by
+ * {@link GuardingDynamicLinker} objects (you only need to deal with these if
+ * you are yourself implementing a language runtime with its own object model
+ * and/or type conversions). To use Dynalink, you have to create one or more
+ * dynamic linkers using a {@link DynamicLinkerFactory}. Subsequently, you need
+ * to invoke its {@link #link(RelinkableCallSite)} method from
+ * {@code invokedynamic} bootstrap methods to let it manage all the call sites
+ * they create. Usual usage would be to create at least one class per language
+ * runtime to contain one linker instance as:
+ * <pre>
+ *
+ * class MyLanguageRuntime {
+ *     private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
+ *     private static final DynamicLinker dynamicLinker = createDynamicLinker();
+ *
+ *     private static DynamicLinker createDynamicLinker() {
+ *         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
+ *         factory.setPrioritizedLinker(myLanguageLinker);
+ *         return factory.createLinker();
+ *     }
+ *
+ *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
+ *         return dynamicLinker.link(
+ *             new SimpleRelinkableCallSite(
+ *                 new CallSiteDescriptor(lookup, parseOperation(name), type)));
+ *     }
+ *
+ *     private static Operation parseOperation(String name) {
+ *         ...
+ *     }
+ * }
+ * </pre>
+ * The above setup of one static linker instance is often too simple. You will
+ * often have your language runtime have a concept of some kind of
+ * "context class loader" and you will want to create one dynamic linker per
+ * such class loader, to ensure it incorporates linkers for all other language
+ * runtimes visible to that class loader (see
+ * {@link DynamicLinkerFactory#setClassLoader(ClassLoader)}).
+ * <p>
+ * There are three components you need to provide in the above example:
+ * <ul>
+ *
+ * <li>You are expected to provide a {@link GuardingDynamicLinker} for your own
+ * language. If your runtime doesn't have its own object model or type
+ * conversions, you don't need to implement a {@code GuardingDynamicLinker}; you
+ * would simply not invoke the {@code setPrioritizedLinker} method on the factory.</li>
+ *
+ * <li>The performance of the programs can depend on your choice of the class to
+ * represent call sites. The above example used
+ * {@link SimpleRelinkableCallSite}, but you might want to use
+ * {@link ChainedCallSite} instead. You'll need to experiment and decide what
+ * fits your runtime the best. You can further subclass either of these or
+ * implement your own.</li>
+ *
+ * <li>You also need to provide {@link CallSiteDescriptor}s to your call sites.
+ * They are immutable objects that contain all the information about the call
+ * site: the class performing the lookups, the operation being invoked, and the
+ * method signature. You will have to supply your own scheme to encode and
+ * decode operations in the call site name or static parameters, that is why
+ * in the above example the {@code parseOperation} method is left unimplemented.</li>
+ *
+ * </ul>
+ */
+public final class DynamicLinker {
+    private static final String CLASS_NAME = DynamicLinker.class.getName();
+    private static final String RELINK_METHOD_NAME = "relink";
+
+    private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives";
+    private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
+    private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke.";
+
+    private final LinkerServices linkerServices;
+    private final GuardedInvocationTransformer prelinkTransformer;
+    private final boolean syncOnRelink;
+    private final int unstableRelinkThreshold;
+
+    /**
+     * Creates a new dynamic linker.
+     *
+     * @param linkerServices the linkerServices used by the linker, created by the factory.
+     * @param prelinkTransformer see {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer)}
+     * @param syncOnRelink see {@link DynamicLinkerFactory#setSyncOnRelink(boolean)}
+     * @param unstableRelinkThreshold see {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)}
+     */
+    DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationTransformer prelinkTransformer,
+            final boolean syncOnRelink, final int unstableRelinkThreshold) {
+        if(unstableRelinkThreshold < 0) {
+            throw new IllegalArgumentException("unstableRelinkThreshold < 0");
+        }
+        this.linkerServices = linkerServices;
+        this.prelinkTransformer = prelinkTransformer;
+        this.syncOnRelink = syncOnRelink;
+        this.unstableRelinkThreshold = unstableRelinkThreshold;
+    }
+
+    /**
+     * Links an invokedynamic call site. It will install a method handle into
+     * the call site that invokes the relinking mechanism of this linker. Next
+     * time the call site is invoked, it will be linked for the actual arguments
+     * it was invoked with.
+     *
+     * @param <T> the particular subclass of {@link RelinkableCallSite} for
+     *        which to create a link.
+     * @param callSite the call site to link.
+     *
+     * @return the callSite, for easy call chaining.
+     */
+    public <T extends RelinkableCallSite> T link(final T callSite) {
+        callSite.initialize(createRelinkAndInvokeMethod(callSite, 0));
+        return callSite;
+    }
+
+    /**
+     * Returns the object representing the linker services of this class that
+     * are normally exposed to individual {@link GuardingDynamicLinker
+     * language-specific linkers}. While as a user of this class you normally
+     * only care about the {@link #link(RelinkableCallSite)} method, in certain
+     * circumstances you might want to use the lower level services directly;
+     * either to lookup specific method handles, to access the type converters,
+     * and so on.
+     *
+     * @return the object representing the linker services of this class.
+     */
+    public LinkerServices getLinkerServices() {
+        return linkerServices;
+    }
+
+    private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME,
+            MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class);
+
+    private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) {
+        // Make a bound MH of invoke() for this linker and call site
+        final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf(
+                relinkCount));
+        // Make a MH that gathers all arguments to the invocation into an Object[]
+        final MethodType type = callSite.getDescriptor().getMethodType();
+        final MethodHandle collectingRelinker = boundRelinker.asCollector(Object[].class, type.parameterCount());
+        return MethodHandles.foldArguments(MethodHandles.exactInvoker(type), collectingRelinker.asType(
+                type.changeReturnType(MethodHandle.class)));
+    }
+
+    /**
+     * Relinks a call site conforming to the invocation arguments.
+     *
+     * @param callSite the call site itself
+     * @param arguments arguments to the invocation
+     *
+     * @return return the method handle for the invocation
+     *
+     * @throws Exception rethrows any exception thrown by the linkers
+     */
+    @SuppressWarnings("unused")
+    private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
+        final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
+        final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
+        final LinkRequest linkRequest = new SimpleLinkRequest(callSiteDescriptor, callSiteUnstable, arguments);
+
+        GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
+
+        // None found - throw an exception
+        if(guardedInvocation == null) {
+            throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
+        }
+
+        // Make sure we transform the invocation before linking it into the call site. This is typically used to match the
+        // return type of the invocation to the call site.
+        guardedInvocation = prelinkTransformer.filter(guardedInvocation, linkRequest, linkerServices);
+        Objects.requireNonNull(guardedInvocation);
+
+        int newRelinkCount = relinkCount;
+        // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
+        // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
+        // has already executed once for the unstable call site; we only want the call site to throw away its current
+        // linkage once, when it transitions to unstable.
+        if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
+            callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
+        } else {
+            callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
+        }
+        if(syncOnRelink) {
+            MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
+        }
+        return guardedInvocation.getInvocation();
+    }
+
+    /**
+     * Returns a stack trace element describing the location of the
+     * {@code invokedynamic} call site currently being linked on the current
+     * thread. The operation is potentially expensive as it needs to generate a
+     * stack trace to inspect it and is intended for use in diagnostics code.
+     * For "free-floating" call sites (not associated with an
+     * {@code invokedynamic} instruction), the result is not well-defined.
+     *
+     * @return a stack trace element describing the location of the call site
+     *         currently being linked, or null if it is not invoked while a call
+     *         site is being linked.
+     */
+    public static StackTraceElement getLinkedCallSiteLocation() {
+        final StackTraceElement[] trace = new Throwable().getStackTrace();
+        for(int i = 0; i < trace.length - 1; ++i) {
+            final StackTraceElement frame = trace[i];
+            // If we found any of our linking entry points on the stack...
+            if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) {
+                // ... then look for the first thing calling it that isn't j.l.invoke
+                for (int j = i + 1; j < trace.length; ++j) {
+                    final StackTraceElement frame2 = trace[j];
+                    if (!frame2.getClassName().startsWith(INVOKE_PACKAGE_PREFIX)) {
+                        return frame2;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()},
+     * the frame immediately on top of the call site frame when the call site is
+     * being linked for the first time.
+     *
+     * @param frame the frame
+     *
+     * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}.
+     */
+    private static boolean isInitialLinkFrame(final StackTraceElement frame) {
+        return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME);
+    }
+
+    /**
+     * Returns {@code true} if the frame represents {@code DynamicLinker.relink()},
+     * the frame immediately on top of the call site frame when the call site is
+     * being relinked (linked for second and subsequent times).
+     *
+     * @param frame the frame
+     *
+     * @return {@code true} if this frame represents {@code DynamicLinker.relink()}.
+     */
+    private static boolean isRelinkFrame(final StackTraceElement frame) {
+        return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME);
+    }
+
+    private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) {
+        return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.function.Supplier;
+import jdk.dynalink.beans.BeansLinker;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardedInvocationTransformer;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.GuardingTypeConverterFactory;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.MethodHandleTransformer;
+import jdk.dynalink.linker.MethodTypeConversionStrategy;
+import jdk.dynalink.linker.support.CompositeGuardingDynamicLinker;
+import jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.support.DefaultInternalObjectFilter;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * A factory class for creating {@link DynamicLinker} objects. Dynamic linkers
+ * are the central objects in Dynalink; these are composed of several
+ * {@link GuardingDynamicLinker} objects and coordinate linking of call sites
+ * with them. The usual dynamic linker is a linker
+ * composed of all {@link GuardingDynamicLinker} objects explicitly pre-created
+ * by the user of the factory and configured with
+ * {@link #setPrioritizedLinkers(List)}, as well as any
+ * {@link #setClassLoader(ClassLoader) automatically discovered} ones, and
+ * finally the ones configured with {@link #setFallbackLinkers(List)}; this last
+ * category usually includes {@link BeansLinker}.
+ */
+public final class DynamicLinkerFactory {
+    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext("getClassLoader");
+
+    /**
+     * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink
+     * threshold}.
+     */
+    private static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8;
+
+    private boolean classLoaderExplicitlySet = false;
+    private ClassLoader classLoader;
+
+    private List<? extends GuardingDynamicLinker> prioritizedLinkers;
+    private List<? extends GuardingDynamicLinker> fallbackLinkers;
+    private boolean syncOnRelink = false;
+    private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
+    private GuardedInvocationTransformer prelinkTransformer;
+    private MethodTypeConversionStrategy autoConversionStrategy;
+    private MethodHandleTransformer internalObjectsFilter;
+
+    private List<ServiceConfigurationError> autoLoadingErrors = Collections.emptyList();
+
+    /**
+     * Creates a new dynamic linker factory with default configuration. Upon
+     * creation, the factory can be configured using various {@code setXxx()}
+     * methods and used to create one or more dynamic linkers according to its
+     * current configuration using {@link #createLinker()}.
+     */
+    public DynamicLinkerFactory() {
+    }
+
+    /**
+     * Sets the class loader for automatic discovery of available guarding
+     * dynamic linkers. {@link GuardingDynamicLinkerExporter} implementations
+     * available through this class loader will be automatically instantiated
+     * using the {@link ServiceLoader} mechanism and the linkers they provide
+     * will be incorporated into {@code DynamicLinker}s that this factory
+     * creates. This allows for cross-language interoperability where call sites
+     * belonging to this language runtime can be linked by linkers from these
+     * automatically discovered runtimes if their native objects are passed to
+     * this runtime. If class loader is not set explicitly by invoking this
+     * method, then the thread context class loader of the thread invoking
+     * {@link #createLinker()} will be used. If this method is invoked
+     * explicitly with null then {@link ServiceLoader#loadInstalled(Class)} will
+     * be used to load the linkers.
+     *
+     * @param classLoader the class loader used for the automatic discovery of
+     * available linkers.
+     */
+    public void setClassLoader(final ClassLoader classLoader) {
+        this.classLoader = classLoader;
+        classLoaderExplicitlySet = true;
+    }
+
+    /**
+     * Sets the prioritized guarding dynamic linkers. Language runtimes using
+     * Dynalink will usually have at least one linker for their own language.
+     * These linkers will be consulted first by the resulting dynamic linker
+     * when it is linking call sites, before any autodiscovered and fallback
+     * linkers. If the factory also autodiscovers a linker class matching one
+     * of the prioritized linkers, the autodiscovered class will be ignored and
+     * the explicit prioritized instance will be used.
+     *
+     * @param prioritizedLinkers the list of prioritized linkers. Can be null.
+     * @throws NullPointerException if any of the list elements are null.
+     */
+    public void setPrioritizedLinkers(final List<? extends GuardingDynamicLinker> prioritizedLinkers) {
+        this.prioritizedLinkers = copyListRequireNonNullElements(prioritizedLinkers);
+    }
+
+    /**
+     * Sets the prioritized guarding dynamic linkers. Identical to calling
+     * {@link #setPrioritizedLinkers(List)} with
+     * {@code Arrays.asList(prioritizedLinkers)}.
+     *
+     * @param prioritizedLinkers an array of prioritized linkers. Can be null.
+     * @throws NullPointerException if any of the array elements are null.
+     */
+    public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) {
+        setPrioritizedLinkers(prioritizedLinkers == null ? null : Arrays.asList(prioritizedLinkers));
+    }
+
+    /**
+     * Sets a single prioritized linker. Identical to calling
+     * {@link #setPrioritizedLinkers(List)} with a single-element list.
+     *
+     * @param prioritizedLinker the single prioritized linker. Must not be null.
+     * @throws NullPointerException if null is passed.
+     */
+    public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) {
+        this.prioritizedLinkers = Collections.singletonList(Objects.requireNonNull(prioritizedLinker));
+    }
+
+    /**
+     * Sets the fallback guarding dynamic linkers. These linkers will be
+     * consulted last by the resulting dynamic linker when it is linking call
+     * sites, after any autodiscovered and prioritized linkers. If the factory
+     * also autodiscovers a linker class matching one of the fallback linkers,
+     * the autodiscovered class will be ignored and the explicit fallback
+     * instance will be used.
+     *
+     * @param fallbackLinkers the list of fallback linkers. Can be empty to
+     * indicate the caller wishes to set no fallback linkers. Note that if this
+     * method is not invoked explicitly or is passed null, then the factory
+     * will create an instance of {@link BeansLinker} to serve as the default
+     * fallback linker.
+     * @throws NullPointerException if any of the list elements are null.
+     */
+    public void setFallbackLinkers(final List<? extends GuardingDynamicLinker> fallbackLinkers) {
+        this.fallbackLinkers = copyListRequireNonNullElements(fallbackLinkers);
+    }
+
+    /**
+     * Sets the fallback guarding dynamic linkers. Identical to calling
+     * {@link #setFallbackLinkers(List)} with
+     * {@code Arrays.asList(fallbackLinkers)}.
+     *
+     * @param fallbackLinkers an array of fallback linkers. Can be empty to
+     * indicate the caller wishes to set no fallback linkers. Note that if this
+     * method is not invoked explicitly or is passed null, then the factory
+     * will create an instance of {@link BeansLinker} to serve as the default
+     * fallback linker.
+     * @throws NullPointerException if any of the array elements are null.
+     */
+    public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) {
+        setFallbackLinkers(fallbackLinkers == null ? null : Arrays.asList(fallbackLinkers));
+    }
+
+    /**
+     * Sets whether the dynamic linker created by this factory will invoke
+     * {@link MutableCallSite#syncAll(MutableCallSite[])} after a call site is
+     * relinked. Defaults to false. You probably want to set it to true if your
+     * runtime supports multithreaded execution of dynamically linked code.
+     * @param syncOnRelink true for invoking sync on relink, false otherwise.
+     */
+    public void setSyncOnRelink(final boolean syncOnRelink) {
+        this.syncOnRelink = syncOnRelink;
+    }
+
+    /**
+     * Sets the unstable relink threshold; the number of times a call site is
+     * relinked after which it will be considered unstable, and subsequent link
+     * requests for it will indicate this. Defaults to 8 when not set explicitly.
+     * @param unstableRelinkThreshold the new threshold. Must not be less than
+     * zero. The value of zero means that call sites will never be considered
+     * unstable.
+     * @see LinkRequest#isCallSiteUnstable()
+     */
+    public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) {
+        if(unstableRelinkThreshold < 0) {
+            throw new IllegalArgumentException("unstableRelinkThreshold < 0");
+        }
+        this.unstableRelinkThreshold = unstableRelinkThreshold;
+    }
+
+    /**
+     * Set the pre-link transformer. This is a
+     * {@link GuardedInvocationTransformer} that will get the final chance to
+     * modify the guarded invocation after it has been created by a component
+     * linker and before the dynamic linker links it into the call site. It is
+     * normally used to adapt the return value type of the invocation to the
+     * type of the call site. When not set explicitly, a default pre-link
+     * transformer will be used that simply calls
+     * {@link GuardedInvocation#asType(LinkerServices, MethodType)}. Customized
+     * pre-link transformers are rarely needed; they are mostly used as a
+     * building block for implementing advanced techniques such as code
+     * deoptimization strategies.
+     * @param prelinkTransformer the pre-link transformer for the dynamic
+     * linker. Can be null to have the factory use the default transformer.
+     */
+    public void setPrelinkTransformer(final GuardedInvocationTransformer prelinkTransformer) {
+        this.prelinkTransformer = prelinkTransformer;
+    }
+
+    /**
+     * Sets an object representing the conversion strategy for automatic type
+     * conversions. After
+     * {@link LinkerServices#asType(MethodHandle, MethodType)} has applied all
+     * custom conversions to a method handle, it still needs to effect
+     * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method
+     * invocation conversions} that can usually be automatically applied as per
+     * {@link MethodHandle#asType(MethodType)}. However, sometimes language
+     * runtimes will want to customize even those conversions for their own call
+     * sites. A typical example is allowing unboxing of null return values,
+     * which is by default prohibited by ordinary
+     * {@code MethodHandles.asType()}. In this case, a language runtime can
+     * install its own custom automatic conversion strategy, that can deal with
+     * null values. Note that when the strategy's
+     * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}
+     * is invoked, the custom language conversions will already have been
+     * applied to the method handle, so by design the difference between the
+     * handle's current method type and the desired final type will always only
+     * be ones that can be subjected to method invocation conversions. The
+     * strategy also doesn't need to invoke a final
+     * {@code MethodHandle.asType()} as that will be done internally as the
+     * final step.
+     * @param autoConversionStrategy the strategy for applying method invocation
+     * conversions for the linker created by this factory. Can be null for no
+     * custom strategy.
+     */
+    public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) {
+        this.autoConversionStrategy = autoConversionStrategy;
+    }
+
+    /**
+     * Sets a method handle transformer that is supposed to act as the
+     * implementation of
+     * {@link LinkerServices#filterInternalObjects(MethodHandle)} for linker
+     * services of dynamic linkers created by this factory. Some language
+     * runtimes can have internal objects that should not escape their scope.
+     * They can add a transformer here that will modify the method handle so
+     * that any parameters that can receive potentially internal language
+     * runtime objects will have a filter added on them to prevent them from
+     * escaping, potentially by wrapping them. The transformer can also
+     * potentially add an unwrapping filter to the return value.
+     * {@link DefaultInternalObjectFilter} is provided as a convenience class
+     * for easily creating such filtering transformers.
+     * @param internalObjectsFilter a method handle transformer filtering out
+     * internal objects, or null.
+     */
+    public void setInternalObjectsFilter(final MethodHandleTransformer internalObjectsFilter) {
+        this.internalObjectsFilter = internalObjectsFilter;
+    }
+
+    /**
+     * Creates a new dynamic linker based on the current configuration. This
+     * method can be invoked more than once to create multiple dynamic linkers.
+     * Automatically discovered linkers are newly instantiated on every
+     * invocation of this method. It is allowed to change the factory's
+     * configuration between invocations. The method is not thread safe. After
+     * invocation, callers can invoke {@link #getAutoLoadingErrors()} to
+     * retrieve a list of {@link ServiceConfigurationError}s that occurred while
+     * trying to load automatically discovered linkers. These are never thrown
+     * from the call to this method as it makes every effort to recover from
+     * them and ignore the failing linkers.
+     * @return the new dynamic Linker
+     */
+    public DynamicLinker createLinker() {
+        // Treat nulls appropriately
+        if(prioritizedLinkers == null) {
+            prioritizedLinkers = Collections.emptyList();
+        }
+        if(fallbackLinkers == null) {
+            fallbackLinkers = Collections.singletonList(new BeansLinker());
+        }
+
+        // Gather classes of all precreated (prioritized and fallback) linkers.
+        // We'll filter out any discovered linkers of the same class.
+        final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses =
+                new HashSet<>();
+        addClasses(knownLinkerClasses, prioritizedLinkers);
+        addClasses(knownLinkerClasses, fallbackLinkers);
+
+        final List<GuardingDynamicLinker> discovered = discoverAutoLoadLinkers();
+
+        // Now, concatenate ...
+        final List<GuardingDynamicLinker> linkers =
+                new ArrayList<>(prioritizedLinkers.size() + discovered.size()
+                        + fallbackLinkers.size());
+        // ... prioritized linkers, ...
+        linkers.addAll(prioritizedLinkers);
+        // ... filtered discovered linkers, ...
+        for(final GuardingDynamicLinker linker: discovered) {
+            if(!knownLinkerClasses.contains(linker.getClass())) {
+                linkers.add(linker);
+            }
+        }
+        // ... and finally fallback linkers.
+        linkers.addAll(fallbackLinkers);
+        final List<GuardingDynamicLinker> optimized = CompositeTypeBasedGuardingDynamicLinker.optimize(linkers);
+        final GuardingDynamicLinker composite;
+        switch(linkers.size()) {
+            case 0: {
+                composite = (r, s) -> null; // linker that can't link anything
+                break;
+            }
+            case 1: {
+                composite = optimized.get(0);
+                break;
+            }
+            default: {
+                composite = new CompositeGuardingDynamicLinker(optimized);
+                break;
+            }
+        }
+
+        final List<GuardingTypeConverterFactory> typeConverters = new LinkedList<>();
+        for(final GuardingDynamicLinker linker: linkers) {
+            if(linker instanceof GuardingTypeConverterFactory) {
+                typeConverters.add((GuardingTypeConverterFactory)linker);
+            }
+        }
+
+        if(prelinkTransformer == null) {
+            prelinkTransformer = (inv, request, linkerServices) -> inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType());
+        }
+
+        return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters,
+                autoConversionStrategy), composite, internalObjectsFilter), prelinkTransformer,
+                syncOnRelink, unstableRelinkThreshold);
+    }
+
+    /**
+     * Returns a list of {@link ServiceConfigurationError}s that were
+     * encountered while loading automatically discovered linkers during the
+     * last invocation of {@link #createLinker()}. They can be any non-Dynalink
+     * specific service configuration issues, as well as some Dynalink-specific
+     * errors when an exporter that the factory tried to automatically load:
+     * <ul>
+     * <li>did not have the runtime permission named
+     * {@link GuardingDynamicLinkerExporter#AUTOLOAD_PERMISSION_NAME} in a
+     * system with a security manager, or</li>
+     * <li>returned null from {@link GuardingDynamicLinkerExporter#get()}, or</li>
+     * <li>the list returned from {@link GuardingDynamicLinkerExporter#get()}
+     * had a null element.</li>
+     * </ul>
+     * @return an immutable list of encountered
+     * {@link ServiceConfigurationError}s. Can be empty.
+     */
+    public List<ServiceConfigurationError> getAutoLoadingErrors() {
+        return Collections.unmodifiableList(autoLoadingErrors);
+    }
+
+    private List<GuardingDynamicLinker> discoverAutoLoadLinkers() {
+        autoLoadingErrors = new LinkedList<>();
+        final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader();
+        final List<GuardingDynamicLinker> discovered = new LinkedList<>();
+        try {
+            final ServiceLoader<GuardingDynamicLinkerExporter> linkerLoader =
+                    AccessController.doPrivileged((PrivilegedAction<ServiceLoader<GuardingDynamicLinkerExporter>>)()-> {
+                        if (effectiveClassLoader == null) {
+                            return ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class);
+                        }
+                        return ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
+                    });
+
+            for(final Iterator<GuardingDynamicLinkerExporter> it = linkerLoader.iterator(); it.hasNext();) {
+                try {
+                    final GuardingDynamicLinkerExporter autoLoader = it.next();
+                    try {
+                        discovered.addAll(requireNonNullElements(
+                                Objects.requireNonNull(autoLoader.get(),
+                                        ()->(autoLoader.getClass().getName() + " returned null from get()")),
+                                ()->(autoLoader.getClass().getName() + " returned a list with at least one null element")));
+                    } catch (final ServiceConfigurationError|VirtualMachineError e) {
+                        // Don't wrap a SCE in another SCE. Also, don't ignore
+                        // any VME (e.g. StackOverflowError or OutOfMemoryError).
+                        throw e;
+                    } catch (final Throwable t) {
+                        throw new ServiceConfigurationError(t.getMessage(), t);
+                    }
+                } catch (final ServiceConfigurationError e) {
+                    // Catch SCE with an individual exporter, carry on with it.hasNext().
+                    autoLoadingErrors.add(e);
+                }
+            }
+        } catch (final ServiceConfigurationError e) {
+            // Catch a top-level SCE; one either in ServiceLoader.load(),
+            // ServiceLoader.iterator(), or Iterator.hasNext().
+            autoLoadingErrors.add(e);
+        }
+        return discovered;
+    }
+
+    private static ClassLoader getThreadContextClassLoader() {
+        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+            @Override
+            public ClassLoader run() {
+                return Thread.currentThread().getContextClassLoader();
+            }
+        }, GET_CLASS_LOADER_CONTEXT);
+    }
+
+    private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
+            final List<? extends GuardingDynamicLinker> linkers) {
+        for(final GuardingDynamicLinker linker: linkers) {
+            knownLinkerClasses.add(linker.getClass());
+        }
+    }
+
+    private static <T> List<T> copyListRequireNonNullElements(final List<T> list) {
+        if (list == null) {
+            return null;
+        }
+        return new ArrayList<>(requireNonNullElements(list, ()->"List has at least one null element"));
+    }
+
+    private static <T> List<T> requireNonNullElements(final List<T> list, final Supplier<String> msgSupplier) {
+        for(final T t: list) {
+            Objects.requireNonNull(t, msgSupplier);
+        }
+        return list;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/LinkerServicesImpl.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.dynalink.linker.ConversionComparator.Comparison;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.MethodHandleTransformer;
+
+/**
+ * Default implementation of the {@link LinkerServices} interface.
+ */
+final class LinkerServicesImpl implements LinkerServices {
+    private static final ThreadLocal<LinkRequest> threadLinkRequest = new ThreadLocal<>();
+
+    private final TypeConverterFactory typeConverterFactory;
+    private final GuardingDynamicLinker topLevelLinker;
+    private final MethodHandleTransformer internalObjectsFilter;
+
+    /**
+     * Creates a new linker services object.
+     *
+     * @param typeConverterFactory the type converter factory exposed by the services.
+     * @param topLevelLinker the top level linker used by the services.
+     * @param internalObjectsFilter a method handle transformer that is supposed to act as the implementation of this
+     * services' {@link #filterInternalObjects(java.lang.invoke.MethodHandle)} method.
+     */
+    LinkerServicesImpl(final TypeConverterFactory typeConverterFactory,
+            final GuardingDynamicLinker topLevelLinker, final MethodHandleTransformer internalObjectsFilter) {
+        this.typeConverterFactory = typeConverterFactory;
+        this.topLevelLinker = topLevelLinker;
+        this.internalObjectsFilter = internalObjectsFilter;
+    }
+
+    @Override
+    public boolean canConvert(final Class<?> from, final Class<?> to) {
+        return typeConverterFactory.canConvert(from, to);
+    }
+
+    @Override
+    public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
+        return typeConverterFactory.asType(handle, fromType);
+    }
+
+    @Override
+    public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
+        return typeConverterFactory.getTypeConverter(sourceType, targetType);
+    }
+
+    @Override
+    public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+        return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2);
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception {
+        final LinkRequest prevLinkRequest = threadLinkRequest.get();
+        threadLinkRequest.set(linkRequest);
+        try {
+            return topLevelLinker.getGuardedInvocation(linkRequest, this);
+        } finally {
+            threadLinkRequest.set(prevLinkRequest);
+        }
+    }
+
+    @Override
+    public MethodHandle filterInternalObjects(final MethodHandle target) {
+        return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target;
+    }
+
+    static MethodHandles.Lookup getCurrentLookup() {
+        final LinkRequest currentRequest = threadLinkRequest.get();
+        if (currentRequest != null) {
+            return currentRequest.getCallSiteDescriptor().getLookup();
+        }
+        return MethodHandles.publicLookup();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2015 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.util.Objects;
+
+/**
+ * Operation that associates a name with another operation. Typically used with
+ * operations that normally take a name or an index to bind them to a fixed
+ * name. E.g. {@code new NamedOperation(StandardOperation.GET_PROPERTY, "color")}
+ * will be a named operation for getting the property named "color" on the
+ * object it is applied to, and
+ * {@code new NamedOperation(StandardOperation.GET_ELEMENT, 3)} will be a named
+ * operation for getting the element at index 3 from the collection it is
+ * applied to. In these cases, the expected signature of the call site for the
+ * operation will change to no longer include the name parameter. Specifically,
+ * the documentation for all {@link StandardOperation} members describes how
+ * they are affected by being incorporated into a named operation.
+ */
+public final class NamedOperation implements Operation {
+    private final Operation baseOperation;
+    private final Object name;
+
+    /**
+     * Creates a new named operation.
+     * @param baseOperation the base operation that is associated with a name.
+     * @param name the name associated with the base operation. Note that the
+     * name is not necessarily a string, but can be an arbitrary object. As the
+     * name is used for addressing, it can be an {@link Integer} when meant
+     * to be used as an index into an array or list etc.
+     * @throws NullPointerException if either {@code baseOperation} or
+     * {@code name} is null.
+     * @throws IllegalArgumentException if {@code baseOperation} is itself a
+     * {@code NamedOperation}.
+     */
+    public NamedOperation(final Operation baseOperation, final Object name) {
+        if (baseOperation instanceof NamedOperation) {
+            throw new IllegalArgumentException("baseOperation is a named operation");
+        }
+        this.baseOperation = Objects.requireNonNull(baseOperation, "baseOperation is null");
+        this.name = Objects.requireNonNull(name, "name is null");
+    }
+
+    /**
+     * Returns the base operation of this named operation.
+     * @return the base operation of this named operation.
+     */
+    public Operation getBaseOperation() {
+        return baseOperation;
+    }
+
+    /**
+     * Returns the name of this named operation.
+     * @return the name of this named operation.
+     */
+    public Object getName() {
+        return name;
+    }
+
+    /**
+     * Compares this named operation to another object. Returns true if the
+     * other object is also a named operation, and both their base operations
+     * and name are equal.
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof NamedOperation) {
+            final NamedOperation other = (NamedOperation)obj;
+            return baseOperation.equals(other.baseOperation) && name.equals(other.name);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the hash code of this named operation. It is defined to be equal
+     * to {@code baseOperation.hashCode() + 31 * name.hashCode()}.
+     */
+    @Override
+    public int hashCode() {
+        return baseOperation.hashCode() + 31 * name.hashCode();
+    }
+
+    /**
+     * Returns the string representation of this named operation. It is defined
+     * to be equal to {@code baseOperation.toString() + ":" + name.toString()}.
+     */
+    @Override
+    public String toString() {
+        return baseOperation.toString() + ":" + name.toString();
+    }
+
+    /**
+     * If the passed operation is a named operation, returns its
+     * {@link #getBaseOperation()}, otherwise returns the operation as is.
+     * @param op the operation
+     * @return the base operation of the passed operation.
+     */
+    public static Operation getBaseOperation(final Operation op) {
+        return op instanceof NamedOperation ? ((NamedOperation)op).baseOperation : op;
+    }
+
+    /**
+     * If the passed operation is a named operation, returns its
+     * {@link #getName()}, otherwise returns null. Note that a named operation
+     * object can never have a null name, therefore returning null is indicative
+     * that the passed operation is not, in fact, a named operation.
+     * @param op the operation
+     * @return the name in the passed operation, or null if it is not a named
+     * operation.
+     */
+    public static Object getName(final Operation op) {
+        return op instanceof NamedOperation ? ((NamedOperation)op).name : null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import jdk.dynalink.linker.GuardingDynamicLinker;
+
+/**
+ * Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}.
+ */
+public class NoSuchDynamicMethodException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Creates a new NoSuchDynamicMethodException
+     * @param message the message of the exception.
+     */
+    public NoSuchDynamicMethodException(final String message) {
+        super(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2015 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+/**
+ * An object that describes a dynamic operation. Dynalink defines a set of
+ * standard operations with the {@link StandardOperation} class, as well as a
+ * way to attach a fixed name to an operation using {@link NamedOperation} and
+ * to express a set of alternative operations using {@link CompositeOperation}.
+ * When presenting examples in this documentation, we will refer to standard
+ * operations using their name (e.g. {@code GET_PROPERTY}), to composite
+ * operations by separating their components with the vertical line character
+ * (e.g. {@code GET_PROPERTY|GET_ELEMENT}), and finally to named operations by
+ * separating the base operation and the name with the colon character (e.g.
+ * {@code GET_PROPERTY|GET_ELEMENT:color}).
+ */
+public interface Operation {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.support.ChainedCallSite;
+import jdk.dynalink.support.SimpleRelinkableCallSite;
+
+/**
+ * Interface for call sites managed by a {@link DynamicLinker}. Users of
+ * Dynalink must use subclasses of {@link CallSite} that also implement this
+ * interface as their call site implementations. There is a readily usable
+ * {@link SimpleRelinkableCallSite} subclass that implements monomorphic inline
+ * caching strategy as well as {@link ChainedCallSite} that implements a
+ * polymorphic inline caching strategy and retains a chain of previously linked
+ * method handles. A relinkable call site will be managed by a
+ * {@link DynamicLinker} object after being associated with it using its
+ * {@link DynamicLinker#link(RelinkableCallSite)} method.
+ */
+public interface RelinkableCallSite {
+    /**
+     * Invoked by dynamic linker to initialize the relinkable call site by
+     * setting a relink-and-invoke method handle. The call site implementation
+     * is supposed to set this method handle as its target using
+     * {@link CallSite#setTarget(MethodHandle)}. Relink-and-invoke is the
+     * initial method handle set by
+     * {@link DynamicLinker#link(RelinkableCallSite)} that will cause the call
+     * site to be relinked to an appropriate target on its first invocation
+     * based on its arguments, and that linked target will then be invoked
+     * (hence the name). This linking protocol effectively delays linking until
+     * the call site is invoked with actual arguments and thus ensures that
+     * linkers can make nuanced linking decisions based on those arguments and
+     * not just on the static method type of the call site.
+     * @param relinkAndInvoke a relink-and-invoke method handle supplied by
+     * Dynalink.
+     */
+    public void initialize(MethodHandle relinkAndInvoke);
+
+    /**
+     * Returns the descriptor for this call site.
+     *
+     * @return the descriptor for this call site.
+     */
+    public CallSiteDescriptor getDescriptor();
+
+    /**
+     * This method will be called by the dynamic linker every time the call site
+     * is relinked (but see
+     * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} for an
+     * exception). It will be passed a {@code GuardedInvocation} that the call
+     * site should incorporate into its target method handle. When this method
+     * is called, the call site is allowed to keep other non-invalidated
+     * invocations around for implementation of polymorphic inline caches and
+     * compose them with this invocation to form its final target.
+     *
+     * @param guardedInvocation the guarded invocation that the call site should
+     * incorporate into its target method handle.
+     * @param relinkAndInvoke a relink-and-invoke method handle. This is a
+     * method handle matching the method type of the call site that is supplied
+     * by the {@link DynamicLinker} as a callback. It should be used by this
+     * call site as the ultimate fallback when it can't invoke its target with
+     * the passed arguments. The fallback method is such that when it's invoked,
+     * it'll try to obtain an adequate target {@link GuardedInvocation} for the
+     * invocation, and subsequently invoke
+     * {@link #relink(GuardedInvocation, MethodHandle)} or
+     * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally
+     * invoke the target.
+     */
+    public void relink(GuardedInvocation guardedInvocation, MethodHandle relinkAndInvoke);
+
+    /**
+     * This method will be called by the dynamic linker every time the call site
+     * is relinked <b>and</b> the linker wishes the call site to throw away any
+     * prior linkage state (that is how it differs from
+     * {@link #relink(GuardedInvocation, MethodHandle)}). It will be passed a
+     * {@code GuardedInvocation} that the call site should use to build its new
+     * target method handle. When this method is called, the call site is
+     * discouraged from keeping any previous state, and is supposed to only
+     * link the current invocation.
+     *
+     * @param guardedInvocation the guarded invocation that the call site should
+     * use to build its target method handle.
+     * @param relinkAndInvoke a relink-and-invoke method handle. This is a
+     * method handle matching the method type of the call site that is supplied
+     * by the {@link DynamicLinker} as a callback. It should be used by this
+     * call site as the ultimate fallback when it can't invoke its target with
+     * the passed arguments. The fallback method is such that when it's invoked,
+     * it'll try to obtain an adequate target {@link GuardedInvocation} for the
+     * invocation, and subsequently invoke
+     * {@link #relink(GuardedInvocation, MethodHandle)} or
+     * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally
+     * invoke the target.
+     */
+    public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relinkAndInvoke);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2015 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+/**
+ * Defines the standard dynamic operations. Getter and setter operations defined
+ * in this enumeration can be composed into a {@link CompositeOperation}, and
+ * {@link NamedOperation} can be used to bind the name parameter of operations
+ * that take one, in which case it disappears from the type signature.
+ */
+public enum StandardOperation implements Operation {
+    /**
+     * Get the value of a property defined on an object. Call sites with this
+     * operation should have a signature of
+     * <tt>(receiver,&nbsp;propertyName)&rarr;value</tt> or
+     * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}, with
+     * all parameters and return type being of any type (either primitive or
+     * reference).
+     */
+    GET_PROPERTY,
+    /**
+     * Set the value of a property defined on an object. Call sites with this
+     * operation should have a signature of
+     * <tt>(receiver,&nbsp;propertyName,&nbsp;value)&rarr;void</tt> or
+     * <tt>(receiver,&nbsp;value)&rarr;void</tt> when used with {@link NamedOperation},
+     * with all parameters and return type being of any type (either primitive
+     * or reference).
+     */
+    SET_PROPERTY,
+    /**
+     * Get the value of an element of a collection. Call sites with this
+     * operation should have a signature of
+     * <tt>(receiver,&nbsp;index)&rarr;value</tt> or
+     * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}, with
+     * all parameters and return type being of any type (either primitive or
+     * reference).
+     */
+    GET_ELEMENT,
+    /**
+     * Set the value of an element of a collection. Call sites with this
+     * operation should have a signature of
+     * <tt>(receiver,&nbsp;index,&nbsp;value)&rarr;void</tt> or
+     * <tt>(receiver,&nbsp;value)&rarr;void</tt> when used with {@link NamedOperation},
+     * with all parameters and return type being of any type (either primitive
+     * or reference).
+     */
+    SET_ELEMENT,
+    /**
+     * Get the length of an array or size of a collection. Call sites with
+     * this operation should have a signature of <tt>(receiver)&rarr;value</tt>,
+     * with all parameters and return type being of any type (either primitive
+     * or reference).
+     */
+    GET_LENGTH,
+    /**
+     * Gets an object representing a method defined on an object. Call sites
+     * with this operation should have a signature of
+     * <tt>(receiver,&nbsp;methodName)&rarr;value</tt>, or
+     * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}
+     * with all parameters and return type being of any type (either primitive
+     * or reference).
+     */
+    GET_METHOD,
+    /**
+     * Calls a method defined on an object. Call sites with this
+     * operation should have a signature of
+     * <tt>(receiver,&nbsp;methodName,&nbsp;arguments...)&rarr;value</tt> or
+     * <tt>(receiver,&nbsp;arguments...)&rarr;value</tt> when used with {@link NamedOperation},
+     * with all parameters and return type being of any type (either primitive
+     * or reference).
+     */
+    CALL_METHOD,
+    /**
+     * Calls a callable object. Call sites with this operation should have a
+     * signature of <tt>(receiver,&nbsp;arguments...)&rarr;value</tt>, with all
+     * parameters and return type being of any type (either primitive or
+     * reference). Typically, if the callable is a method of an object, the
+     * first argument will act as the "this" value passed to the called method.
+     * The <tt>CALL</tt> operation is allowed to be used with a
+     * {@link NamedOperation} even though it does not take a name. Using it with
+     * a named operation won't affect its signature; the name is solely meant to
+     * be used as a diagnostic description for error messages.
+     */
+    CALL,
+    /**
+     * Calls a constructor object. Call sites with this operation should have a
+     * signature of <tt>(receiver,&nbsp;arguments...)&rarr;value</tt>, with all
+     * parameters and return type being of any type (either primitive or
+     * reference). The <tt>NEW</tt> operation is allowed to be used with a
+     * {@link NamedOperation} even though it does not take a name. Using it with
+     * a named operation won't affect its signature; the name is solely meant to
+     * be used as a diagnostic description for error messages.
+     */
+    NEW
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Supplier;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.linker.ConversionComparator;
+import jdk.dynalink.linker.ConversionComparator.Comparison;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardingTypeConverterFactory;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.MethodTypeConversionStrategy;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * A factory for type converters. This class is the main implementation behind the
+ * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory}
+ * instances and creates appropriate converters for method handles.
+ */
+final class TypeConverterFactory {
+    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext("getClassLoader");
+
+    private final GuardingTypeConverterFactory[] factories;
+    private final ConversionComparator[] comparators;
+    private final MethodTypeConversionStrategy autoConversionStrategy;
+
+    private final ClassValue<ClassMap<MethodHandle>> converterMap = new ClassValue<ClassMap<MethodHandle>>() {
+        @Override
+        protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
+            return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
+                @Override
+                protected MethodHandle computeValue(final Class<?> targetType) {
+                    try {
+                        return createConverter(sourceType, targetType);
+                    } catch (final RuntimeException e) {
+                        throw e;
+                    } catch (final Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            };
+        }
+    };
+
+    private final ClassValue<ClassMap<MethodHandle>> converterIdentityMap = new ClassValue<ClassMap<MethodHandle>>() {
+        @Override
+        protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
+            return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
+                @Override
+                protected MethodHandle computeValue(final Class<?> targetType) {
+                    if(!canAutoConvert(sourceType, targetType)) {
+                        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
+                        if(converter != IDENTITY_CONVERSION) {
+                            return converter;
+                        }
+                    }
+                    return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType));
+                }
+            };
+        }
+    };
+
+    private final ClassValue<ClassMap<Boolean>> canConvert = new ClassValue<ClassMap<Boolean>>() {
+        @Override
+        protected ClassMap<Boolean> computeValue(final Class<?> sourceType) {
+            return new ClassMap<Boolean>(getClassLoader(sourceType)) {
+                @Override
+                protected Boolean computeValue(final Class<?> targetType) {
+                    try {
+                        return getTypeConverterNull(sourceType, targetType) != null;
+                    } catch (final RuntimeException e) {
+                        throw e;
+                    } catch (final Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            };
+        }
+    };
+
+    private static ClassLoader getClassLoader(final Class<?> clazz) {
+        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+            @Override
+            public ClassLoader run() {
+                return clazz.getClassLoader();
+            }
+        }, GET_CLASS_LOADER_CONTEXT);
+    }
+
+    /**
+     * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances.
+     *
+     * @param factories the {@link GuardingTypeConverterFactory} instances to compose.
+     * @param autoConversionStrategy conversion strategy for automatic type conversions. After
+     * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom
+     * conversions to a method handle, it still needs to effect
+     * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that
+     * can usually be automatically applied as per
+     * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}.
+     * However, sometimes language runtimes will want to customize even those conversions for their own call
+     * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by
+     * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom
+     * automatic conversion strategy, that can deal with null values. Note that when the strategy's
+     * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)}
+     * is invoked, the custom language conversions will already have been applied to the method handle, so by
+     * design the difference between the handle's current method type and the desired final type will always
+     * only be ones that can be subjected to method invocation conversions. Can be null, in which case no
+     * custom strategy is employed.
+     */
+    TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories,
+            final MethodTypeConversionStrategy autoConversionStrategy) {
+        final List<GuardingTypeConverterFactory> l = new LinkedList<>();
+        final List<ConversionComparator> c = new LinkedList<>();
+        for(final GuardingTypeConverterFactory factory: factories) {
+            l.add(factory);
+            if(factory instanceof ConversionComparator) {
+                c.add((ConversionComparator)factory);
+            }
+        }
+        this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]);
+        this.comparators = c.toArray(new ConversionComparator[c.size()]);
+        this.autoConversionStrategy = autoConversionStrategy;
+    }
+
+    /**
+     * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by
+     * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of
+     * parameters. For all conversions that are not a JLS method invocation conversion it'll insert
+     * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
+     * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation
+     * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first
+     * if an automatic conversion strategy was specified in the
+     * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply
+     * {@link MethodHandle#asType(MethodType)} for any remaining conversions.
+     *
+     * @param handle target method handle
+     * @param fromType the types of source arguments
+     * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)},
+     * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and
+     * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
+     * {@link GuardingTypeConverterFactory} produced type converters as filters.
+     */
+    MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
+        MethodHandle newHandle = handle;
+        final MethodType toType = newHandle.type();
+        final int l = toType.parameterCount();
+        if(l != fromType.parameterCount()) {
+            throw new WrongMethodTypeException("Parameter counts differ: " + handle.type() + " vs. " + fromType);
+        }
+        int pos = 0;
+        final List<MethodHandle> converters = new LinkedList<>();
+        for(int i = 0; i < l; ++i) {
+            final Class<?> fromParamType = fromType.parameterType(i);
+            final Class<?> toParamType = toType.parameterType(i);
+            if(canAutoConvert(fromParamType, toParamType)) {
+                newHandle = applyConverters(newHandle, pos, converters);
+            } else {
+                final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType);
+                if(converter != null) {
+                    if(converters.isEmpty()) {
+                        pos = i;
+                    }
+                    converters.add(converter);
+                } else {
+                    newHandle = applyConverters(newHandle, pos, converters);
+                }
+            }
+        }
+        newHandle = applyConverters(newHandle, pos, converters);
+
+        // Convert return type
+        final Class<?> fromRetType = fromType.returnType();
+        final Class<?> toRetType = toType.returnType();
+        if(fromRetType != Void.TYPE && toRetType != Void.TYPE) {
+            if(!canAutoConvert(toRetType, fromRetType)) {
+                final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType);
+                if(converter != null) {
+                    newHandle = MethodHandles.filterReturnValue(newHandle, converter);
+                }
+            }
+        }
+
+        // Give change to automatic conversion strategy, if one is present.
+        final MethodHandle autoConvertedHandle =
+                autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle;
+
+        // Do a final asType for any conversions that remain.
+        return autoConvertedHandle.asType(fromType);
+    }
+
+    private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List<MethodHandle> converters) {
+        if(converters.isEmpty()) {
+            return handle;
+        }
+        final MethodHandle newHandle =
+                MethodHandles.filterArguments(handle, pos, converters.toArray(new MethodHandle[converters.size()]));
+        converters.clear();
+        return newHandle;
+    }
+
+    /**
+     * Returns true if there might exist a conversion between the requested types (either an automatic JVM conversion,
+     * or one provided by any available {@link GuardingTypeConverterFactory}), or false if there definitely does not
+     * exist a conversion between the requested types. Note that returning true does not guarantee that the conversion
+     * will succeed at runtime (notably, if the "from" or "to" types are sufficiently generic), but returning false
+     * guarantees that it would fail.
+     *
+     * @param from the source type for the conversion
+     * @param to the target type for the conversion
+     * @return true if there can be a conversion, false if there can not.
+     */
+    boolean canConvert(final Class<?> from, final Class<?> to) {
+        return canAutoConvert(from, to) || canConvert.get(from).get(to);
+    }
+
+    /**
+     * Determines which of the two type conversions from a source type to the two target types is preferred. This is
+     * used for dynamic overloaded method resolution. If the source type is convertible to exactly one target type with
+     * a method invocation conversion, it is chosen, otherwise available {@link ConversionComparator}s are consulted.
+     * @param sourceType the source type.
+     * @param targetType1 one potential target type
+     * @param targetType2 another potential target type.
+     * @return one of Comparison constants that establish which - if any - of the target types is preferable for the
+     * conversion.
+     */
+    Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+        for(final ConversionComparator comparator: comparators) {
+            final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2);
+            if(result != Comparison.INDETERMINATE) {
+                return result;
+            }
+        }
+        if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType1)) {
+            if(!TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) {
+                return Comparison.TYPE_1_BETTER;
+            }
+        } else if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) {
+            return Comparison.TYPE_2_BETTER;
+        }
+        return Comparison.INDETERMINATE;
+    }
+
+    /**
+     * Determines whether it's safe to perform an automatic conversion between the source and target class.
+     *
+     * @param fromType convert from this class
+     * @param toType convert to this class
+     * @return true if it's safe to let MethodHandles.convertArguments() to handle this conversion.
+     */
+    /*private*/ static boolean canAutoConvert(final Class<?> fromType, final Class<?> toType) {
+        return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
+    }
+
+    /*private*/ MethodHandle getCacheableTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
+        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
+        return converter == IDENTITY_CONVERSION ? null : converter;
+    }
+
+    /*private*/ MethodHandle getTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
+        try {
+            return getCacheableTypeConverterNull(sourceType, targetType);
+        } catch(final NotCacheableConverter e) {
+            return e.converter;
+        }
+    }
+
+    /*private*/ MethodHandle getCacheableTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
+        return converterMap.get(sourceType).get(targetType);
+    }
+
+    /**
+     * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
+     * case it will return an identity conversion (that might fail for some values at runtime). You can use this method
+     * if you have a piece of your program that is written in Java, and you need to reuse existing type conversion
+     * machinery in a non-invokedynamic context.
+     * @param sourceType the type to convert from
+     * @param targetType the type to convert to
+     * @return a method handle performing the conversion.
+     */
+    MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
+        try {
+            return converterIdentityMap.get(sourceType).get(targetType);
+        } catch(final NotCacheableConverter e) {
+            return e.converter;
+        }
+    }
+
+    private static class LookupSupplier implements Supplier<MethodHandles.Lookup> {
+        volatile boolean returnedLookup;
+        volatile boolean closed;
+
+        @Override
+        public Lookup get() {
+            if (closed) {
+                // Something held on to this supplier and tried to invoke it
+                // after we're done with it.
+                throw new IllegalStateException();
+            }
+            final Lookup lookup = LinkerServicesImpl.getCurrentLookup();
+            returnedLookup = true;
+            return lookup;
+        }
+    }
+
+    /*private*/ MethodHandle createConverter(final Class<?> sourceType, final Class<?> targetType) throws Exception {
+        final MethodType type = MethodType.methodType(targetType, sourceType);
+        final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
+        MethodHandle last = identity;
+
+        final LookupSupplier lookupSupplier = new LookupSupplier();
+        try {
+            for(int i = factories.length; i-- > 0;) {
+                final GuardedInvocation next = factories[i].convertToType(sourceType, targetType, lookupSupplier);
+                if(next != null) {
+                    last = next.compose(last);
+                }
+            }
+        } finally {
+            lookupSupplier.closed = true;
+        }
+
+        if(last == identity) {
+            return IDENTITY_CONVERSION;
+        }
+        if(!lookupSupplier.returnedLookup) {
+            return last;
+        }
+        // At least one of the consulted converter factories obtained the
+        // lookup, so we must presume the created converter is sensitive to the
+        // lookup class and thus we will not cache it.
+        throw new NotCacheableConverter(last);
+    }
+
+    /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
+
+    @SuppressWarnings("serial")
+    private static class NotCacheableConverter extends RuntimeException {
+        final MethodHandle converter;
+
+        NotCacheableConverter(final MethodHandle converter) {
+            super("", null, false, false);
+            this.converter = converter;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,890 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
+import jdk.dynalink.internal.InternalTypeUtilities;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.Guards;
+import jdk.dynalink.linker.support.Lookup;
+import sun.reflect.CallerSensitive;
+
+/**
+ * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
+ * exposure and method calls for both static and instance facets of a class.
+ */
+abstract class AbstractJavaLinker implements GuardingDynamicLinker {
+
+    final Class<?> clazz;
+    private final MethodHandle classGuard;
+    private final MethodHandle assignableGuard;
+    private final Map<String, AnnotatedDynamicMethod> propertyGetters = new HashMap<>();
+    private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
+    private final Map<String, DynamicMethod> methods = new HashMap<>();
+
+    AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard) {
+        this(clazz, classGuard, classGuard);
+    }
+
+    AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) {
+        this.clazz = clazz;
+        this.classGuard = classGuard;
+        this.assignableGuard = assignableGuard;
+
+        final FacetIntrospector introspector = createFacetIntrospector();
+        // Add methods and properties
+        for(final Method method: introspector.getMethods()) {
+            final String name = method.getName();
+            // Add method
+            addMember(name, method, methods);
+            // Add the method as a property getter and/or setter
+            if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
+                // Property getter
+                setPropertyGetter(method, 3);
+            } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
+                    method.getReturnType() == boolean.class) {
+                // Boolean property getter
+                setPropertyGetter(method, 2);
+            } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
+                // Property setter
+                addMember(decapitalize(name.substring(3)), method, propertySetters);
+            }
+        }
+
+        // Add field getter/setters as property getters/setters.
+        for(final Field field: introspector.getFields()) {
+            final String name = field.getName();
+            // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
+            if(!propertyGetters.containsKey(name)) {
+                setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
+            }
+            if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
+                addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name),
+                        propertySetters);
+            }
+        }
+
+        // Add inner classes, but only those for which we don't hide a property with it
+        for(final Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
+            final String name = innerClassSpec.getKey();
+            if(!propertyGetters.containsKey(name)) {
+                setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
+            }
+        }
+    }
+
+    private static String decapitalize(final String str) {
+        assert str != null;
+        if(str.isEmpty()) {
+            return str;
+        }
+
+        final char c0 = str.charAt(0);
+        if(Character.isLowerCase(c0)) {
+            return str;
+        }
+
+        // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize
+        if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) {
+            return str;
+        }
+
+        final char c[] = str.toCharArray();
+        c[0] = Character.toLowerCase(c0);
+        return new String(c);
+    }
+
+    abstract FacetIntrospector createFacetIntrospector();
+
+    Set<String> getReadablePropertyNames() {
+        return getUnmodifiableKeys(propertyGetters);
+    }
+
+    Set<String> getWritablePropertyNames() {
+        return getUnmodifiableKeys(propertySetters);
+    }
+
+    Set<String> getMethodNames() {
+        return getUnmodifiableKeys(methods);
+    }
+
+    private static Set<String> getUnmodifiableKeys(final Map<String, ?> m) {
+        return Collections.unmodifiableSet(m.keySet());
+    }
+
+    /**
+     * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only
+     * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
+     * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
+     * instead.
+     * @param name name of the property
+     * @param handle the method handle that implements the property getter
+     * @param validationType the validation type for the property
+     */
+    private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) {
+        propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
+    }
+
+    /**
+     * Sets the specified reflective method to be the property getter for the specified property.
+     * @param getter the getter method
+     * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
+     * names starting with "is".
+     */
+    private void setPropertyGetter(final Method getter, final int prefixLen) {
+        setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
+                getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
+    }
+
+    /**
+     * Sets the specified method handle to be the property getter for the specified property. Note that you can only
+     * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
+     * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
+     * instead.
+     * @param name name of the property
+     * @param handle the method handle that implements the property getter
+     * @param validationType the validation type for the property
+     */
+    void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) {
+        setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
+    }
+
+    private void addMember(final String name, final AccessibleObject ao, final Map<String, DynamicMethod> methodMap) {
+        addMember(name, createDynamicMethod(ao), methodMap);
+    }
+
+    private void addMember(final String name, final SingleDynamicMethod method, final Map<String, DynamicMethod> methodMap) {
+        final DynamicMethod existingMethod = methodMap.get(name);
+        final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
+        if(newMethod != existingMethod) {
+            methodMap.put(name, newMethod);
+        }
+    }
+
+    /**
+     * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The
+     * methods should represent all overloads of the same name (or all constructors of the class).
+     * @param members the reflective members
+     * @param clazz the class declaring the reflective members
+     * @param name the common name of the reflective members.
+     * @return a dynamic method representing all the specified reflective members.
+     */
+    static DynamicMethod createDynamicMethod(final Iterable<? extends AccessibleObject> members, final Class<?> clazz, final String name) {
+        DynamicMethod dynMethod = null;
+        for(final AccessibleObject method: members) {
+            dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
+        }
+        return dynMethod;
+    }
+
+    /**
+     * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will
+     * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive
+     * dynamic method when needed.
+     * @param m the reflective member
+     * @return the single dynamic method representing the reflective member
+     */
+    private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) {
+        if (m.isAnnotationPresent(CallerSensitive.class)) {
+            // Method has @CallerSensitive annotation
+            return new CallerSensitiveDynamicMethod(m);
+        }
+        // Method has no @CallerSensitive annotation
+        final MethodHandle mh;
+        try {
+            mh = unreflectSafely(m);
+        } catch (final IllegalAccessError e) {
+            // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't
+            // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive.
+            return new CallerSensitiveDynamicMethod(m);
+        }
+        // Proceed with non-caller sensitive
+        final Member member = (Member)m;
+        return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor);
+    }
+
+    /**
+     * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be
+     * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were
+     * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege
+     * unreflector as its caller, and thus completely useless.
+     * @param m the method or constructor
+     * @return the method handle
+     */
+    private static MethodHandle unreflectSafely(final AccessibleObject m) {
+        if(m instanceof Method) {
+            final Method reflMethod = (Method)m;
+            final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod);
+            if(Modifier.isStatic(reflMethod.getModifiers())) {
+                return StaticClassIntrospector.editStaticMethodHandle(handle);
+            }
+            return handle;
+        }
+        return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor<?>)m));
+    }
+
+    private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class<?> clazz, final String name) {
+        if(existing == null) {
+            return method;
+        } else if(existing.contains(method)) {
+            return existing;
+        } else if(existing instanceof SingleDynamicMethod) {
+            final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name);
+            odm.addMethod(((SingleDynamicMethod)existing));
+            odm.addMethod(method);
+            return odm;
+        } else if(existing instanceof OverloadedDynamicMethod) {
+            ((OverloadedDynamicMethod)existing).addMethod(method);
+            return existing;
+        }
+        throw new AssertionError();
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
+            throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
+
+        // Handle NamedOperation(CALL_METHOD, name) separately
+        final Operation operation = callSiteDescriptor.getOperation();
+        if (operation instanceof NamedOperation) {
+            final NamedOperation namedOperation = (NamedOperation)operation;
+            if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) {
+                return createGuardedDynamicMethodInvocation(callSiteDescriptor,
+                        linkerServices, namedOperation.getName().toString(), methods);
+            }
+        }
+
+        List<Operation> operations = Arrays.asList(
+                CompositeOperation.getOperations(
+                        NamedOperation.getBaseOperation(operation)));
+        final Object name = NamedOperation.getName(operation);
+
+        while(!operations.isEmpty()) {
+            final GuardedInvocationComponent gic =
+                    getGuardedInvocationComponent(callSiteDescriptor,
+                            linkerServices, operations, name);
+            if(gic != null) {
+                return gic.getGuardedInvocation();
+            }
+            operations = pop(operations);
+        }
+        return null;
+    }
+
+    protected GuardedInvocationComponent getGuardedInvocationComponent(
+            final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices,
+            final List<Operation> operations, final Object name)
+    throws Exception {
+        if(operations.isEmpty()) {
+            return null;
+        }
+        final Operation op = operations.get(0);
+        // Either GET_PROPERTY:name(this) or GET_PROPERTY(this, name)
+        if(op == StandardOperation.GET_PROPERTY) {
+            return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        }
+        // Either SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value)
+        if(op == StandardOperation.SET_PROPERTY) {
+            return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        }
+        // Either GET_METHOD:name(this), or GET_METHOD(this, name)
+        if(op == StandardOperation.GET_METHOD) {
+            return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        }
+        return null;
+    }
+
+    static final <T> List<T> pop(final List<T> l) {
+        return l.subList(1, l.size());
+    }
+
+    MethodHandle getClassGuard(final CallSiteDescriptor desc) {
+        return getClassGuard(desc.getMethodType());
+    }
+
+    MethodHandle getClassGuard(final MethodType type) {
+        return Guards.asType(classGuard, type);
+    }
+
+    GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) {
+        return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
+    }
+
+    abstract SingleDynamicMethod getConstructorMethod(final String signature);
+
+    private MethodHandle getAssignableGuard(final MethodType type) {
+        return Guards.asType(assignableGuard, type);
+    }
+
+    private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap){
+        final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
+        return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
+    }
+
+    private MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap) {
+        final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
+        return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
+    }
+
+    private DynamicMethod getDynamicMethod(final String methodName, final Map<String, DynamicMethod> methodMap) {
+        final DynamicMethod dynaMethod = methodMap.get(methodName);
+        return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
+    }
+
+    private SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName,
+            final Map<String, DynamicMethod> methodsMap) {
+        // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
+        // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
+        // resolution works correctly in almost every situation. However, in presence of many language-specific
+        // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected
+        // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload
+        // for performance reasons.
+
+        // Is the method name lexically of the form "name(types)"?
+        final int lastChar = fullName.length() - 1;
+        if(fullName.charAt(lastChar) != ')') {
+            return null;
+        }
+        final int openBrace = fullName.indexOf('(');
+        if(openBrace == -1) {
+            return null;
+        }
+
+        final String name = fullName.substring(0, openBrace);
+        final String signature = fullName.substring(openBrace + 1, lastChar);
+
+        // Find an existing method for the "name" part
+        final DynamicMethod simpleNamedMethod = methodsMap.get(name);
+        if(simpleNamedMethod == null) {
+            // explicit signature constructor access
+            // Java.type("java.awt.Color")["(int,int,int)"]
+            // will get Color(int,int,int) constructor of Color class.
+            if (name.isEmpty()) {
+                return getConstructorMethod(signature);
+            }
+
+            return null;
+        }
+
+        // Try to get a narrowed dynamic method for the explicit parameter types.
+        return simpleNamedMethod.getMethodForExactParamTypes(signature);
+    }
+
+    private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
+            boolean.class, MethodHandle.class));
+    private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
+            MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
+
+    private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+        if (name == null) {
+            return getUnnamedPropertySetter(callSiteDescriptor, linkerServices, operations);
+        }
+        return getNamedPropertySetter(callSiteDescriptor, linkerServices, operations, name);
+    }
+
+    private GuardedInvocationComponent getUnnamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations) throws Exception {
+        // Must have three arguments: target object, property name, and property value.
+        assertParameterCount(callSiteDescriptor, 3);
+
+        // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
+        // valid for us to convert return values proactively. Also, since we don't know what setters will be
+        // invoked, we'll conservatively presume Object return type. The one exception is void return.
+        final MethodType origType = callSiteDescriptor.getMethodType();
+        final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);
+
+        // What's below is basically:
+        //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
+        //     get_setter_handle(type, linkerServices))
+        // only with a bunch of method signature adjustments. Basically, retrieve method setter
+        // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
+        // component's invocation.
+
+        // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
+        // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
+        // Object return type).
+        final MethodType setterType = type.dropParameterTypes(1, 2);
+        // Bind property setter handle to the expected setter type and linker services. Type is
+        // MethodHandle(Object, String, Object)
+        final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
+                callSiteDescriptor.changeMethodType(setterType), linkerServices);
+
+        // Cast getter to MethodHandle(O, N, V)
+        final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
+                MethodHandle.class));
+
+        // Handle to invoke the setter R(MethodHandle, O, V)
+        final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
+        // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
+        final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
+                1));
+        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
+                linkerServices, operations, null);
+
+        final MethodHandle fallbackFolded;
+        if(nextComponent == null) {
+            // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
+            fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
+                    type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
+        } else {
+            // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
+            // extra argument resulting from fold
+            fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
+                    0, MethodHandle.class);
+        }
+
+        // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
+        final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
+                    IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
+        if(nextComponent == null) {
+            return getClassGuardedInvocationComponent(compositeSetter, type);
+        }
+        return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
+    }
+
+    private GuardedInvocationComponent getNamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+        // Must have two arguments: target object and property value
+        assertParameterCount(callSiteDescriptor, 2);
+        final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
+                name.toString(), propertySetters);
+        // If we have a property setter with this name, this composite operation will always stop here
+        if(gi != null) {
+            return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
+        }
+        // If we don't have a property setter with this name, always fall back to the next operation in the
+        // composite (if any)
+        return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations, name);
+    }
+
+    private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
+
+    private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
+            boolean.class, AnnotatedDynamicMethod.class));
+    private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
+            MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
+    private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
+            "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class));
+    private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
+
+    private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
+        if (name == null) {
+            return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops);
+        }
+
+        return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name);
+    }
+
+    private GuardedInvocationComponent getUnnamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops) throws Exception {
+        // Since we can't know what kind of a getter we'll get back on different invocations, we'll just
+        // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking
+        // runtime might not allow coercing at that call site.
+        final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
+        // Must have exactly two arguments: receiver and name
+        assertParameterCount(callSiteDescriptor, 2);
+
+        // What's below is basically:
+        //   foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle)
+        // only with a bunch of method signature adjustments. Basically, retrieve method getter
+        // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null,
+        // or delegate to next component's invocation.
+
+        final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
+                AnnotatedDynamicMethod.class));
+        final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
+                GET_ANNOTATED_METHOD, 1, callSiteDescriptor, linkerServices);
+        final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
+                callSiteBoundMethodGetter);
+        // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
+        final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
+                MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
+        // Since it's in the target of a fold, drop the unnecessary second argument
+        // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1)
+        final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
+                type.parameterType(1));
+        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
+                linkerServices, ops, null);
+
+        final MethodHandle fallbackFolded;
+        if(nextComponent == null) {
+            // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null
+            fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
+                    type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
+        } else {
+            // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to
+            // drop the extra argument resulting from fold and to change its return type to Object.
+            final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation();
+            final MethodType nextType = nextInvocation.type();
+            fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType(
+                    nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class);
+        }
+
+        // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
+        final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
+                    IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
+        if(nextComponent == null) {
+            return getClassGuardedInvocationComponent(compositeGetter, type);
+        }
+        return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
+    }
+
+    private GuardedInvocationComponent getNamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
+        // Must have exactly one argument: receiver
+        assertParameterCount(callSiteDescriptor, 1);
+        // Fixed name
+        final AnnotatedDynamicMethod annGetter = propertyGetters.get(name.toString());
+        if(annGetter == null) {
+            // We have no such property, always delegate to the next component operation
+            return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
+        }
+        final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices);
+        // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
+        // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
+        // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
+        // we're linking against a field getter, don't make the assumption.
+        // NOTE: No delegation to the next component operation if we have a property with this name, even if its
+        // value is null.
+        final ValidationType validationType = annGetter.validationType;
+        // TODO: we aren't using the type that declares the most generic getter here!
+        return new GuardedInvocationComponent(getter, getGuard(validationType,
+                callSiteDescriptor.getMethodType()), clazz, validationType);
+    }
+
+    private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) {
+        switch(validationType) {
+            case EXACT_CLASS: {
+                return getClassGuard(methodType);
+            }
+            case INSTANCE_OF: {
+                return getAssignableGuard(methodType);
+            }
+            case IS_ARRAY: {
+                return Guards.isArray(0, methodType);
+            }
+            case NONE: {
+                return null;
+            }
+            default: {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class,
+            MethodType.methodType(boolean.class, Object.class));
+    private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class);
+
+    private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
+        // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to
+        // be visible outside of this linker, declare it to return Object.
+        final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
+        if (name == null) {
+            return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type);
+        }
+
+        return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type);
+    }
+
+    private GuardedInvocationComponent getUnnamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops, final MethodType type) throws Exception {
+        // Must have exactly two arguments: receiver and name
+        assertParameterCount(callSiteDescriptor, 2);
+        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
+                linkerServices, ops, null);
+        if(nextComponent == null || !InternalTypeUtilities.areAssignable(DynamicMethod.class,
+                nextComponent.getGuardedInvocation().getInvocation().type().returnType())) {
+            // No next component operation, or it can never produce a dynamic method; just return a component
+            // for this operation.
+            return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
+        }
+
+        // What's below is basically:
+        // foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) only with a
+        // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
+        // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
+
+        final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type);
+        // Since it is part of the foldArgument() target, it will have extra args that we need to drop.
+        final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
+                OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class));
+        final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
+        // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the
+        // return type.
+        assert nextComponentInvocation.type().changeReturnType(type.returnType()).equals(type);
+        // Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
+        final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
+                Object.class);
+        // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
+        final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
+                IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter);
+
+        return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
+    }
+
+    private GuardedInvocationComponent getNamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> ops, final Object name, final MethodType type)
+            throws Exception {
+        // Must have exactly one argument: receiver
+        assertParameterCount(callSiteDescriptor, 1);
+        final DynamicMethod method = getDynamicMethod(name.toString());
+        if(method == null) {
+            // We have no such method, always delegate to the next component
+            return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
+        }
+        // No delegation to the next component of the composite operation; if we have a method with that name,
+        // we'll always return it at this point.
+        return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
+                MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
+    }
+
+    static class MethodPair {
+        final MethodHandle method1;
+        final MethodHandle method2;
+
+        MethodPair(final MethodHandle method1, final MethodHandle method2) {
+            this.method1 = method1;
+            this.method2 = method2;
+        }
+
+        MethodHandle guardWithTest(final MethodHandle test) {
+            return MethodHandles.guardWithTest(test, method1, method2);
+        }
+    }
+
+    static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) {
+        final MethodType type1 = m1.type();
+        final MethodType type2 = m2.type();
+        final Class<?> commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(),
+                type2.returnType());
+        return new MethodPair(
+                m1.asType(type1.changeReturnType(commonRetType)),
+                m2.asType(type2.changeReturnType(commonRetType)));
+    }
+
+    private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
+        if(descriptor.getMethodType().parameterCount() != paramCount) {
+            throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters.");
+        }
+    }
+
+    private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
+            "getPropertyGetterHandle", Object.class, Object.class), 1, Object.class);
+    private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this);
+
+    /**
+     * @param id the property ID
+     * @return the method handle for retrieving the property, or null if the property does not exist
+     */
+    @SuppressWarnings("unused")
+    private Object getPropertyGetterHandle(final Object id) {
+        return propertyGetters.get(id);
+    }
+
+    // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
+    // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is
+    // a typical property setter with variable name signature (target, name, value).
+    private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments(
+            privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class,
+                    LinkerServices.class, Object.class), 3, Object.class), 5, Object.class);
+    // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object)
+    private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
+
+    @SuppressWarnings("unused")
+    private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices,
+            final Object id) {
+        return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
+    }
+
+    private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
+            "getDynamicMethod", Object.class, Object.class), 1, Object.class);
+    private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
+
+    @SuppressWarnings("unused")
+    // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't
+    // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for
+    // GET_METHOD linking).
+    private Object getDynamicMethod(final Object name) {
+        return getDynamicMethod(String.valueOf(name), methods);
+    }
+
+    /**
+     * Returns a dynamic method of the specified name.
+     *
+     * @param name name of the method
+     * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
+     * method with the specified name does not exist.
+     */
+    DynamicMethod getDynamicMethod(final String name) {
+        return getDynamicMethod(name, methods);
+    }
+
+    /**
+     * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the
+     * receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one,
+     * creating more stable call sites.
+     * @param getter the getter
+     * @return getter with same name, declared on the most generic superclass/interface of the declaring class
+     */
+    private static Method getMostGenericGetter(final Method getter) {
+        return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
+    }
+
+    private static Method getMostGenericGetter(final String name, final Class<?> returnType, final Class<?> declaringClass) {
+        if(declaringClass == null) {
+            return null;
+        }
+        // Prefer interfaces
+        for(final Class<?> itf: declaringClass.getInterfaces()) {
+            final Method itfGetter = getMostGenericGetter(name, returnType, itf);
+            if(itfGetter != null) {
+                return itfGetter;
+            }
+        }
+        final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass());
+        if(superGetter != null) {
+            return superGetter;
+        }
+        if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
+            try {
+                return declaringClass.getMethod(name);
+            } catch(final NoSuchMethodException e) {
+                // Intentionally ignored, meant to fall through
+            }
+        }
+        return null;
+    }
+
+    private static final class AnnotatedDynamicMethod {
+        private final SingleDynamicMethod method;
+        /*private*/ final ValidationType validationType;
+
+        AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) {
+            this.method = method;
+            this.validationType = validationType;
+        }
+
+        MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
+            return method.getInvocation(callSiteDescriptor, linkerServices);
+        }
+
+        @SuppressWarnings("unused")
+        MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) {
+            final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc));
+            assert inv != null;
+            return inv;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class for discovering accessible methods and inner classes. Normally, a public member declared on a class is
+ * accessible (that is, it can be invoked from anywhere). However, this is not the case if the class itself is not
+ * public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly
+ * accessible superclass or implemented interface of the class, and use it instead of the member discovered on the
+ * class.
+ */
+class AccessibleMembersLookup {
+    private final Map<MethodSignature, Method> methods;
+    private final Set<Class<?>> innerClasses;
+    private final boolean instance;
+
+    /**
+     * Creates a mapping for all accessible methods and inner classes on a class.
+     *
+     * @param clazz the inspected class
+     * @param instance true to inspect instance methods, false to inspect static methods.
+     */
+    AccessibleMembersLookup(final Class<?> clazz, final boolean instance) {
+        this.methods = new HashMap<>();
+        this.innerClasses = new LinkedHashSet<>();
+        this.instance = instance;
+        lookupAccessibleMembers(clazz);
+    }
+
+    /**
+     * Returns an accessible method equivalent of a method.
+     *
+     * @param m the method whose accessible equivalent is requested.
+     * @return the accessible equivalent for the method (can be the same as the passed in method), or null if there is
+     * no accessible method equivalent.
+     */
+    Method getAccessibleMethod(final Method m) {
+        return m == null ? null : methods.get(new MethodSignature(m));
+    }
+
+    Collection<Method> getMethods() {
+        return methods.values();
+    }
+
+    Class<?>[] getInnerClasses() {
+        return innerClasses.toArray(new Class<?>[innerClasses.size()]);
+    }
+
+    /**
+     * A helper class that represents a method signature - name and argument types.
+     */
+    static final class MethodSignature {
+        private final String name;
+        private final Class<?>[] args;
+
+        /**
+         * Creates a new method signature from arbitrary data.
+         *
+         * @param name the name of the method this signature represents.
+         * @param args the argument types of the method.
+         */
+        MethodSignature(final String name, final Class<?>[] args) {
+            this.name = name;
+            this.args = args;
+        }
+
+        /**
+         * Creates a signature for the given method.
+         *
+         * @param method the method for which a signature is created.
+         */
+        MethodSignature(final Method method) {
+            this(method.getName(), method.getParameterTypes());
+        }
+
+        /**
+         * Compares this object to another object
+         *
+         * @param o the other object
+         * @return true if the other object is also a method signature with the same name, same number of arguments, and
+         * same types of arguments.
+         */
+        @Override
+        public boolean equals(final Object o) {
+            if(o instanceof MethodSignature) {
+                final MethodSignature ms = (MethodSignature)o;
+                return ms.name.equals(name) && Arrays.equals(args, ms.args);
+            }
+            return false;
+        }
+
+        /**
+         * Returns a hash code, consistent with the overridden {@link #equals(Object)}.
+         */
+        @Override
+        public int hashCode() {
+            return name.hashCode() ^ Arrays.hashCode(args);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder b = new StringBuilder();
+            b.append("[MethodSignature ").append(name).append('(');
+            if(args.length > 0) {
+                b.append(args[0].getCanonicalName());
+                for(int i = 1; i < args.length; ++i) {
+                    b.append(", ").append(args[i].getCanonicalName());
+                }
+            }
+            return b.append(")]").toString();
+        }
+    }
+
+    private void lookupAccessibleMembers(final Class<?> clazz) {
+        boolean searchSuperTypes;
+
+        if(!CheckRestrictedPackage.isRestrictedClass(clazz)) {
+            searchSuperTypes = false;
+            for(final Method method: clazz.getMethods()) {
+                final boolean isStatic = Modifier.isStatic(method.getModifiers());
+                if(instance != isStatic) {
+                    final MethodSignature sig = new MethodSignature(method);
+                    if(!methods.containsKey(sig)) {
+                        final Class<?> declaringClass = method.getDeclaringClass();
+                        if(declaringClass != clazz && CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
+                            //Sometimes, the declaring class of a method (Method.getDeclaringClass())
+                            //retrieved through Class.getMethods() for a public class will be a
+                            //non-public superclass. For such a method, we need to find a method with
+                            //the same name and signature in a public superclass or implemented
+                            //interface.
+                            //This typically doesn't happen with classes emitted by a reasonably modern
+                            //javac, as it'll create synthetic delegator methods in all public
+                            //immediate subclasses of the non-public class. We have, however, observed
+                            //this in the wild with class files compiled with older javac that doesn't
+                            //generate the said synthetic delegators.
+                            searchSuperTypes = true;
+                        } else {
+                            // don't allow inherited static
+                            if (!isStatic || clazz == declaringClass) {
+                                methods.put(sig, method);
+                            }
+                        }
+                    }
+                }
+            }
+            for(final Class<?> innerClass: clazz.getClasses()) {
+                // Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just
+                // expose non-static classes with explicit constructor outer class argument.
+                // NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes
+                // were not yet loaded, they'll only get loaded in a non-resolved state; no static initializers for
+                // them will trigger just by doing this.
+                innerClasses.add(innerClass);
+            }
+        } else {
+            searchSuperTypes = true;
+        }
+
+        // don't need to search super types for static methods
+        if(instance && searchSuperTypes) {
+            // If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is
+            // public, but some of its methods claim that their declaring class is non-public. We'll try superclasses
+            // and implemented interfaces then looking for public ones.
+            final Class<?>[] interfaces = clazz.getInterfaces();
+            for(int i = 0; i < interfaces.length; i++) {
+                lookupAccessibleMembers(interfaces[i]);
+            }
+            final Class<?> superclass = clazz.getSuperclass();
+            if(superclass != null) {
+                lookupAccessibleMembers(superclass);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ApplicableOverloadedMethods.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodType;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * Represents overloaded methods applicable to a specific call site signature.
+ */
+class ApplicableOverloadedMethods {
+    private final List<SingleDynamicMethod> methods;
+    private final boolean varArgs;
+
+    /**
+     * Creates a new ApplicableOverloadedMethods instance
+     *
+     * @param methods a list of all overloaded methods with the same name for a class.
+     * @param callSiteType the type of the call site
+     * @param test applicability test. One of {@link #APPLICABLE_BY_SUBTYPING},
+     * {@link #APPLICABLE_BY_METHOD_INVOCATION_CONVERSION}, or {@link #APPLICABLE_BY_VARIABLE_ARITY}.
+     */
+    ApplicableOverloadedMethods(final List<SingleDynamicMethod> methods, final MethodType callSiteType,
+            final ApplicabilityTest test) {
+        this.methods = new LinkedList<>();
+        for(final SingleDynamicMethod m: methods) {
+            if(test.isApplicable(callSiteType, m)) {
+                this.methods.add(m);
+            }
+        }
+        varArgs = test == APPLICABLE_BY_VARIABLE_ARITY;
+    }
+
+    /**
+     * Retrieves all the methods this object holds.
+     *
+     * @return list of all methods.
+     */
+    List<SingleDynamicMethod> getMethods() {
+        return methods;
+    }
+
+    /**
+     * Returns a list of all methods in this objects that are maximally specific.
+     *
+     * @return a list of maximally specific methods.
+     */
+    List<SingleDynamicMethod> findMaximallySpecificMethods() {
+        return MaximallySpecific.getMaximallySpecificMethods(methods, varArgs);
+    }
+
+    abstract static class ApplicabilityTest {
+        abstract boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method);
+    }
+
+    /**
+     * Implements the applicability-by-subtyping test from JLS 15.12.2.2.
+     */
+    static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() {
+        @Override
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
+            final MethodType methodType = method.getMethodType();
+            final int methodArity = methodType.parameterCount();
+            if(methodArity != callSiteType.parameterCount()) {
+                return false;
+            }
+            // 0th arg is receiver; it doesn't matter for overload
+            // resolution.
+            for(int i = 1; i < methodArity; ++i) {
+                if(!TypeUtilities.isSubtype(callSiteType.parameterType(i), methodType.parameterType(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Implements the applicability-by-method-invocation-conversion test from JLS 15.12.2.3.
+     */
+    static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() {
+        @Override
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
+            final MethodType methodType = method.getMethodType();
+            final int methodArity = methodType.parameterCount();
+            if(methodArity != callSiteType.parameterCount()) {
+                return false;
+            }
+            // 0th arg is receiver; it doesn't matter for overload
+            // resolution.
+            for(int i = 1; i < methodArity; ++i) {
+                if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i),
+                        methodType.parameterType(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Implements the applicability-by-variable-arity test from JLS 15.12.2.4.
+     */
+    static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() {
+        @Override
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
+            if(!method.isVarArgs()) {
+                return false;
+            }
+            final MethodType methodType = method.getMethodType();
+            final int methodArity = methodType.parameterCount();
+            final int fixArity = methodArity - 1;
+            final int callSiteArity = callSiteType.parameterCount();
+            if(fixArity > callSiteArity) {
+                return false;
+            }
+            // 0th arg is receiver; it doesn't matter for overload
+            // resolution.
+            for(int i = 1; i < fixArity; ++i) {
+                if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i),
+                        methodType.parameterType(i))) {
+                    return false;
+                }
+            }
+            final Class<?> varArgType = methodType.parameterType(fixArity).getComponentType();
+            for(int i = fixArity; i < callSiteArity; ++i) {
+                if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), varArgType)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanIntrospector.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.util.Collections;
+import java.util.Map;
+
+class BeanIntrospector extends FacetIntrospector {
+    BeanIntrospector(final Class<?> clazz) {
+        super(clazz, true);
+    }
+
+    @Override
+    Map<String, MethodHandle> getInnerClassGetters() {
+        return Collections.emptyMap(); // NOTE: non-static inner classes are also on StaticClassIntrospector.
+    }
+
+    @Override
+    MethodHandle editMethodHandle(final MethodHandle mh) {
+        return mh;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.support.Guards;
+import jdk.dynalink.linker.support.Lookup;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by
+ * {@link BeansLinker}.
+ */
+class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker {
+    BeanLinker(final Class<?> clazz) {
+        super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz));
+        if(clazz.isArray()) {
+            // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an
+            // explicit property is beneficial for them.
+            // REVISIT: is it maybe a code smell that StandardOperation.GET_LENGTH is not needed?
+            setPropertyGetter("length", GET_ARRAY_LENGTH, ValidationType.IS_ARRAY);
+        } else if(List.class.isAssignableFrom(clazz)) {
+            setPropertyGetter("length", GET_COLLECTION_LENGTH, ValidationType.INSTANCE_OF);
+        }
+    }
+
+    @Override
+    public boolean canLinkType(final Class<?> type) {
+        return type == clazz;
+    }
+
+    @Override
+    FacetIntrospector createFacetIntrospector() {
+        return new BeanIntrospector(clazz);
+    }
+
+    @Override
+    protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+        final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor,
+                linkerServices, operations, name);
+        if(superGic != null) {
+            return superGic;
+        }
+        if(operations.isEmpty()) {
+            return null;
+        }
+        final Operation op = operations.get(0);
+        if(op == StandardOperation.GET_ELEMENT) {
+            return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        }
+        if(op == StandardOperation.SET_ELEMENT) {
+            return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        }
+        if(op == StandardOperation.GET_LENGTH) {
+            return getLengthGetter(callSiteDescriptor);
+        }
+        return null;
+    }
+
+    @Override
+    SingleDynamicMethod getConstructorMethod(final String signature) {
+        return null;
+    }
+
+    private static final MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get",
+            MethodType.methodType(Object.class, int.class));
+
+    private static final MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get",
+            MethodType.methodType(Object.class, Object.class));
+
+    private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
+    private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
+
+    private enum CollectionType {
+        ARRAY, LIST, MAP
+    };
+
+    private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+        final MethodType callSiteType = callSiteDescriptor.getMethodType();
+        final Class<?> declaredType = callSiteType.parameterType(0);
+        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
+                linkerServices, operations, name);
+
+        // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
+        // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
+        // dealing with an array, or a list or map, but hey...
+        // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
+        // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
+        final GuardedInvocationComponent gic;
+        final CollectionType collectionType;
+        if(declaredType.isArray()) {
+            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
+            collectionType = CollectionType.ARRAY;
+        } else if(List.class.isAssignableFrom(declaredType)) {
+            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
+            collectionType = CollectionType.LIST;
+        } else if(Map.class.isAssignableFrom(declaredType)) {
+            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
+            collectionType = CollectionType.MAP;
+        } else if(clazz.isArray()) {
+            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
+            collectionType = CollectionType.ARRAY;
+        } else if(List.class.isAssignableFrom(clazz)) {
+            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.LIST;
+        } else if(Map.class.isAssignableFrom(clazz)) {
+            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.MAP;
+        } else {
+            // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
+            return nextComponent;
+        }
+
+        // Convert the key to a number if we're working with a list or array
+        final Object typedName;
+        if(collectionType != CollectionType.MAP && name != null) {
+            typedName = convertKeyToInteger(name, linkerServices);
+            if(typedName == null) {
+                // key is not numeric, it can never succeed
+                return nextComponent;
+            }
+        } else {
+            typedName = name;
+        }
+
+        final GuardedInvocation gi = gic.getGuardedInvocation();
+        final Binder binder = new Binder(linkerServices, callSiteType, typedName);
+        final MethodHandle invocation = gi.getInvocation();
+
+        if(nextComponent == null) {
+            return gic.replaceInvocation(binder.bind(invocation));
+        }
+
+        final MethodHandle checkGuard;
+        switch(collectionType) {
+        case LIST:
+            checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
+            break;
+        case MAP:
+            // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
+            // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
+            // that returns constant null (on true), or falls back to next component (on false)
+            checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
+            break;
+        case ARRAY:
+            checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
+            break;
+        default:
+            throw new AssertionError();
+        }
+        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+                nextComponent.getGuardedInvocation().getInvocation());
+        return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
+                gic.getValidatorClass(), gic.getValidationType());
+    }
+
+    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
+            final MethodHandle invocation, final LinkerServices linkerServices) {
+        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation));
+    }
+
+    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
+            final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
+            final ValidationType validationType, final LinkerServices linkerServices) {
+        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation), guard,
+                validatorClass, validationType);
+    }
+
+    private static Integer convertKeyToInteger(final Object fixedKey, final LinkerServices linkerServices) throws Exception {
+        if (fixedKey instanceof Integer) {
+            return (Integer)fixedKey;
+        }
+
+        final Number n;
+        if (fixedKey instanceof Number) {
+            n = (Number)fixedKey;
+        } else {
+            final Class<?> keyClass = fixedKey.getClass();
+            if(linkerServices.canConvert(keyClass, Number.class)) {
+                final Object val;
+                try {
+                    val = linkerServices.getTypeConverter(keyClass, Number.class).invoke(fixedKey);
+                } catch(Exception|Error e) {
+                    throw e;
+                } catch(final Throwable t) {
+                    throw new RuntimeException(t);
+                }
+                if(!(val instanceof Number)) {
+                    return null; // not a number
+                }
+                n = (Number)val;
+            } else if (fixedKey instanceof String){
+                try {
+                    return Integer.valueOf((String)fixedKey);
+                } catch(final NumberFormatException e) {
+                    // key is not a number
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        }
+
+        if(n instanceof Integer) {
+            return (Integer)n;
+        }
+        final int intIndex = n.intValue();
+        final double doubleValue = n.doubleValue();
+        if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinites trigger IOOBE
+            return null; // not an exact integer
+        }
+        return intIndex;
+    }
+
+    private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) {
+        final Class<?> sourceType = desc.getMethodType().parameterType(1);
+        if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) {
+            return mh;
+        } else if(ls.canConvert(sourceType, Number.class)) {
+            final MethodHandle converter = ls.getTypeConverter(sourceType, Number.class);
+            return MethodHandles.filterArguments(mh, 1, converter.asType(converter.type().changeReturnType(
+                    mh.type().parameterType(1))));
+        }
+        return mh;
+    }
+
+    /**
+     * Contains methods to adapt an item getter/setter method handle to the requested type, optionally binding it to a
+     * fixed key first.
+     */
+    private static class Binder {
+        private final LinkerServices linkerServices;
+        private final MethodType methodType;
+        private final Object fixedKey;
+
+        Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) {
+            this.linkerServices = linkerServices;
+            this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass());
+            this.fixedKey = fixedKey;
+        }
+
+        /*private*/ MethodHandle bind(final MethodHandle handle) {
+            return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType));
+        }
+
+        /*private*/ MethodHandle bindTest(final MethodHandle handle) {
+            return bindToFixedKey(Guards.asType(handle, methodType));
+        }
+
+        private MethodHandle bindToFixedKey(final MethodHandle handle) {
+            return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey);
+        }
+    }
+
+    private static final MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class);
+    private static final MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class);
+    private static final MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
+            MethodType.methodType(boolean.class, Object.class));
+
+    private static MethodHandle findRangeCheck(final Class<?> collectionType) {
+        return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class);
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean rangeCheck(final Object array, final Object index) {
+        if(!(index instanceof Number)) {
+            return false;
+        }
+        final Number n = (Number)index;
+        final int intIndex = n.intValue();
+        final double doubleValue = n.doubleValue();
+        if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE
+            return false;
+        }
+        if(0 <= intIndex && intIndex < Array.getLength(array)) {
+            return true;
+        }
+        throw new ArrayIndexOutOfBoundsException("Array index out of range: " + n);
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean rangeCheck(final List<?> list, final Object index) {
+        if(!(index instanceof Number)) {
+            return false;
+        }
+        final Number n = (Number)index;
+        final int intIndex = n.intValue();
+        final double doubleValue = n.doubleValue();
+        if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE
+            return false;
+        }
+        if(0 <= intIndex && intIndex < list.size()) {
+            return true;
+        }
+        throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size());
+    }
+
+    private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set",
+            MethodType.methodType(Object.class, int.class, Object.class));
+
+    private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
+            MethodType.methodType(Object.class, Object.class, Object.class));
+
+    private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+        final MethodType callSiteType = callSiteDescriptor.getMethodType();
+        final Class<?> declaredType = callSiteType.parameterType(0);
+
+        final GuardedInvocationComponent gic;
+        // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
+        // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
+        // dealing with an array, or a list or map, but hey...
+        // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
+        // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
+        final CollectionType collectionType;
+        if(declaredType.isArray()) {
+            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
+            collectionType = CollectionType.ARRAY;
+        } else if(List.class.isAssignableFrom(declaredType)) {
+            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
+            collectionType = CollectionType.LIST;
+        } else if(Map.class.isAssignableFrom(declaredType)) {
+            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
+            collectionType = CollectionType.MAP;
+        } else if(clazz.isArray()) {
+            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
+                    MethodHandles.arrayElementSetter(clazz)), callSiteType);
+            collectionType = CollectionType.ARRAY;
+        } else if(List.class.isAssignableFrom(clazz)) {
+            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.LIST;
+        } else if(Map.class.isAssignableFrom(clazz)) {
+            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
+                    Map.class, ValidationType.INSTANCE_OF, linkerServices);
+            collectionType = CollectionType.MAP;
+        } else {
+            // Can't set elements for objects that are neither arrays, nor list, nor maps.
+            gic = null;
+            collectionType = null;
+        }
+
+        // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
+        // as maps will always succeed in setting the element and will never need to fall back to the next component
+        // operation.
+        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent(
+                callSiteDescriptor, linkerServices, operations, name);
+        if(gic == null) {
+            return nextComponent;
+        }
+
+        // Convert the key to a number if we're working with a list or array
+        final Object typedName;
+        if(collectionType != CollectionType.MAP && name != null) {
+            typedName = convertKeyToInteger(name, linkerServices);
+            if(typedName == null) {
+                // key is not numeric, it can never succeed
+                return nextComponent;
+            }
+        } else {
+            typedName = name;
+        }
+
+        final GuardedInvocation gi = gic.getGuardedInvocation();
+        final Binder binder = new Binder(linkerServices, callSiteType, typedName);
+        final MethodHandle invocation = gi.getInvocation();
+
+        if(nextComponent == null) {
+            return gic.replaceInvocation(binder.bind(invocation));
+        }
+
+        assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
+        final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
+            RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
+        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+                nextComponent.getGuardedInvocation().getInvocation());
+        return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
+                gic.getValidatorClass(), gic.getValidationType());
+    }
+
+    private static final MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength",
+            MethodType.methodType(int.class, Object.class));
+
+    private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
+            MethodType.methodType(int.class));
+
+    private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size",
+            MethodType.methodType(int.class));
+
+    private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
+
+    private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) {
+        assertParameterCount(callSiteDescriptor, 1);
+        final MethodType callSiteType = callSiteDescriptor.getMethodType();
+        final Class<?> declaredType = callSiteType.parameterType(0);
+        // If declared type of receiver at the call site is already an array, collection, or map, bind without guard.
+        // Thing is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance
+        // they're dealing with an array, collection, or map, but hey...
+        if(declaredType.isArray()) {
+            return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType));
+        } else if(Collection.class.isAssignableFrom(declaredType)) {
+            return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType));
+        } else if(Map.class.isAssignableFrom(declaredType)) {
+            return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType));
+        }
+
+        // Otherwise, create a binding based on the actual type of the argument with an appropriate guard.
+        if(clazz.isArray()) {
+            return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType), Guards.isArray(0,
+                    callSiteType), ValidationType.IS_ARRAY);
+        } if(Collection.class.isAssignableFrom(clazz)) {
+            return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType), Guards.asType(
+                    COLLECTION_GUARD, callSiteType), Collection.class, ValidationType.INSTANCE_OF);
+        } if(Map.class.isAssignableFrom(clazz)) {
+            return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType), Guards.asType(MAP_GUARD,
+                    callSiteType), Map.class, ValidationType.INSTANCE_OF);
+        }
+        // Can't retrieve length for objects that are neither arrays, nor collections, nor maps.
+        return null;
+    }
+
+    private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
+        if(descriptor.getMethodType().parameterCount() != paramCount) {
+            throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.util.Collections;
+import java.util.Set;
+import jdk.dynalink.DynamicLinkerFactory;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+
+/**
+ * A linker for ordinary Java objects. Normally used as the ultimate fallback
+ * linker by the {@link DynamicLinkerFactory} so it is given the chance to link
+ * calls to all objects that no other linker recognized. Specifically, this
+ * linker will:
+ * <ul>
+ * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()},
+ * and {@code isXxx()} as property setters and getters for
+ * {@link StandardOperation#SET_PROPERTY} and {@link StandardOperation#GET_PROPERTY}
+ * operations;</li>
+ * <li>expose all public methods for invocation through
+ * {@link StandardOperation#CALL_METHOD} operation;</li>
+ * <li>expose all public methods for retrieval for
+ * {@link StandardOperation#GET_METHOD} operation; the methods thus retrieved
+ * can then be invoked using {@link StandardOperation#CALL}.</li>
+ * <li>expose all public fields as properties, unless there are getters or
+ * setters for the properties of the same name;</li>
+ * <li>expose {@link StandardOperation#GET_LENGTH},
+ * {@link StandardOperation#GET_ELEMENT} and {@link StandardOperation#SET_ELEMENT}
+ * on native Java arrays, as well as {@link java.util.List} and
+ * {@link java.util.Map} objects; ({@link StandardOperation#GET_LENGTH} works on
+ * any {@link java.util.Collection});</li>
+ * <li>expose a virtual property named {@code length} on Java arrays;</li>
+ * <li>expose {@link StandardOperation#NEW} on instances of {@link StaticClass}
+ * as calls to constructors, including those static class objects that represent
+ * Java arrays (their constructors take a single {@code int} parameter
+ * representing the length of the array to create);</li>
+ * <li>expose static methods, fields, and properties of classes in a similar
+ * manner to how instance method, fields, and properties are exposed, on
+ * {@link StaticClass} objects.</li>
+ * <li>expose a virtual property named {@code static} on instances of
+ * {@link java.lang.Class} to access their {@link StaticClass}.</li>
+ * </ul>
+ * <p><strong>Overloaded method resolution</strong> is performed automatically
+ * for property setters, methods, and constructors. Additionally, manual
+ * overloaded method selection is supported by having a call site specify a name
+ * for a method that contains an explicit signature, i.e.
+ * {@code NamedMethod(GET_METHOD, "parseInt(String,int)")}. You can use
+ * non-qualified class names in such signatures regardless of those classes'
+ * packages, they will match any class with the same non-qualified name. You
+ * only have to use a fully qualified class name in case non-qualified class
+ * names would cause selection ambiguity (that is extremely rare). Overloaded
+ * resolution for constructors is not automatic as there is no logical place to
+ * attach that functionality to but if a language wishes to provide this
+ * functionality, it can use {@link #getConstructorMethod(Class, String)} as a
+ * useful building block for it.</p>
+ * <p><strong>Variable argument invocation</strong> is handled for both methods
+ * and constructors.</p>
+ * <p><strong>Caller sensitive methods</strong> can be linked as long as they
+ * are otherwise public and link requests have call site descriptors carrying
+ * full-strength {@link Lookup} objects and not weakened lookups or the public
+ * lookup.</p>
+ * <p>The class also exposes various static methods for discovery of available
+ * property and method names on classes and class instances, as well as access
+ * to per-class linkers using the {@link #getLinkerForClass(Class)}
+ * method.</p>
+ */
+public class BeansLinker implements GuardingDynamicLinker {
+    private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
+        @Override
+        protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) {
+            // If ClassValue.put() were public, we could just pre-populate with these known mappings...
+            return
+                clazz == Class.class ? new ClassLinker() :
+                clazz == StaticClass.class ? new StaticClassLinker() :
+                DynamicMethod.class.isAssignableFrom(clazz) ? new DynamicMethodLinker() :
+                new BeanLinker(clazz);
+        }
+    };
+
+    /**
+     * Creates a new beans linker.
+     */
+    public BeansLinker() {
+    }
+
+    /**
+     * Returns a bean linker for a particular single class. Useful when you need
+     * to override or extend the behavior of linking for some classes in your
+     * language runtime's linker, but still want to delegate to the default
+     * behavior in some cases.
+     * @param clazz the class
+     * @return a bean linker for that class
+     */
+    public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) {
+        return linkers.get(clazz);
+    }
+
+    /**
+     * Returns true if the object is a Java dynamic method (e.g., one
+     * obtained through a {@code GET_METHOD} operation on a Java object or
+     * {@link StaticClass} or through
+     * {@link #getConstructorMethod(Class, String)}.
+     *
+     * @param obj the object we want to test for being a Java dynamic method.
+     * @return true if it is a dynamic method, false otherwise.
+     */
+    public static boolean isDynamicMethod(final Object obj) {
+        return obj instanceof DynamicMethod;
+    }
+
+    /**
+     * Returns true if the object is a Java constructor (obtained through
+     * {@link #getConstructorMethod(Class, String)}}.
+     *
+     * @param obj the object we want to test for being a Java constructor.
+     * @return true if it is a constructor, false otherwise.
+     */
+    public static boolean isDynamicConstructor(final Object obj) {
+        return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor();
+    }
+
+    /**
+     * Return the dynamic method of constructor of the given class and the given
+     * signature. This method is useful for exposing a functionality for
+     * selecting an overloaded constructor based on an explicit signature, as
+     * this functionality is not otherwise exposed by Dynalink as
+     * {@link StaticClass} objects act as overloaded constructors without
+     * explicit signature selection. Example usage would be:
+     * {@code getConstructorMethod(java.awt.Color.class, "int, int, int")}.
+     * @param clazz the class
+     * @param signature full signature of the constructor. Note how you can use
+     * names of primitive types, array names with normal Java notation (e.g.
+     * {@code "int[]"}), and normally you can even use unqualified class names
+     * (e.g. {@code "String, List"} instead of
+     * {@code "java.lang.String, java.util.List"} as long as they don't cause
+     * ambiguity in the specific parameter position.
+     * @return dynamic method for the constructor or null if no constructor with
+     * the specified signature exists.
+     */
+    public static Object getConstructorMethod(final Class<?> clazz, final String signature) {
+        return StaticClassLinker.getConstructorMethod(clazz, signature);
+    }
+
+    /**
+     * Returns a set of names of all readable instance properties of a class.
+     * @param clazz the class
+     * @return a set of names of all readable instance properties of a class.
+     */
+    public static Set<String> getReadableInstancePropertyNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+        if(linker instanceof BeanLinker) {
+            return ((BeanLinker)linker).getReadablePropertyNames();
+        }
+        return Collections.emptySet();
+    }
+
+    /**
+     * Returns a set of names of all writable instance properties of a class.
+     * @param clazz the class
+     * @return a set of names of all writable instance properties of a class.
+     */
+    public static Set<String> getWritableInstancePropertyNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+        if(linker instanceof BeanLinker) {
+            return ((BeanLinker)linker).getWritablePropertyNames();
+        }
+        return Collections.emptySet();
+    }
+
+    /**
+     * Returns a set of names of all instance methods of a class.
+     * @param clazz the class
+     * @return a set of names of all instance methods of a class.
+     */
+    public static Set<String> getInstanceMethodNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+        if(linker instanceof BeanLinker) {
+            return ((BeanLinker)linker).getMethodNames();
+        }
+        return Collections.emptySet();
+    }
+
+    /**
+     * Returns a set of names of all readable static properties of a class.
+     * @param clazz the class
+     * @return a set of names of all readable static properties of a class.
+     */
+    public static Set<String> getReadableStaticPropertyNames(final Class<?> clazz) {
+        return StaticClassLinker.getReadableStaticPropertyNames(clazz);
+    }
+
+    /**
+     * Returns a set of names of all writable static properties of a class.
+     * @param clazz the class
+     * @return a set of names of all writable static properties of a class.
+     */
+    public static Set<String> getWritableStaticPropertyNames(final Class<?> clazz) {
+        return StaticClassLinker.getWritableStaticPropertyNames(clazz);
+    }
+
+    /**
+     * Returns a set of names of all static methods of a class.
+     * @param clazz the class
+     * @return a set of names of all static methods of a class.
+     */
+    public static Set<String> getStaticMethodNames(final Class<?> clazz) {
+        return StaticClassLinker.getStaticMethodNames(clazz);
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
+            throws Exception {
+        final Object receiver = request.getReceiver();
+        if(receiver == null) {
+            // Can't operate on null
+            return null;
+        }
+        return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.linker.support.Lookup;
+
+/**
+ * A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is
+ * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in
+ * {@link #getTarget(CallSiteDescriptor)} to unreflect a method handle from the reflective member on
+ * every request.
+ */
+class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
+    private static final AccessControlContext GET_LOOKUP_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext(
+                    CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME);
+
+    // Typed as "AccessibleObject" as it can be either a method or a constructor.
+    // If we were Java8-only, we could use java.lang.reflect.Executable
+    private final AccessibleObject target;
+    private final MethodType type;
+
+    CallerSensitiveDynamicMethod(final AccessibleObject target) {
+        super(getName(target));
+        this.target = target;
+        this.type = getMethodType(target);
+    }
+
+    private static String getName(final AccessibleObject target) {
+        final Member m = (Member)target;
+        final boolean constructor = m instanceof Constructor;
+        return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() :
+            getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor);
+    }
+
+    @Override
+    MethodType getMethodType() {
+        return type;
+    }
+
+    private static MethodType getMethodType(final AccessibleObject ao) {
+        final boolean isMethod = ao instanceof Method;
+        final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass();
+        final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes();
+        final MethodType type = MethodType.methodType(rtype, ptypes);
+        final Member m = (Member)ao;
+        return type.insertParameterTypes(0,
+                isMethod ?
+                        Modifier.isStatic(m.getModifiers()) ?
+                                Object.class :
+                                m.getDeclaringClass() :
+                        StaticClass.class);
+    }
+
+    @Override
+    boolean isVarArgs() {
+        return target instanceof Method ? ((Method)target).isVarArgs() : ((Constructor<?>)target).isVarArgs();
+    }
+
+    @Override
+    MethodHandle getTarget(final CallSiteDescriptor desc) {
+        final MethodHandles.Lookup lookup = AccessController.doPrivileged(
+                (PrivilegedAction<MethodHandles.Lookup>)()->desc.getLookup(),
+                GET_LOOKUP_CONTEXT);
+
+        if(target instanceof Method) {
+            final MethodHandle mh = Lookup.unreflect(lookup, (Method)target);
+            if(Modifier.isStatic(((Member)target).getModifiers())) {
+                return StaticClassIntrospector.editStaticMethodHandle(mh);
+            }
+            return mh;
+        }
+        return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup,
+                (Constructor<?>)target));
+    }
+
+    @Override
+    boolean isConstructor() {
+        return target instanceof Constructor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.reflect.Modifier;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import jdk.dynalink.internal.AccessControlContextFactory;
+
+/**
+ * A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc.
+ */
+class CheckRestrictedPackage {
+    private static final AccessControlContext NO_PERMISSIONS_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext();
+
+    /**
+     * Returns true if the class is either not public, or it resides in a package with restricted access.
+     * @param clazz the class to test
+     * @return true if the class is either not public, or it resides in a package with restricted access.
+     */
+    static boolean isRestrictedClass(final Class<?> clazz) {
+        if(!Modifier.isPublic(clazz.getModifiers())) {
+            // Non-public classes are always restricted
+            return true;
+        }
+        final SecurityManager sm = System.getSecurityManager();
+        if(sm == null) {
+            // No further restrictions if we don't have a security manager
+            return false;
+        }
+        final String name = clazz.getName();
+        final int i = name.lastIndexOf('.');
+        if (i == -1) {
+            // Classes in default package are never restricted
+            return false;
+        }
+        // Do a package access check from within an access control context with no permissions
+        try {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                @Override
+                public Void run() {
+                    sm.checkPackageAccess(name.substring(0, i));
+                    return null;
+                }
+            }, NO_PERMISSIONS_CONTEXT);
+        } catch(final SecurityException e) {
+            return true;
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
+import jdk.dynalink.linker.support.Lookup;
+
+/**
+ * A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and
+ * methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by
+ * the Dynalink as constructors for the instances of the class, {@link StaticClass} is used for this purpose.
+ */
+class ClassLinker extends BeanLinker {
+
+    ClassLinker() {
+        super(Class.class);
+        // Map "classObject.static" to StaticClass.forClass(classObject). Can use EXACT_CLASS since class Class is final.
+        setPropertyGetter("static", FOR_CLASS, ValidationType.EXACT_CLASS);
+    }
+
+    private static final MethodHandle FOR_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClass.class,
+            "forClass", MethodType.methodType(StaticClass.class, Class.class));
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassString.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.internal.InternalTypeUtilities;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * Represents a sequence of {@link Class} objects, useful for representing method signatures. Provides value
+ * semantics for using them as map keys, as well as specificity calculations and applicability checks as per
+ * JLS.
+ */
+final class ClassString {
+    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext("getClassLoader");
+
+    /**
+     * An anonymous inner class used solely to represent the "type" of null values for method applicability checking.
+     */
+    static final Class<?> NULL_CLASS = (new Object() { /* Intentionally empty */ }).getClass();
+
+    private final Class<?>[] classes;
+    private int hashCode;
+
+    ClassString(final Class<?>[] classes) {
+        this.classes = classes;
+    }
+
+    ClassString(final MethodType type) {
+        this(type.parameterArray());
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if(!(other instanceof ClassString)) {
+            return false;
+        }
+        final Class<?>[] otherClasses = ((ClassString)other).classes;
+        if(otherClasses.length != classes.length) {
+            return false;
+        }
+        for(int i = 0; i < otherClasses.length; ++i) {
+            if(otherClasses[i] != classes[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        if(hashCode == 0) {
+            int h = 0;
+            for(int i = 0; i < classes.length; ++i) {
+                h ^= classes[i].hashCode();
+            }
+            hashCode = h;
+        }
+        return hashCode;
+    }
+
+    boolean isVisibleFrom(final ClassLoader classLoader) {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                for(final Class<?> clazz: classes) {
+                    if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        }, GET_CLASS_LOADER_CONTEXT);
+    }
+
+    List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
+        return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg),
+                varArg, classes, linkerServices);
+    }
+
+    /**
+     * Returns all methods that are applicable to actual parameter classes represented by this ClassString object.
+     */
+    LinkedList<MethodHandle> getApplicables(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
+        final LinkedList<MethodHandle> list = new LinkedList<>();
+        for(final MethodHandle member: methods) {
+            if(isApplicable(member, linkerServices, varArg)) {
+                list.add(member);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Returns true if the supplied method is applicable to actual parameter classes represented by this ClassString
+     * object.
+     *
+     */
+    private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) {
+        final Class<?>[] formalTypes = method.type().parameterArray();
+        final int cl = classes.length;
+        final int fl = formalTypes.length - (varArg ? 1 : 0);
+        if(varArg) {
+            if(cl < fl) {
+                return false;
+            }
+        } else {
+            if(cl != fl) {
+                return false;
+            }
+        }
+        // Starting from 1 as we ignore the receiver type
+        for(int i = 1; i < fl; ++i) {
+            if(!canConvert(linkerServices, classes[i], formalTypes[i])) {
+                return false;
+            }
+        }
+        if(varArg) {
+            final Class<?> varArgType = formalTypes[fl].getComponentType();
+            for(int i = fl; i < cl; ++i) {
+                if(!canConvert(linkerServices, classes[i], varArgType)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static boolean canConvert(final LinkerServices ls, final Class<?> from, final Class<?> to) {
+        if(from == NULL_CLASS) {
+            return !to.isPrimitive();
+        }
+        return ls == null ? TypeUtilities.isMethodInvocationConvertible(from, to) : ls.canConvert(from, to);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethod.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.linker.LinkerServices;
+
+/**
+ * Represents a single dynamic method. A "dynamic" method can be bound to a single Java method, or can be bound to all
+ * overloaded methods of the same name on a class. Getting an invocation of a dynamic method bound to multiple
+ * overloaded methods will perform overload resolution (actually, it will perform partial overloaded resolution at link
+ * time, but if that fails to identify exactly one target method, it will generate a method handle that will perform the
+ * rest of the overload resolution at invocation time for actual argument types).
+ */
+abstract class DynamicMethod {
+    private final String name;
+
+    DynamicMethod(final String name) {
+        this.name = name;
+    }
+
+    String getName() {
+        return name;
+    }
+
+    /**
+     * Creates an invocation for the dynamic method. If the method is overloaded, it will perform overloaded method
+     * resolution based on the specified method type. The resulting resolution can either identify a single method to be
+     * invoked among the overloads, or it can identify multiple ones. In the latter case, the returned method handle
+     * will perform further overload resolution among these candidates at every invocation. If the method to be invoked
+     * is a variable arguments (vararg) method, it will pack the extra arguments in an array before the invocation of
+     * the underlying method if it is not already done.
+     *
+     * @param callSiteDescriptor the descriptor of the call site
+     * @param linkerServices linker services. Used for language-specific type conversions.
+     * @return an invocation suitable for calling the method from the specified call site.
+     */
+    abstract MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices);
+
+    /**
+     * Returns a single dynamic method representing a single underlying Java method (possibly selected among several
+     * overloads) with formal parameter types exactly matching the passed signature.
+     * @param paramTypes the comma-separated list of requested parameter type names. The names will match both
+     * qualified and unqualified type names.
+     * @return a single dynamic method representing a single underlying Java method, or null if none of the Java methods
+     * behind this dynamic method exactly match the requested parameter types.
+     */
+    abstract SingleDynamicMethod getMethodForExactParamTypes(String paramTypes);
+
+    /**
+     * True if this dynamic method already contains a method with an identical signature as the passed in method.
+     * @param method the method to check
+     * @return true if it already contains an equivalent method.
+     */
+    abstract boolean contains(SingleDynamicMethod method);
+
+    static String getClassAndMethodName(final Class<?> clazz, final String name) {
+        final String clazzName = clazz.getCanonicalName();
+        return (clazzName == null ? clazz.getName() : clazzName) + "." + name;
+    }
+
+    @Override
+    public String toString() {
+        return "[" + getClass().getName() + " " + getName() + "]";
+    }
+
+    /**
+     * True if this method happens to be a constructor method.
+     *
+     * @return true if this represents a constructor.
+     */
+    boolean isConstructor() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.support.Guards;
+
+/**
+ * Simple linker that implements the {@link StandardOperation#CALL} operation
+ * for {@link DynamicMethod} objects - the objects returned by
+ * {@link StandardOperation#GET_METHOD} through {@link AbstractJavaLinker}.
+ */
+class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
+    @Override
+    public boolean canLinkType(final Class<?> type) {
+        return DynamicMethod.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) {
+        final Object receiver = linkRequest.getReceiver();
+        if(!(receiver instanceof DynamicMethod)) {
+            return null;
+        }
+        final DynamicMethod dynMethod = (DynamicMethod)receiver;
+        final boolean constructor = dynMethod.isConstructor();
+        final MethodHandle invocation;
+
+        final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
+        final Operation op = NamedOperation.getBaseOperation(desc.getOperation());
+        if (op == StandardOperation.CALL && !constructor) {
+            invocation = dynMethod.getInvocation(desc.changeMethodType(
+                    desc.getMethodType().dropParameterTypes(0, 1)), linkerServices);
+        } else if (op == StandardOperation.NEW && constructor) {
+            final MethodHandle ctorInvocation = dynMethod.getInvocation(desc, linkerServices);
+            if(ctorInvocation == null) {
+                return null;
+            }
+
+            // Insert null for StaticClass parameter
+            invocation = MethodHandles.insertArguments(ctorInvocation, 0, (Object)null);
+        } else {
+            return null;
+        }
+
+        if (invocation != null) {
+            return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0,
+                desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
+        }
+
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/FacetIntrospector.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import jdk.dynalink.linker.support.Lookup;
+
+/**
+ * Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are
+ * subclasses for instance (bean) and static facet of a class.
+ */
+abstract class FacetIntrospector {
+    private final Class<?> clazz;
+    private final boolean instance;
+    private final boolean isRestricted;
+
+    protected final AccessibleMembersLookup membersLookup;
+
+    FacetIntrospector(final Class<?> clazz, final boolean instance) {
+        this.clazz = clazz;
+        this.instance = instance;
+        isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz);
+        membersLookup = new AccessibleMembersLookup(clazz, instance);
+    }
+
+    /**
+     * Returns getters for inner classes.
+     * @return getters for inner classes.
+     */
+    abstract Map<String, MethodHandle> getInnerClassGetters();
+
+    /**
+     * Returns the fields for the class facet.
+     * @return the fields for the class facet.
+     */
+    Collection<Field> getFields() {
+        if(isRestricted) {
+            // NOTE: we can't do anything here. Unlike with methods in AccessibleMethodsLookup, we can't just return
+            // the fields from a public superclass, because this class might define same-named fields which will shadow
+            // the superclass fields, and we have no way to know if they do, since we're denied invocation of
+            // getFields(). Therefore, the only correct course of action is to not expose any public fields from a class
+            // defined in a restricted package.
+            return Collections.emptySet();
+        }
+
+        final Field[] fields = clazz.getFields();
+        final Collection<Field> cfields = new ArrayList<>(fields.length);
+        for(final Field field: fields) {
+            final boolean isStatic = Modifier.isStatic(field.getModifiers());
+            if(isStatic && clazz != field.getDeclaringClass()) {
+                // ignore inherited static fields
+                continue;
+            }
+
+            if(instance != isStatic && isAccessible(field)) {
+                cfields.add(field);
+            }
+        }
+        return cfields;
+    }
+
+    boolean isAccessible(final Member m) {
+        final Class<?> declaring = m.getDeclaringClass();
+        // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a
+        // non-restricted class, so if the declaring class is identical to the class being inspected, then forego
+        // a potentially expensive restricted-package check.
+        return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring);
+    }
+
+    /**
+     * Returns all the methods in the facet.
+     * @return all the methods in the facet.
+     */
+    Collection<Method> getMethods() {
+        return membersLookup.getMethods();
+    }
+
+
+    MethodHandle unreflectGetter(final Field field) {
+        return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field));
+    }
+
+    MethodHandle unreflectSetter(final Field field) {
+        return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field));
+    }
+
+    /**
+     * Returns an edited method handle. A facet might need to edit an unreflected method handle before it is usable with
+     * the facet. By default, returns the passed method handle unchanged. The class' static facet will introduce a
+     * dropArguments.
+     * @param mh the method handle to edit.
+     * @return the edited method handle.
+     */
+    abstract MethodHandle editMethodHandle(MethodHandle mh);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import jdk.dynalink.linker.GuardedInvocation;
+
+/**
+ * Represents one component for a GuardedInvocation of a potentially composite operation of an
+ * {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its
+ * guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz"
+ * expressions. This allows choosing the most restrictive guard as the guard for the composition of two components.
+ */
+class GuardedInvocationComponent {
+    enum ValidationType {
+        NONE, // No guard; the operation can be linked unconditionally (quite rare); least strict.
+        INSTANCE_OF, // "validatorClass.isInstance(obj)" guard
+        EXACT_CLASS, // "obj.getClass() == validatorClass" guard; most strict.
+        IS_ARRAY, // "obj.getClass().isArray()"
+    }
+
+    private final GuardedInvocation guardedInvocation;
+    private final Validator validator;
+
+    GuardedInvocationComponent(final MethodHandle invocation) {
+        this(invocation, null, ValidationType.NONE);
+    }
+
+    GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) {
+        this(invocation, guard, null, validationType);
+    }
+
+    GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
+            final ValidationType validationType) {
+        this(invocation, guard, new Validator(validatorClass, validationType));
+    }
+
+    GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class<?> validatorClass,
+            final ValidationType validationType) {
+        this(guardedInvocation, new Validator(validatorClass, validationType));
+    }
+
+    GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) {
+        return replaceInvocation(newInvocation, guardedInvocation.getGuard());
+    }
+
+    GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) {
+        return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation,
+                newGuard), validator);
+    }
+
+    private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) {
+        this(new GuardedInvocation(invocation, guard), validator);
+    }
+
+    private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) {
+        this.guardedInvocation = guardedInvocation;
+        this.validator = validator;
+    }
+
+    GuardedInvocation getGuardedInvocation() {
+        return guardedInvocation;
+    }
+
+    Class<?> getValidatorClass() {
+        return validator.validatorClass;
+    }
+
+    ValidationType getValidationType() {
+        return validator.validationType;
+    }
+
+    GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard,
+            final Class<?> otherValidatorClass, final ValidationType otherValidationType) {
+        final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType));
+        final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard;
+        return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator);
+    }
+
+    private static class Validator {
+        /*private*/ final Class<?> validatorClass;
+        /*private*/ final ValidationType validationType;
+
+        Validator(final Class<?> validatorClass, final ValidationType validationType) {
+            this.validatorClass = validatorClass;
+            this.validationType = validationType;
+        }
+
+        Validator compose(final Validator other) {
+            if(other.validationType == ValidationType.NONE) {
+                return this;
+            }
+            switch(validationType) {
+                case NONE:
+                    return other;
+                case INSTANCE_OF:
+                    switch(other.validationType) {
+                        case INSTANCE_OF:
+                            if(isAssignableFrom(other)) {
+                                return other;
+                            } else if(other.isAssignableFrom(this)) {
+                                return this;
+                            }
+                            break;
+                        case EXACT_CLASS:
+                            if(isAssignableFrom(other)) {
+                                return other;
+                            }
+                            break;
+                        case IS_ARRAY:
+                            if(validatorClass.isArray()) {
+                                return this;
+                            }
+                            break;
+                        default:
+                            throw new AssertionError();
+                    }
+                    break;
+                case EXACT_CLASS:
+                    switch(other.validationType) {
+                        case INSTANCE_OF:
+                            if(other.isAssignableFrom(this)) {
+                                return this;
+                            }
+                            break;
+                        case EXACT_CLASS:
+                            if(validatorClass == other.validatorClass) {
+                                return this;
+                            }
+                            break;
+                        case IS_ARRAY:
+                            if(validatorClass.isArray()) {
+                                return this;
+                            }
+                            break;
+                        default:
+                            throw new AssertionError();
+                    }
+                    break;
+                case IS_ARRAY:
+                    switch(other.validationType) {
+                        case INSTANCE_OF:
+                        case EXACT_CLASS:
+                            if(other.validatorClass.isArray()) {
+                                return other;
+                            }
+                            break;
+                        case IS_ARRAY:
+                            return this;
+                        default:
+                            throw new AssertionError();
+                    }
+                    break;
+                default:
+                    throw new AssertionError();
+            }
+            throw new AssertionError("Incompatible composition " + this + " vs " + other);
+        }
+
+        private boolean isAssignableFrom(final Validator other) {
+            return validatorClass.isAssignableFrom(other.validatorClass);
+        }
+
+        @Override
+        public String toString() {
+            return "Validator[" + validationType + (validatorClass == null ? "" : (" " + validatorClass.getName())) + "]";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MaximallySpecific.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.dynalink.linker.ConversionComparator.Comparison;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.TypeUtilities;
+
+/**
+ * Utility class that encapsulates the algorithm for choosing the maximally specific methods.
+ */
+class MaximallySpecific {
+    /**
+     * Given a list of methods, returns a list of maximally specific methods.
+     *
+     * @param methods the list of methods
+     * @param varArgs whether to assume the methods are varargs
+     * @return the list of maximally specific methods.
+     */
+    static List<SingleDynamicMethod> getMaximallySpecificMethods(final List<SingleDynamicMethod> methods, final boolean varArgs) {
+        return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null);
+    }
+
+    private abstract static class MethodTypeGetter<T> {
+        abstract MethodType getMethodType(T t);
+    }
+
+    private static final MethodTypeGetter<MethodHandle> METHOD_HANDLE_TYPE_GETTER =
+            new MethodTypeGetter<MethodHandle>() {
+        @Override
+        MethodType getMethodType(final MethodHandle t) {
+            return t.type();
+        }
+    };
+
+    private static final MethodTypeGetter<SingleDynamicMethod> DYNAMIC_METHOD_TYPE_GETTER =
+            new MethodTypeGetter<SingleDynamicMethod>() {
+        @Override
+        MethodType getMethodType(final SingleDynamicMethod t) {
+            return t.getMethodType();
+        }
+    };
+
+     /**
+      * Given a list of methods handles, returns a list of maximally specific methods, applying language-runtime
+      * specific conversion preferences.
+      *
+      * @param methods the list of method handles
+      * @param varArgs whether to assume the method handles are varargs
+      * @param argTypes concrete argument types for the invocation
+      * @return the list of maximally specific method handles.
+      */
+     static List<MethodHandle> getMaximallySpecificMethodHandles(final List<MethodHandle> methods, final boolean varArgs,
+             final Class<?>[] argTypes, final LinkerServices ls) {
+         return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER);
+     }
+
+     /**
+      * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific
+      * conversion preferences.
+      *
+      * @param methods the list of methods
+      * @param varArgs whether to assume the methods are varargs
+      * @param argTypes concrete argument types for the invocation
+      * @return the list of maximally specific methods.
+      */
+     static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(final List<SingleDynamicMethod> methods,
+             final boolean varArgs, final Class<?>[] argTypes, final LinkerServices ls) {
+         return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER);
+     }
+
+    /**
+     * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific
+     * conversion preferences.
+     *
+     * @param methods the list of methods
+     * @param varArgs whether to assume the methods are varargs
+     * @param argTypes concrete argument types for the invocation
+     * @return the list of maximally specific methods.
+     */
+    private static <T> List<T> getMaximallySpecificMethods(final List<T> methods, final boolean varArgs,
+            final Class<?>[] argTypes, final LinkerServices ls, final MethodTypeGetter<T> methodTypeGetter) {
+        if(methods.size() < 2) {
+            return methods;
+        }
+        final LinkedList<T> maximals = new LinkedList<>();
+        for(final T m: methods) {
+            final MethodType methodType = methodTypeGetter.getMethodType(m);
+            boolean lessSpecific = false;
+            for(final Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) {
+                final T max = maximal.next();
+                switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) {
+                    case TYPE_1_BETTER: {
+                        maximal.remove();
+                        break;
+                    }
+                    case TYPE_2_BETTER: {
+                        lessSpecific = true;
+                        break;
+                    }
+                    case INDETERMINATE: {
+                        // do nothing
+                        break;
+                    }
+                    default: {
+                        throw new AssertionError();
+                    }
+                }
+            }
+            if(!lessSpecific) {
+                maximals.addLast(m);
+            }
+        }
+        return maximals;
+    }
+
+    private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class<?>[] argTypes,
+            final LinkerServices ls) {
+        final int pc1 = t1.parameterCount();
+        final int pc2 = t2.parameterCount();
+        assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1);
+        assert (argTypes == null) == (ls == null);
+        final int maxPc = Math.max(Math.max(pc1, pc2), argTypes == null ? 0 : argTypes.length);
+        boolean t1MoreSpecific = false;
+        boolean t2MoreSpecific = false;
+        // NOTE: Starting from 1 as overloaded method resolution doesn't depend on 0th element, which is the type of
+        // 'this'. We're only dealing with instance methods here, not static methods. Actually, static methods will have
+        // a fake 'this' of type StaticClass.
+        for(int i = 1; i < maxPc; ++i) {
+            final Class<?> c1 = getParameterClass(t1, pc1, i, varArgs);
+            final Class<?> c2 = getParameterClass(t2, pc2, i, varArgs);
+            if(c1 != c2) {
+                final Comparison cmp = compare(c1, c2, argTypes, i, ls);
+                if(cmp == Comparison.TYPE_1_BETTER && !t1MoreSpecific) {
+                    t1MoreSpecific = true;
+                    if(t2MoreSpecific) {
+                        return Comparison.INDETERMINATE;
+                    }
+                }
+                if(cmp == Comparison.TYPE_2_BETTER && !t2MoreSpecific) {
+                    t2MoreSpecific = true;
+                    if(t1MoreSpecific) {
+                        return Comparison.INDETERMINATE;
+                    }
+                }
+            }
+        }
+        if(t1MoreSpecific) {
+            return Comparison.TYPE_1_BETTER;
+        } else if(t2MoreSpecific) {
+            return Comparison.TYPE_2_BETTER;
+        }
+        return Comparison.INDETERMINATE;
+    }
+
+    private static Comparison compare(final Class<?> c1, final Class<?> c2, final Class<?>[] argTypes, final int i, final LinkerServices cmp) {
+        if(cmp != null) {
+            final Comparison c = cmp.compareConversion(argTypes[i], c1, c2);
+            if(c != Comparison.INDETERMINATE) {
+                return c;
+            }
+        }
+        if(TypeUtilities.isSubtype(c1, c2)) {
+            return Comparison.TYPE_1_BETTER;
+        } if(TypeUtilities.isSubtype(c2, c1)) {
+            return Comparison.TYPE_2_BETTER;
+        }
+        return Comparison.INDETERMINATE;
+    }
+
+    private static Class<?> getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) {
+        return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java	Wed Dec 02 09:37:26 2015 -0800
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.dynalink.beans;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest;
+import jdk.dynalink.internal.AccessControlContextFactory;
+import jdk.dynalink.internal.InternalTypeUtilities;
+import jdk.dynalink.linker.LinkerServices;
+
+/**
+ * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all
+ * constructors) for a particular class. Correctly handles overload resolution, variable arity methods, and caller
+ * sensitive methods within the overloads.
+ */
+class OverloadedDynamicMethod extends DynamicMethod {
+    /**
+     * Holds a list of all methods.
+     */
+    private final LinkedList<SingleDynamicMethod> methods;
+    private final ClassLoader classLoader;
+
+    /**
+     * Creates a new overloaded dynamic method.
+     *
+     * @param clazz the class this method belongs to
+     * @param name the name of the method
+     */
+    OverloadedDynamicMethod(final Class<?> clazz, final String name) {
+        this(new LinkedList<SingleDynamicMethod>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name));
+    }
+
+    private OverloadedDynamicMethod(final LinkedList<SingleDynamicMethod> methods, final ClassLoader classLoader, final String name) {
+        super(name);
+        this.methods = methods;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) {
+        final LinkedList<SingleDynamicMethod> matchingMethods = new LinkedList<>();
+        for(final SingleDynamicMethod method: methods) {
+            final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes);
+            if(matchingMethod != null) {
+                matchingMethods.add(matchingMethod);
+            }
+        }
+        switch(matchingMethods.size()) {
+            case 0: {
+                return null;
+            }
+            case 1: {
+                return matchingMethods.getFirst();
+            }
+            default: {
+                throw new BootstrapMethodError("Can't choose among " + matchingMethods + " for argument types "
+                        + paramTypes + " for method " + getName());
+            }
+        }
+    }
+
+    @Override
+    public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
+        final MethodType callSiteType = callSiteDescriptor.getMethodType();
+        // First, find all methods applicable to the call site by subtyping (JLS 15.12.2.2)
+        final ApplicableOverloadedMethods subtypingApplicables = getApplicables(callSiteType,
+                ApplicableOverloadedMethods.APPLICABLE_BY_SUBTYPING);
+        // Next, find all methods applicable by method invocation conversion to the call site (JLS 15.12.2.3).
+        final ApplicableOverloadedMethods methodInvocationApplicables = getApplicables(callSiteType,
+                ApplicableOverloadedMethods.APPLICABLE_BY_METHOD_INVOCATION_CONVERSION);
+        // Finally, find all methods applicable by variable arity invocation. (JLS 15.12.2.4).
+        final ApplicableOverloadedMethods variableArityApplicables = getApplicables(callSiteType,
+                ApplicableOverloadedMethods.APPLICABLE_BY_VARIABLE_ARITY);
+
+        // Find the methods that are maximally specific based on the call site signature
+        List<SingleDynamicMethod> maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods();
+        if(maximallySpecifics.isEmpty()) {
+            maximallySpecifics = methodInvocationApplicables.findMaximallySpecificMethods();
+            if(maximallySpecifics.isEmpty()) {
+                maximallySpecifics = variableArityApplicables.findMaximallySpecificMethods();
+            }
+        }
+
+        // Now, get a list of the rest of the methods; those that are *not* applicable to the call site signature based
+        // on JLS rules. As paradoxical as that might sound, we have to consider these for dynamic invocation, as they
+        // might match more concrete types passed in invocations. That's why we provisionally call them "invokables".
+        // This is typical for very generic signatures at call sites. Typical example: call site specifies
+        // (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability
+        // rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation.
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final List<SingleDynamicMethod> invokables = (List)methods.clone();
+        invokables.removeAll(subtypingApplicables.getMethods());
+        invokables.removeAll(methodInvocationApplicables.getMethods());
+        invokables.removeAll(variableArityApplicables.getMethods());
+        for(final Iterator<SingleDynamicMethod> it = invokables.iterator(); it.hasNext();) {
+            final SingleDynamicMethod m = it.next();
+            if(!isApplicableDynamically(linkerServices, callSiteType, m)) {
+                it.remove();
+            }
+        }
+
+        // If no additional methods can apply at invocation time, and there's more than one maximally specific method
+        // based on call site signature, that is a link-time ambiguity. In a static scenario, javac would report an
+        // ambiguity error.
+        if(invokables.isEmpty() && maximallySpecifics.size() > 1) {
+            throw new BootstrapMethodError("Can't choose among " + maximallySpecifics + " for argument types "
+                    + callSiteType);
+        }
+
+        // Merge them all.
+        invokables.addAll(maximallySpecifics);
+        switch(invokables.size()) {
+            case 0: {
+                // No overloads can ever match the call site type
+                return null;
+            }
+            case 1: {
+                // Very lucky, we ended up with a single candidate method handle based on the call site signature; we
+                // can link it very simply by delegating to the SingleDynamicMethod.
+                return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices);
+            }
+            default: {
+                // We have more than one candidate. We have no choice but to link to a method that resolves overloads on
+                // every invocation (alternatively, we could opportunistically link the one method that resolves for the
+                // current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd
+                // go back all the way to candidate selection. Note that we're resolving any potential caller sensitive
+                // methods here to their handles, as the OverloadedMethod instance is specific to a call site, so it
+                // has an already determined Lookup.
+                final List<MethodHandle> methodHandles = new ArrayList<>(invokables.size());
+                for(final SingleDynamicMethod method: invokables) {
+                    methodHandles.add(method.getTarget(callSiteDescriptor));
+                }
+                return new OverloadedMethod(methodHandles, this, getCallSiteClassLoader(callSiteDescriptor), callSiteType, linkerServices).getInvoker();
+            }
+        }
+    }
+
+    private static final AccessControlContext GET_CALL_SITE_CLASS_LOADER_CONTEXT =
+            AccessControlContextFactory.createAccessControlContext(
+                    "getClassLoader", CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME);
+
+    private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) {
+        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+            @Override
+            public ClassLoader run() {
+                return callSiteDescriptor.getLookup().lookupClass().getClassLoader();
+            }
+        }, GET_CALL_SITE_CLASS_LOADER_CONTEXT);
+    }
+
+    @Override
+    public boolean contains(final SingleDynamicMethod m) {
+        for(final SingleDynamicMethod method: methods) {
+            if(method.contains(m)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isConstructor() {
+        assert !methods.isEmpty();
+        return methods.getFirst().isConstructor();
+    }
+
+    @Override
+    public String toString() {
+        // First gather the names and sort them. This makes it consistent and easier to read.
+        final List<String> names = new ArrayList<>(methods.size());
+        int len = 0;
+        for (final SingleDynamicMethod m: methods) {
+            final String name = m.getName();
+            len += name.length();
+            names.add(name);
+        }
+        // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean".
+        final Collator collator = Collator.getInstance();
+        collator.setStrength(Collator.SECONDARY);
+        Collections.sort(names, collator);
+
+        final String className = getClass().getName();
+        // Class name length + length of signatures + 2 chars/per signature for indentation and newline +
+        // 3 for brackets and initial newline
+        final int totalLength = className.length() + len + 2 * names.size() + 3;
+        final StringBuilder b = new StringBuilder(totalLength);
+        b.append('[').append(className).append('\n');
+        for(final String name: names) {
+            b.append(' ').append(name).append('\n');
+        }
+        b.append(']');
+        assert b.length() == totalLength;
+        return b.toString();
+    };
+
+    ClassLoader getClassLoader() {
+        return classLoader;
+    }
+
+    private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType,
+            final SingleDynamicMethod m) {
+        final MethodType methodType = m.getMethodType();
+        final boolean varArgs = m.isVarArgs();
+        final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
+        final int callSiteArgLen = callSiteType.parameterCount();
+
+        // Arity checks
+        if(varArgs) {
+            if(callSiteArgLen < fixedArgLen) {
+                return false;
+            }
+        } else if(callSiteArgLen != fixedArgLen) {
+            return false;
+        }
+
+        // Fixed arguments type checks, starting from 1, as receiver type doesn't participate
+        for(int i = 1; i < fixedArgLen; ++i) {
+            if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) {
+                return false;
+            }
+        }
+        if(!varArgs) {
+            // Not vararg; both arity and types matched.
+            return true;
+        }
+
+        final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen);
+        final Class<?> varArgType = varArgArrayType.getComponentType();
+
+        if(fixedArgLen == callSiteArgLen - 1) {
+            // Exactly one vararg; check both array type matching and array component type matching.
+            final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
+            return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
+                    || isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
+        }
+
+        // Either zero, or more than one vararg; check if all actual vararg types match the vararg array component type.
+        for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
+            if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class<?> callSiteType,
+            final Class<?> methodType) {
+        return isPotentiallyConvertible(callSiteType, methodType)
+                || linkerServices.canConvert(callSiteType, methodType);
+    }
+
+    private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) {
+        return new ApplicableOverloadedMethods(methods, callSiteType, test);
+    }
+
+    /**
+     * Add a method to this overloaded method's set.
+     *
+     * @param method a method to add
+     */
+    public void addMethod(final SingleDynamicMethod method) {
+        assert constructorFlagConsistent(method);
+        methods.add(method);
+    }
+
+    private boolean constructorFlagConsistent(final SingleDynamicMethod method) {
+        return methods.isEmpty()? true : (methods.getFirst().isConstructor() == method.isConstructor());
+    }
+
+    /**
+     * Determines whether one type can be potentially converted to another type at runtime. Allows a conversion between
+     * any subtype and supertype in either direction, and also allows a conversion between any two primitive types, as
+     * well as between any primitive type and any reference type that can hold a boxed primitive.
+     *
+     * @param callSiteType the parameter type at the call site
+     * @param methodType the parameter type in the method declaration
+     * @return true if callSiteType is potentially convertible to the methodType.
+     */
+    private static boolean isPotentiallyConvertible(final Class<?> callSiteType, final Class<?> methodType) {
+        // Widening or narrowing reference conversion
+        if(InternalTypeUtilities.areAssignable(callSiteType, methodType)) {
+            return true;
+