jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java
changeset 18284 e281a0a2583e
parent 18182 a86f1b828425
child 18569 0e46c17766b7
equal deleted inserted replaced
18282:61693b1882bf 18284:e281a0a2583e
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.lang.invoke;
    26 package java.lang.invoke;
    27 
       
    28 import java.io.Serializable;
       
    29 import java.util.Arrays;
       
    30 
    27 
    31 /**
    28 /**
    32  * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
    29  * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
    33  *
    30  *
    34  * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
    31  * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
    45  * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
    42  * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
    46  * produces the lambda object.
    43  * produces the lambda object.
    47  *
    44  *
    48  * <p>When parameterized types are used, the instantiated type of the functional interface method may be different
    45  * <p>When parameterized types are used, the instantiated type of the functional interface method may be different
    49  * from that in the functional interface. For example, consider
    46  * from that in the functional interface. For example, consider
    50  * {@code interface I<T> { int m(T x); }} if this functional interface type is used in a lambda
    47  * <code>interface I&lt;T&gt; { int m(T x); }</code> if this functional interface type is used in a lambda
    51  * {@code I<Byte>; v = ...}, we need both the actual functional interface method which has the signature
    48  * <code>I&lt;Byte&gt; v = ...</code>, we need both the actual functional interface method which has the signature
    52  * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply
    49  * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply
    53  * <I>instantiated method type</I>), which has signature
    50  * <I>instantiated method type</I>), which has signature
    54  * {@code (Byte)int}.
    51  * <code>(Byte)int</code>.
       
    52  *
       
    53  * <p>While functional interfaces only have a single abstract method from the language perspective (concrete
       
    54  * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple
       
    55  * methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result
       
    56  * in invoking the implementation method.
    55  *
    57  *
    56  * <p>The argument list of the implementation method and the argument list of the functional interface method(s)
    58  * <p>The argument list of the implementation method and the argument list of the functional interface method(s)
    57  * may differ in several ways.  The implementation methods may have additional arguments to accommodate arguments
    59  * may differ in several ways.  The implementation methods may have additional arguments to accommodate arguments
    58  * captured by the lambda expression; there may also be differences resulting from permitted adaptations of
    60  * captured by the lambda expression; there may also be differences resulting from permitted adaptations of
    59  * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args,
    61  * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args,
   140  * or additional marker superinterfaces.
   142  * or additional marker superinterfaces.
   141  *
   143  *
   142  */
   144  */
   143 public class LambdaMetafactory {
   145 public class LambdaMetafactory {
   144 
   146 
   145     /** Flag for alternate metafactories indicating the lambda object is
   147     /** Flag for alternate metafactories indicating the lambda object is must to be serializable */
   146      * must to be serializable */
       
   147     public static final int FLAG_SERIALIZABLE = 1 << 0;
   148     public static final int FLAG_SERIALIZABLE = 1 << 0;
   148 
   149 
   149     /**
   150     /**
   150      * Flag for alternate metafactories indicating the lambda object implements
   151      * Flag for alternate metafactories indicating the lambda object implements other marker interfaces
   151      * other marker interfaces
       
   152      * besides Serializable
   152      * besides Serializable
   153      */
   153      */
   154     public static final int FLAG_MARKERS = 1 << 1;
   154     public static final int FLAG_MARKERS = 1 << 1;
   155 
   155 
   156     /**
       
   157      * Flag for alternate metafactories indicating the lambda object requires
       
   158      * additional bridge methods
       
   159      */
       
   160     public static final int FLAG_BRIDGES = 1 << 2;
       
   161 
       
   162     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
   156     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
   163     private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
   157 
   164 
   158 /**
   165     /**
   159      * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
   166      * Standard meta-factory for conversion of lambda expressions or method
   160      *
   167      * references to functional interfaces.
   161      * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
   168      *
   162      *               of the caller.
   169      * @param caller Stacked automatically by VM; represents a lookup context
   163      * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
   170      *                   with the accessibility privileges of the caller.
       
   171      * @param invokedName Stacked automatically by VM; the name of the invoked
       
   172      *                    method as it appears at the call site.
       
   173      *                    Currently unused.
   164      *                    Currently unused.
   174      * @param invokedType Stacked automatically by VM; the signature of the
   165      * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
   175      *                    invoked method, which includes the expected static
   166      *                    expected static type of the returned lambda object, and the static types of the captured
   176      *                    type of the returned lambda object, and the static
   167      *                    arguments for the lambda.  In the event that the implementation method is an instance method,
   177      *                    types of the captured arguments for the lambda.
   168      *                    the first argument in the invocation signature will correspond to the receiver.
   178      *                    In the event that the implementation method is an
   169      * @param samMethod The primary method in the functional interface to which the lambda or method reference is
   179      *                    instance method, the first argument in the invocation
   170      *                  being converted, represented as a method handle.
   180      *                    signature will correspond to the receiver.
   171      * @param implMethod The implementation method which should be called (with suitable adaptation of argument
   181      * @param samMethod The primary method in the functional interface to which
   172      *                   types, return types, and adjustment for captured arguments) when methods of the resulting
   182      *                  the lambda or method reference is being converted,
   173      *                   functional interface instance are invoked.
   183      *                  represented as a method handle.
   174      * @param instantiatedMethodType The signature of the primary functional interface method after type variables
   184      * @param implMethod The implementation method which should be called
   175      *                               are substituted with their instantiation from the capture site
   185      *                   (with suitable adaptation of argument types, return
   176      * @return a CallSite, which, when invoked, will return an instance of the functional interface
   186      *                   types, and adjustment for captured arguments) when
       
   187      *                   methods of the resulting functional interface instance
       
   188      *                   are invoked.
       
   189      * @param instantiatedMethodType The signature of the primary functional
       
   190      *                               interface method after type variables
       
   191      *                               are substituted with their instantiation
       
   192      *                               from the capture site
       
   193      * @return a CallSite, which, when invoked, will return an instance of the
       
   194      * functional interface
       
   195      * @throws ReflectiveOperationException
   177      * @throws ReflectiveOperationException
   196      * @throws LambdaConversionException If any of the meta-factory protocol
   178      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
   197      * invariants are violated
       
   198      */
   179      */
   199     public static CallSite metaFactory(MethodHandles.Lookup caller,
   180     public static CallSite metaFactory(MethodHandles.Lookup caller,
   200                                        String invokedName,
   181                                        String invokedName,
   201                                        MethodType invokedType,
   182                                        MethodType invokedType,
   202                                        MethodHandle samMethod,
   183                                        MethodHandle samMethod,
   203                                        MethodHandle implMethod,
   184                                        MethodHandle implMethod,
   204                                        MethodType instantiatedMethodType)
   185                                        MethodType instantiatedMethodType)
   205                    throws ReflectiveOperationException, LambdaConversionException {
   186                    throws ReflectiveOperationException, LambdaConversionException {
   206         AbstractValidatingLambdaMetafactory mf;
   187         AbstractValidatingLambdaMetafactory mf;
   207         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
   188         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
   208                                              implMethod, instantiatedMethodType,
   189                 0, EMPTY_CLASS_ARRAY);
   209                                              false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
       
   210         mf.validateMetafactoryArgs();
   190         mf.validateMetafactoryArgs();
   211         return mf.buildCallSite();
   191         return mf.buildCallSite();
   212     }
   192     }
   213 
   193 
   214     /**
   194     /**
   215      * Alternate meta-factory for conversion of lambda expressions or method
   195      * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
   216      * references to functional interfaces, which supports serialization and
   196      * which supports serialization and other uncommon options.
   217      * other uncommon options.
       
   218      *
   197      *
   219      * The declared argument list for this method is:
   198      * The declared argument list for this method is:
   220      *
   199      *
   221      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
   200      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
   222      *                          String invokedName,
   201      *                          String invokedName,
   232      *                          MethodHandle implMethod,
   211      *                          MethodHandle implMethod,
   233      *                          MethodType instantiatedMethodType,
   212      *                          MethodType instantiatedMethodType,
   234      *                          int flags,
   213      *                          int flags,
   235      *                          int markerInterfaceCount, // IF flags has MARKERS set
   214      *                          int markerInterfaceCount, // IF flags has MARKERS set
   236      *                          Class... markerInterfaces // IF flags has MARKERS set
   215      *                          Class... markerInterfaces // IF flags has MARKERS set
   237      *                          int bridgeCount,          // IF flags has BRIDGES set
       
   238      *                          MethodType... bridges     // IF flags has BRIDGES set
       
   239      *                          )
   216      *                          )
   240      *
   217      *
   241      *
   218      *
   242      * @param caller Stacked automatically by VM; represents a lookup context
   219      * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
   243      *               with the accessibility privileges of the caller.
   220      *               of the caller.
   244      * @param invokedName Stacked automatically by VM; the name of the invoked
   221      * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
   245      *                    method as it appears at the call site. Currently unused.
   222      *                    Currently unused.
   246      * @param invokedType Stacked automatically by VM; the signature of the
   223      * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
   247      *                    invoked method, which includes the expected static
   224      *                    expected static type of the returned lambda object, and the static types of the captured
   248      *                    type of the returned lambda object, and the static
   225      *                    arguments for the lambda.  In the event that the implementation method is an instance method,
   249      *                    types of the captured arguments for the lambda.
   226      *                    the first argument in the invocation signature will correspond to the receiver.
   250      *                    In the event that the implementation method is an
   227      * @param  args       argument to pass, flags, marker interface count, and marker interfaces as described above
   251      *                    instance method, the first argument in the invocation
   228      * @return a CallSite, which, when invoked, will return an instance of the functional interface
   252      *                    signature will correspond to the receiver.
       
   253      * @param  args       flags and optional arguments, as described above
       
   254      * @return a CallSite, which, when invoked, will return an instance of the
       
   255      * functional interface
       
   256      * @throws ReflectiveOperationException
   229      * @throws ReflectiveOperationException
   257      * @throws LambdaConversionException If any of the meta-factory protocol
   230      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
   258      * invariants are violated
       
   259      */
   231      */
   260     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
   232     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
   261                                           String invokedName,
   233                                           String invokedName,
   262                                           MethodType invokedType,
   234                                           MethodType invokedType,
   263                                           Object... args)
   235                                           Object... args)
   265         MethodHandle samMethod = (MethodHandle)args[0];
   237         MethodHandle samMethod = (MethodHandle)args[0];
   266         MethodHandle implMethod = (MethodHandle)args[1];
   238         MethodHandle implMethod = (MethodHandle)args[1];
   267         MethodType instantiatedMethodType = (MethodType)args[2];
   239         MethodType instantiatedMethodType = (MethodType)args[2];
   268         int flags = (Integer) args[3];
   240         int flags = (Integer) args[3];
   269         Class<?>[] markerInterfaces;
   241         Class<?>[] markerInterfaces;
   270         MethodType[] bridges;
       
   271         int argIndex = 4;
   242         int argIndex = 4;
   272         if ((flags & FLAG_MARKERS) != 0) {
   243         if ((flags & FLAG_MARKERS) != 0) {
   273             int markerCount = (Integer) args[argIndex++];
   244             int markerCount = (Integer) args[argIndex++];
   274             markerInterfaces = new Class<?>[markerCount];
   245             markerInterfaces = new Class<?>[markerCount];
   275             System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
   246             System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
   276             argIndex += markerCount;
   247             argIndex += markerCount;
   277         }
   248         }
   278         else
   249         else
   279             markerInterfaces = EMPTY_CLASS_ARRAY;
   250             markerInterfaces = EMPTY_CLASS_ARRAY;
   280         if ((flags & FLAG_BRIDGES) != 0) {
   251         AbstractValidatingLambdaMetafactory mf;
   281             int bridgeCount = (Integer) args[argIndex++];
   252         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
   282             bridges = new MethodType[bridgeCount];
   253                                              flags, markerInterfaces);
   283             System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
       
   284             argIndex += bridgeCount;
       
   285         }
       
   286         else
       
   287             bridges = EMPTY_MT_ARRAY;
       
   288 
       
   289         boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
       
   290         for (Class<?> c : markerInterfaces)
       
   291             foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
       
   292         boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
       
   293                                  || foundSerializableSupertype;
       
   294 
       
   295         if (isSerializable && !foundSerializableSupertype) {
       
   296             markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
       
   297             markerInterfaces[markerInterfaces.length-1] = Serializable.class;
       
   298         }
       
   299 
       
   300         AbstractValidatingLambdaMetafactory mf
       
   301                 = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
       
   302                                                   implMethod, instantiatedMethodType,
       
   303                                                   isSerializable, markerInterfaces, bridges);
       
   304         mf.validateMetafactoryArgs();
   254         mf.validateMetafactoryArgs();
   305         return mf.buildCallSite();
   255         return mf.buildCallSite();
   306     }
   256     }
   307 }
   257 }