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

Print this page

        

@@ -23,13 +23,10 @@
  * questions.
  */
 
 package java.lang.invoke;
 
-import java.io.Serializable;
-import java.util.Arrays;
-
 /**
  * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
  *
  * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
  * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for

@@ -45,16 +42,21 @@
  * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
  * produces the lambda object.
  *
  * <p>When parameterized types are used, the instantiated type of the functional interface method may be different
  * from that in the functional interface. For example, consider
- * {@code interface I<T> { int m(T x); }} if this functional interface type is used in a lambda
- * {@code I<Byte>; v = ...}, we need both the actual functional interface method which has the signature
- * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply
+ * <code>interface I&lt;T&gt; { int m(T x); }</code> if this functional interface type is used in a lambda
+ * <code>I&lt;Byte&gt; v = ...</code>, we need both the actual functional interface method which has the signature
+ * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply
  * <I>instantiated method type</I>), which has signature
- * {@code (Byte)int}.
+ * <code>(Byte)int</code>.
  *
+ * <p>While functional interfaces only have a single abstract method from the language perspective (concrete
+ * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple
+ * methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result
+ * in invoking the implementation method.
+ *
  * <p>The argument list of the implementation method and the argument list of the functional interface method(s)
  * may differ in several ways.  The implementation methods may have additional arguments to accommodate arguments
  * captured by the lambda expression; there may also be differences resulting from permitted adaptations of
  * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args,
  * but this is expected to be handled by the compiler.

@@ -140,83 +142,60 @@
  * or additional marker superinterfaces.
  *
  */
 public class LambdaMetafactory {
 
-    /** Flag for alternate metafactories indicating the lambda object is
-     * must to be serializable */
+    /** Flag for alternate metafactories indicating the lambda object is must to be serializable */
     public static final int FLAG_SERIALIZABLE = 1 << 0;
 
     /**
-     * Flag for alternate metafactories indicating the lambda object implements
-     * other marker interfaces
+     * Flag for alternate metafactories indicating the lambda object implements other marker interfaces
      * besides Serializable
      */
     public static final int FLAG_MARKERS = 1 << 1;
 
-    /**
-     * Flag for alternate metafactories indicating the lambda object requires
-     * additional bridge methods
-     */
-    public static final int FLAG_BRIDGES = 1 << 2;
-
     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
-    private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
 
-    /**
-     * Standard meta-factory for conversion of lambda expressions or method
-     * references to functional interfaces.
+/**
+     * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
      *
-     * @param caller Stacked automatically by VM; represents a lookup context
-     *                   with the accessibility privileges of the caller.
-     * @param invokedName Stacked automatically by VM; the name of the invoked
-     *                    method as it appears at the call site.
+     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+     *               of the caller.
+     * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
      *                    Currently unused.
-     * @param invokedType Stacked automatically by VM; the signature of the
-     *                    invoked method, which includes the expected static
-     *                    type of the returned lambda object, and the static
-     *                    types of the captured arguments for the lambda.
-     *                    In the event that the implementation method is an
-     *                    instance method, the first argument in the invocation
-     *                    signature will correspond to the receiver.
-     * @param samMethod The primary method in the functional interface to which
-     *                  the lambda or method reference is being converted,
-     *                  represented as a method handle.
-     * @param implMethod The implementation method which should be called
-     *                   (with suitable adaptation of argument types, return
-     *                   types, and adjustment for captured arguments) when
-     *                   methods of the resulting functional interface instance
-     *                   are invoked.
-     * @param instantiatedMethodType The signature of the primary functional
-     *                               interface method after type variables
-     *                               are substituted with their instantiation
-     *                               from the capture site
-     * @return a CallSite, which, when invoked, will return an instance of the
-     * functional interface
+     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
+     *                    expected static type of the returned lambda object, and the static types of the captured
+     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
+     *                    the first argument in the invocation signature will correspond to the receiver.
+     * @param samMethod The primary method in the functional interface to which the lambda or method reference is
+     *                  being converted, represented as a method handle.
+     * @param implMethod The implementation method which should be called (with suitable adaptation of argument
+     *                   types, return types, and adjustment for captured arguments) when methods of the resulting
+     *                   functional interface instance are invoked.
+     * @param instantiatedMethodType The signature of the primary functional interface method after type variables
+     *                               are substituted with their instantiation from the capture site
+     * @return a CallSite, which, when invoked, will return an instance of the functional interface
      * @throws ReflectiveOperationException
-     * @throws LambdaConversionException If any of the meta-factory protocol
-     * invariants are violated
+     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
      */
     public static CallSite metaFactory(MethodHandles.Lookup caller,
                                        String invokedName,
                                        MethodType invokedType,
                                        MethodHandle samMethod,
                                        MethodHandle implMethod,
                                        MethodType instantiatedMethodType)
                    throws ReflectiveOperationException, LambdaConversionException {
         AbstractValidatingLambdaMetafactory mf;
-        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
-                                             implMethod, instantiatedMethodType,
-                                             false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
+        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
+                0, EMPTY_CLASS_ARRAY);
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
 
     /**
-     * Alternate meta-factory for conversion of lambda expressions or method
-     * references to functional interfaces, which supports serialization and
-     * other uncommon options.
+     * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
+     * which supports serialization and other uncommon options.
      *
      * The declared argument list for this method is:
      *
      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
      *                          String invokedName,

@@ -232,32 +211,25 @@
      *                          MethodHandle implMethod,
      *                          MethodType instantiatedMethodType,
      *                          int flags,
      *                          int markerInterfaceCount, // IF flags has MARKERS set
      *                          Class... markerInterfaces // IF flags has MARKERS set
-     *                          int bridgeCount,          // IF flags has BRIDGES set
-     *                          MethodType... bridges     // IF flags has BRIDGES set
      *                          )
      *
      *
-     * @param caller Stacked automatically by VM; represents a lookup context
-     *               with the accessibility privileges of the caller.
-     * @param invokedName Stacked automatically by VM; the name of the invoked
-     *                    method as it appears at the call site. Currently unused.
-     * @param invokedType Stacked automatically by VM; the signature of the
-     *                    invoked method, which includes the expected static
-     *                    type of the returned lambda object, and the static
-     *                    types of the captured arguments for the lambda.
-     *                    In the event that the implementation method is an
-     *                    instance method, the first argument in the invocation
-     *                    signature will correspond to the receiver.
-     * @param  args       flags and optional arguments, as described above
-     * @return a CallSite, which, when invoked, will return an instance of the
-     * functional interface
+     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+     *               of the caller.
+     * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
+     *                    Currently unused.
+     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
+     *                    expected static type of the returned lambda object, and the static types of the captured
+     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
+     *                    the first argument in the invocation signature will correspond to the receiver.
+     * @param  args       argument to pass, flags, marker interface count, and marker interfaces as described above
+     * @return a CallSite, which, when invoked, will return an instance of the functional interface
      * @throws ReflectiveOperationException
-     * @throws LambdaConversionException If any of the meta-factory protocol
-     * invariants are violated
+     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
      */
     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
                                           String invokedName,
                                           MethodType invokedType,
                                           Object... args)

@@ -265,43 +237,21 @@
         MethodHandle samMethod = (MethodHandle)args[0];
         MethodHandle implMethod = (MethodHandle)args[1];
         MethodType instantiatedMethodType = (MethodType)args[2];
         int flags = (Integer) args[3];
         Class<?>[] markerInterfaces;
-        MethodType[] bridges;
         int argIndex = 4;
         if ((flags & FLAG_MARKERS) != 0) {
             int markerCount = (Integer) args[argIndex++];
             markerInterfaces = new Class<?>[markerCount];
             System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
             argIndex += markerCount;
         }
         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);
-            argIndex += bridgeCount;
-        }
-        else
-            bridges = EMPTY_MT_ARRAY;
-
-        boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
-        for (Class<?> c : markerInterfaces)
-            foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
-        boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
-                                 || foundSerializableSupertype;
-
-        if (isSerializable && !foundSerializableSupertype) {
-            markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
-            markerInterfaces[markerInterfaces.length-1] = Serializable.class;
-        }
-
-        AbstractValidatingLambdaMetafactory mf
-                = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
-                                                  implMethod, instantiatedMethodType,
-                                                  isSerializable, markerInterfaces, bridges);
+        AbstractValidatingLambdaMetafactory mf;
+        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
+                                             flags, markerInterfaces);
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
 }