< prev index next >

src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java

Print this page
rev 54208 : 8174222: LambdaMetafactory: validate inputs and improve documentation

@@ -25,10 +25,12 @@
 
 package java.lang.invoke;
 
 import java.io.Serializable;
 import java.util.Arrays;
+import java.lang.reflect.Array;
+import java.util.Objects;
 
 /**
  * <p>Methods to facilitate the creation of simple "function objects" that
  * implement one or more interfaces by delegation to a provided {@link MethodHandle},
  * possibly after type adaptation and partial evaluation of arguments.  These

@@ -37,53 +39,59 @@
  * reference expression</em> features of the Java Programming Language.
  *
  * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
  * proceeds in order through three phases:
  * <ul>
- *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
+ *     <li><p><em>Linkage</em> occurs when the methods in this class are invoked.
  *     They take as arguments an interface to be implemented (typically a
  *     <em>functional interface</em>, one with a single abstract method), a
  *     name and signature of a method from that interface to be implemented, a
- *     method handle describing the desired implementation behavior
- *     for that method, and possibly other additional metadata, and produce a
- *     {@link CallSite} whose target can be used to create suitable function
- *     objects.  Linkage may involve dynamically loading a new class that
- *     implements the target interface. The {@code CallSite} can be considered a
- *     "factory" for function objects and so these linkage methods are referred
- *     to as "metafactories".</li>
+ *     {@link MethodHandleInfo direct method handle} describing the desired
+ *     implementation behavior for that method, and possibly other additional
+ *     metadata, and produce a {@link CallSite} whose target can be used to
+ *     create suitable function objects.
+ *
+ *     <p>Linkage may involve dynamically loading a new class that implements
+ *     the target interface, or re-using a suitable existing class.
+ *
+ *     <p>The {@code CallSite} can be considered a "factory" for function
+ *     objects and so these linkage methods are referred to as
+ *     "metafactories".</li>
  *
- *     <li><em>Capture</em> occurs when the {@code CallSite}'s target is
+ *     <li><p><em>Capture</em> occurs when the {@code CallSite}'s target is
  *     invoked, typically through an {@code invokedynamic} call site,
  *     producing a function object.  This may occur many times for
- *     a single factory {@code CallSite}.  Capture may involve allocation of a
- *     new function object, or may return an existing function object.  The
- *     behavior {@code MethodHandle} may have additional parameters beyond those
- *     of the specified interface method; these are referred to as <em>captured
- *     parameters</em>, which must be provided as arguments to the
- *     {@code CallSite} target, and which may be early-bound to the behavior
- *     {@code MethodHandle}.  The number of captured parameters and their types
- *     are determined during linkage.
- *     The identity of a function object produced by invoking the
- *     {@code CallSite}'s target is unpredictable, and therefore
- *     identity-sensitive operations (such as reference equality, object
- *     locking, and {@code System.identityHashCode()} may produce different
- *     results in different implementations, or even upon different invocations
- *     in the same implementation.</li>
- *
- *     <li><em>Invocation</em> occurs when an implemented interface method
- *     is invoked on a function object.  This may occur many times for a single
- *     function object.  The method referenced by the behavior {@code MethodHandle}
- *     is invoked with the captured arguments and any additional arguments
- *     provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
+ *     a single factory {@code CallSite}.
+ *
+ *     <p>If the behavior {@code MethodHandle} has additional parameters beyond
+ *     those of the specified interface method, these are referred to as
+ *     <em>captured parameters</em>, which must be provided as arguments to the
+ *     {@code CallSite} target. The expected number and types of captured
+ *     parameters are determined during linkage.
+ *
+ *     <p>Capture may involve allocation of a new function object, or may return
+ *     a suitable existing function object. The identity of a function object
+ *     produced by capture is unpredictable, and therefore identity-sensitive
+ *     operations (such as reference equality, object locking, and {@code
+ *     System.identityHashCode()}) may produce different results in different
+ *     implementations, or even upon different invocations in the same
+ *     implementation.</li>
+ *
+ *     <li><p><em>Invocation</em> occurs when an implemented interface method is
+ *     invoked on a function object. This may occur many times for a single
+ *     function object. The method referenced by the implementation MethodHandle
+ *     is invoked, passing to it the captured arguments and the invocation
+ *     arguments. The result of the method is returned.
+ *     </li>
  * </ul>
  *
  * <p>It is sometimes useful to restrict the set of inputs or results permitted
  * at invocation.  For example, when the generic interface {@code Predicate<T>}
  * is parameterized as {@code Predicate<String>}, the input must be a
  * {@code String}, even though the method to implement allows any {@code Object}.
  * At linkage time, an additional {@link MethodType} parameter describes the
- * "instantiated" method type; on invocation, the arguments and eventual result
+ * "dynamic" method type; on invocation, the arguments and eventual result
  * are checked against this {@code MethodType}.
  *
  * <p>This class provides two forms of linkage methods: a standard version
  * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
  * using an optimized protocol, and an alternate version

@@ -119,28 +127,26 @@
  *     {@link SerializedLambda} for details.</li>
  * </ul>
  *
  * <p>Assume the linkage arguments are as follows:
  * <ul>
- *      <li>{@code invokedType} (describing the {@code CallSite} signature) has
+ *      <li>{@code factoryType} (describing the {@code CallSite} signature) has
  *      K parameters of types (D1..Dk) and return type Rd;</li>
- *      <li>{@code samMethodType} (describing the implemented method type) has N
+ *      <li>{@code interfaceMethodType} (describing the implemented method type) has N
  *      parameters, of types (U1..Un) and return type Ru;</li>
- *      <li>{@code implMethod} (the {@code MethodHandle} providing the
- *      implementation has M parameters, of types (A1..Am) and return type Ra
+ *      <li>{@code implementation} (the {@code MethodHandle} providing the
+ *      implementation) has M parameters, of types (A1..Am) and return type Ra
  *      (if the method describes an instance method, the method type of this
  *      method handle already includes an extra first argument corresponding to
  *      the receiver);</li>
- *      <li>{@code instantiatedMethodType} (allowing restrictions on invocation)
+ *      <li>{@code dynamicMethodType} (allowing restrictions on invocation)
  *      has N parameters, of types (T1..Tn) and return type Rt.</li>
  * </ul>
  *
  * <p>Then the following linkage invariants must hold:
  * <ul>
- *     <li>Rd is an interface</li>
- *     <li>{@code implMethod} is a <em>direct method handle</em></li>
- *     <li>{@code samMethodType} and {@code instantiatedMethodType} have the same
+ *     <li>{@code interfaceMethodType} and {@code dynamicMethodType} have the same
  *     arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
  *     both reference types and Ti is a subtype of Ui</li>
  *     <li>Either Rt and Ru are the same type, or both are reference types and
  *     Rt is a subtype of Ru</li>
  *     <li>K + N = M</li>

@@ -148,11 +154,11 @@
  *     <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
  *     <li>The return type Rt is void, or the return type Ra is not void and is
  *     adaptable to Rt</li>
  * </ul>
  *
- * <p>Further, at capture time, if {@code implMethod} corresponds to an instance
+ * <p>Further, at capture time, if {@code implementation} corresponds to an instance
  * method, and there are any capture arguments ({@code K > 0}), then the first
  * capture argument (corresponding to the receiver) must be non-null.
  *
  * <p>A type Q is considered adaptable to S as follows:
  * <table class="striped">

@@ -216,28 +222,28 @@
  * (which in this case, includes information describing the implementation method,
  * the target interface, and the target interface method(s)), as well as a
  * method signature describing the number and static types (but not the values)
  * of the dynamic arguments and the static return type of the invokedynamic site.
  *
- * @implNote The implementation method is described with a method handle. In
- * theory, any method handle could be used. Currently supported are direct method
- * handles representing invocation of virtual, interface, constructor and static
- * methods.
+ * <p>The implementation method is described with a direct method handle
+ * referencing a method or constructor. In theory, any method handle could be
+ * used, but this is not compatible with some implementation techniques and
+ * would complicate the work implementations must do.
+ *
  * @since 1.8
  */
 public final class LambdaMetafactory {
 
     private LambdaMetafactory() {}
 
-    /** Flag for alternate metafactories indicating the lambda object
+    /** Flag for {@link #altMetafactory} indicating the lambda object
      * must be serializable */
     public static final int FLAG_SERIALIZABLE = 1 << 0;
 
     /**
-     * Flag for alternate metafactories indicating the lambda object implements
-     * other marker interfaces
-     * besides Serializable
+     * Flag for {@link #altMetafactory} indicating the lambda object implements
+     * other interfaces besides {@code Serializable}
      */
     public static final int FLAG_MARKERS = 1 << 1;
 
     /**
      * Flag for alternate metafactories indicating the lambda object requires

@@ -247,11 +253,11 @@
 
     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
     private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
 
     // LambdaMetafactory bootstrap methods are startup sensitive, and may be
-    // special cased in java.lang.invokeBootstrapMethodInvoker to ensure
+    // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
     // methods are invoked with exact type information to avoid generating
     // code for runtime checks. Take care any changes or additions here are
     // reflected there as appropriate.
 
     /**

@@ -267,66 +273,73 @@
      * A general description of the behavior of this method is provided
      * {@link LambdaMetafactory above}.
      *
      * <p>When the target of the {@code CallSite} returned from this method is
      * invoked, the resulting function objects are instances of a class which
-     * implements the interface named by the return type of {@code invokedType},
-     * declares a method with the name given by {@code invokedName} and the
-     * signature given by {@code samMethodType}.  It may also override additional
+     * implements the interface named by the return type of {@code factoryType},
+     * declares a method with the name given by {@code methodName} and the
+     * signature given by {@code interfaceMethodType}.  It may also override additional
      * methods from {@code Object}.
      *
      * @param caller Represents a lookup context with the accessibility
      *               privileges of the caller.  Specifically, the lookup context
      *               must have
      *               <a href="MethodHandles.Lookup.html#privacc">private access</a>
      *               privileges.
      *               When used with {@code invokedynamic}, this is stacked
      *               automatically by the VM.
-     * @param invokedName The name of the method to implement.  When used with
+     * @param methodName The name of the method to implement.  When used with
      *                    {@code invokedynamic}, this is provided by the
      *                    {@code NameAndType} of the {@code InvokeDynamic}
      *                    structure and is stacked automatically by the VM.
-     * @param invokedType The expected signature of the {@code CallSite}.  The
+     * @param factoryType The expected signature of the {@code CallSite}.  The
      *                    parameter types represent the types of capture variables;
      *                    the return type is the interface to implement.   When
      *                    used with {@code invokedynamic}, this is provided by
      *                    the {@code NameAndType} of the {@code InvokeDynamic}
      *                    structure and is stacked automatically by the VM.
-     *                    In the event that the implementation method is an
-     *                    instance method and this signature has any parameters,
-     *                    the first parameter in the invocation signature must
-     *                    correspond to the receiver.
-     * @param samMethodType Signature and return type of method to be implemented
-     *                      by the function object.
-     * @param implMethod A direct method handle describing the implementation
+     * @param interfaceMethodType Signature and return type of method to be
+     *                            implemented by the function object.
+     * @param implementation A direct method handle describing the implementation
      *                   method which should be called (with suitable adaptation
-     *                   of argument types, return types, and with captured
+     *                       of argument types and return types, and with captured
      *                   arguments prepended to the invocation arguments) at
      *                   invocation time.
-     * @param instantiatedMethodType The signature and return type that should
+     * @param dynamicMethodType The signature and return type that should
      *                               be enforced dynamically at invocation time.
-     *                               This may be the same as {@code samMethodType},
-     *                               or may be a specialization of it.
+     *                          In simple use cases this is the same as
+     *                          {@code interfaceMethodType}.
      * @return a CallSite whose target can be used to perform capture, generating
-     *         instances of the interface named by {@code invokedType}
-     * @throws LambdaConversionException If any of the linkage invariants
-     *                                   described {@link LambdaMetafactory above}
-     *                                   are violated, or the lookup context
-     *                                   does not have private access privileges.
+     *         instances of the interface named by {@code factoryType}
+     * @throws LambdaConversionException If {@code caller} does not have private
+     *         access privileges, or if {@code methodName} is not a valid JVM
+     *         method name, or if the return type of {@code factoryType} is not
+     *         an interface, or if {@code implementation} is not a direct method
+     *         handle referencing a method or constructor, or if the linkage
+     *         invariants are violated, as defined {@link LambdaMetafactory above}.
+     * @throws NullPointerException If any argument is {@code null}.
+     * @throws SecurityException If a security manager is present, and it
+     *         <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+     *         from {@code caller} to the package of {@code implementation}.
      */
     public static CallSite metafactory(MethodHandles.Lookup caller,
-                                       String invokedName,
-                                       MethodType invokedType,
-                                       MethodType samMethodType,
-                                       MethodHandle implMethod,
-                                       MethodType instantiatedMethodType)
+                                       String methodName,
+                                       MethodType factoryType,
+                                       MethodType interfaceMethodType,
+                                       MethodHandle implementation,
+                                       MethodType dynamicMethodType)
             throws LambdaConversionException {
         AbstractValidatingLambdaMetafactory mf;
-        mf = new InnerClassLambdaMetafactory(caller, invokedType,
-                                             invokedName, samMethodType,
-                                             implMethod, instantiatedMethodType,
-                                             false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
+        mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
+                                             Objects.requireNonNull(factoryType),
+                                             Objects.requireNonNull(methodName),
+                                             Objects.requireNonNull(interfaceMethodType),
+                                             Objects.requireNonNull(implementation),
+                                             Objects.requireNonNull(dynamicMethodType),
+                                             false,
+                                             EMPTY_CLASS_ARRAY,
+                                             EMPTY_MT_ARRAY);
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
 
     /**

@@ -349,27 +362,27 @@
      * parameter that contains additional parameters.  The declared argument
      * list for this method is:
      *
      * <pre>{@code
      *  CallSite altMetafactory(MethodHandles.Lookup caller,
-     *                          String invokedName,
-     *                          MethodType invokedType,
+     *                          String methodName,
+     *                          MethodType factoryType,
      *                          Object... args)
      * }</pre>
      *
      * <p>but it behaves as if the argument list is as follows:
      *
      * <pre>{@code
      *  CallSite altMetafactory(MethodHandles.Lookup caller,
-     *                          String invokedName,
-     *                          MethodType invokedType,
-     *                          MethodType samMethodType,
-     *                          MethodHandle implMethod,
-     *                          MethodType instantiatedMethodType,
+     *                          String methodName,
+     *                          MethodType factoryType,
+     *                          MethodType interfaceMethodType,
+     *                          MethodHandle implementation,
+     *                          MethodType dynamicMethodType,
      *                          int flags,
-     *                          int markerInterfaceCount,  // IF flags has MARKERS set
-     *                          Class... markerInterfaces, // IF flags has MARKERS set
+     *                          int interfaceCount,        // IF flags has MARKERS set
+     *                          Class... interfaces,       // IF flags has MARKERS set
      *                          int bridgeCount,           // IF flags has BRIDGES set
      *                          MethodType... bridges      // IF flags has BRIDGES set
      *                          )
      * }</pre>
      *

@@ -379,29 +392,29 @@
      * are interpreted as follows:
      * <ul>
      *     <li>{@code flags} indicates additional options; this is a bitwise
      *     OR of desired flags.  Defined flags are {@link #FLAG_BRIDGES},
      *     {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
-     *     <li>{@code markerInterfaceCount} is the number of additional interfaces
+     *     <li>{@code interfaceCount} is the number of additional interfaces
      *     the function object should implement, and is present if and only if the
      *     {@code FLAG_MARKERS} flag is set.</li>
-     *     <li>{@code markerInterfaces} is a variable-length list of additional
-     *     interfaces to implement, whose length equals {@code markerInterfaceCount},
+     *     <li>{@code interfaces} is a variable-length list of additional
+     *     interfaces to implement, whose length equals {@code interfaceCount},
      *     and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
      *     <li>{@code bridgeCount} is the number of additional method signatures
      *     the function object should implement, and is present if and only if
      *     the {@code FLAG_BRIDGES} flag is set.</li>
      *     <li>{@code bridges} is a variable-length list of additional
      *     methods signatures to implement, whose length equals {@code bridgeCount},
      *     and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
      * </ul>
      *
-     * <p>Each class named by {@code markerInterfaces} is subject to the same
-     * restrictions as {@code Rd}, the return type of {@code invokedType},
+     * <p>Each class named by {@code interfaces} is subject to the same
+     * restrictions as {@code Rd}, the return type of {@code factoryType},
      * as described {@link LambdaMetafactory above}.  Each {@code MethodType}
      * named by {@code bridges} is subject to the same restrictions as
-     * {@code samMethodType}, as described {@link LambdaMetafactory above}.
+     * {@code interfaceMethodType}, as described {@link LambdaMetafactory above}.
      *
      * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
      * will implement {@code Serializable}, and will have a {@code writeReplace}
      * method that returns an appropriate {@link SerializedLambda}.  The
      * {@code caller} class must have an appropriate {@code $deserializeLambda$}

@@ -410,13 +423,13 @@
      * <p>When the target of the {@code CallSite} returned from this method is
      * invoked, the resulting function objects are instances of a class with
      * the following properties:
      * <ul>
      *     <li>The class implements the interface named by the return type
-     *     of {@code invokedType} and any interfaces named by {@code markerInterfaces}</li>
-     *     <li>The class declares methods with the name given by {@code invokedName},
-     *     and the signature given by {@code samMethodType} and additional signatures
+     *     of {@code factoryType} and any interfaces named by {@code interfaces}</li>
+     *     <li>The class declares methods with the name given by {@code methodName},
+     *     and the signature given by {@code interfaceMethodType} and additional signatures
      *     given by {@code bridges}</li>
      *     <li>The class may override methods from {@code Object}, and may
      *     implement methods related to serialization.</li>
      * </ul>
      *

@@ -425,82 +438,121 @@
      *               must have
      *               <a href="MethodHandles.Lookup.html#privacc">private access</a>
      *               privileges.
      *               When used with {@code invokedynamic}, this is stacked
      *               automatically by the VM.
-     * @param invokedName The name of the method to implement.  When used with
+     * @param methodName The name of the method to implement.  When used with
      *                    {@code invokedynamic}, this is provided by the
      *                    {@code NameAndType} of the {@code InvokeDynamic}
      *                    structure and is stacked automatically by the VM.
-     * @param invokedType The expected signature of the {@code CallSite}.  The
+     * @param factoryType The expected signature of the {@code CallSite}.  The
      *                    parameter types represent the types of capture variables;
      *                    the return type is the interface to implement.   When
      *                    used with {@code invokedynamic}, this is provided by
      *                    the {@code NameAndType} of the {@code InvokeDynamic}
      *                    structure and is stacked automatically by the VM.
-     *                    In the event that the implementation method is an
-     *                    instance method and this signature has any parameters,
-     *                    the first parameter in the invocation signature must
-     *                    correspond to the receiver.
-     * @param  args       An {@code Object[]} array containing the required
-     *                    arguments {@code samMethodType}, {@code implMethod},
-     *                    {@code instantiatedMethodType}, {@code flags}, and any
-     *                    optional arguments, as described
-     *                    {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above}
+     * @param  args An array of {@code Object} containing the required
+     *              arguments {@code interfaceMethodType}, {@code implementation},
+     *              {@code dynamicMethodType}, {@code flags}, and any
+     *              optional arguments, as described above
      * @return a CallSite whose target can be used to perform capture, generating
-     *         instances of the interface named by {@code invokedType}
-     * @throws LambdaConversionException If any of the linkage invariants
-     *                                   described {@link LambdaMetafactory above}
-     *                                   are violated, or the lookup context
-     *                                   does not have private access privileges.
+     *         instances of the interface named by {@code factoryType}
+     * @throws LambdaConversionException If {@code caller} does not have private
+     *         access privileges, or if {@code methodName} is not a valid JVM
+     *         method name, or if the return type of {@code factoryType} is not
+     *         an interface, or if any of {@code interfaces} is not an
+     *         interface, or if {@code implementation} is not a direct method
+     *         handle referencing a method or constructor, or if the linkage
+     *         invariants are violated, as defined {@link LambdaMetafactory above}.
+     * @throws NullPointerException If any argument, or any component of {@code args},
+     *         is {@code null}.
+     * @throws IllegalArgumentException If the number or types of the components
+     *         of {@code args} do not follow the above rules, or if
+     *         {@code interfaceCount} or {@code bridgeCount} are negative
+     *         integers.
+     * @throws SecurityException If a security manager is present, and it
+     *         <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+     *         from {@code caller} to the package of {@code implementation}.
      */
     public static CallSite altMetafactory(MethodHandles.Lookup caller,
-                                          String invokedName,
-                                          MethodType invokedType,
+                                          String methodName,
+                                          MethodType factoryType,
                                           Object... args)
             throws LambdaConversionException {
-        MethodType samMethodType = (MethodType)args[0];
-        MethodHandle implMethod = (MethodHandle)args[1];
-        MethodType instantiatedMethodType = (MethodType)args[2];
-        int flags = (Integer) args[3];
-        Class<?>[] markerInterfaces;
-        MethodType[] bridges;
-        int argIndex = 4;
+        Objects.requireNonNull(caller);
+        Objects.requireNonNull(methodName);
+        Objects.requireNonNull(factoryType);
+        Objects.requireNonNull(args);
+        int argIndex = 0;
+        MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
+        MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
+        MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
+        int flags = extractArg(args, argIndex++, Integer.class);
+        Class<?>[] interfaces = EMPTY_CLASS_ARRAY;
+        MethodType[] bridges = EMPTY_MT_ARRAY;
         if ((flags & FLAG_MARKERS) != 0) {
-            int markerCount = (Integer) args[argIndex++];
-            markerInterfaces = new Class<?>[markerCount];
-            System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
-            argIndex += markerCount;
+            int interfaceCount = extractArg(args, argIndex++, Integer.class);
+            if (interfaceCount < 0) {
+                throw new IllegalArgumentException("negative argument count");
+            }
+            if (interfaceCount > 0) {
+                interfaces = extractArgs(args, argIndex, Class.class, interfaceCount);
+                argIndex += interfaceCount;
+            }
         }
-        else
-            markerInterfaces = EMPTY_CLASS_ARRAY;
         if ((flags & FLAG_BRIDGES) != 0) {
-            int bridgeCount = (Integer) args[argIndex++];
-            bridges = new MethodType[bridgeCount];
-            System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
+            int bridgeCount = extractArg(args, argIndex++, Integer.class);
+            if (bridgeCount < 0) {
+                throw new IllegalArgumentException("negative argument count");
+            }
+            if (bridgeCount > 0) {
+                bridges = extractArgs(args, argIndex, MethodType.class, bridgeCount);
             argIndex += bridgeCount;
         }
-        else
-            bridges = EMPTY_MT_ARRAY;
+        }
+        if (argIndex < args.length) {
+            throw new IllegalArgumentException("too many arguments");
+        }
 
         boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
         if (isSerializable) {
-            boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
-            for (Class<?> c : markerInterfaces)
+            boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
+            for (Class<?> c : interfaces)
                 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
             if (!foundSerializableSupertype) {
-                markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
-                markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+                interfaces = Arrays.copyOf(interfaces, interfaces.length + 1);
+                interfaces[interfaces.length-1] = Serializable.class;
             }
         }
 
         AbstractValidatingLambdaMetafactory mf
-                = new InnerClassLambdaMetafactory(caller, invokedType,
-                                                  invokedName, samMethodType,
-                                                  implMethod,
-                                                  instantiatedMethodType,
+                = new InnerClassLambdaMetafactory(caller, factoryType,
+                                                  methodName, interfaceMethodType,
+                                                  implementation,
+                                                  dynamicMethodType,
                                                   isSerializable,
-                                                  markerInterfaces, bridges);
+                                                  interfaces, bridges);
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
+
+    private static <T> T extractArg(Object[] args, int index, Class<T> type) {
+        if (index >= args.length) {
+            throw new IllegalArgumentException("missing argument");
+        }
+        Object result = Objects.requireNonNull(args[index]);
+        if (!type.isInstance(result)) {
+            throw new IllegalArgumentException("argument has wrong type");
+        }
+        return type.cast(result);
+    }
+
+    private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
+        @SuppressWarnings("unchecked")
+        T[] result = (T[]) Array.newInstance(type, count);
+        for (int i = 0; i < count; i++) {
+            result[i] = extractArg(args, index + i, type);
+        }
+        return result;
+    }
+
 }
< prev index next >