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