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

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import java.io.Serializable;
  29 import java.util.Arrays;
  30 
  31 /**
  32  * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
  33  *
  34  * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
  35  * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for
  36  * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole
  37  * method of the functional interface and the implementation method, and returns an object (the lambda object) that
  38  * implements the target type. Methods of the lambda object invoke the implementation method. For method
  39  * references, the implementation method is simply the referenced method; for lambda expressions, the
  40  * implementation method is produced by the compiler based on the body of the lambda expression. The methods in
  41  * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the
  42  * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories.
  43  *
  44  * <p>The bootstrap methods in this class take the information about the functional interface, the implementation
  45  * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
  46  * produces the lambda object.
  47  *
  48  * <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
  50  * {@code interface I<T> { int m(T x); }} 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
  52  * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply
  53  * <I>instantiated method type</I>), which has signature
  54  * {@code (Byte)int}.
  55  *





  56  * <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
  58  * 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,
  60  * but this is expected to be handled by the compiler.
  61  *
  62  * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list.  The
  63  * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at
  64  * invocation time.  The bootstrap method has access to the entire static argument list (which in this case,
  65  * contains method handles describing the implementation method and the canonical functional interface method),
  66  * as well as a method signature describing the number and static types (but not the values) of the dynamic
  67  * arguments, and the static return type of the invokedynamic site.
  68  *
  69  * <p>The implementation method is described with a method handle. In theory, any method handle could be used.
  70  * Currently supported are method handles representing invocation of virtual, interface, constructor and static
  71  * methods.
  72  *
  73  * <p>Assume:
  74  * <ul>
  75  *      <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li>


 125  *         <td>Reference</td><td>Primitive</td>
 126  *         <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
 127  *         <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
 128  *         <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
 129  *     </tr>
 130  *     <tr>
 131  *         <td>Reference</td><td>Reference</td>
 132  *         <td>strict: S is a supertype of Q
 133  *         <br>loose: none</td>
 134  *         <td>Cast from Q to S</td>
 135  *     </tr>
 136  * </table>
 137  *
 138  * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol.
 139  * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization
 140  * or additional marker superinterfaces.
 141  *
 142  */
 143 public class LambdaMetafactory {
 144 
 145     /** Flag for alternate metafactories indicating the lambda object is
 146      * must to be serializable */
 147     public static final int FLAG_SERIALIZABLE = 1 << 0;
 148 
 149     /**
 150      * Flag for alternate metafactories indicating the lambda object implements
 151      * other marker interfaces
 152      * besides Serializable
 153      */
 154     public static final int FLAG_MARKERS = 1 << 1;
 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];
 163     private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
 164 
 165     /**
 166      * Standard meta-factory for conversion of lambda expressions or method
 167      * references to functional interfaces.
 168      *
 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.
 173      *                    Currently unused.
 174      * @param invokedType Stacked automatically by VM; the signature of the
 175      *                    invoked method, which includes the expected static
 176      *                    type of the returned lambda object, and the static
 177      *                    types of the captured arguments for the lambda.
 178      *                    In the event that the implementation method is an
 179      *                    instance method, the first argument in the invocation
 180      *                    signature will correspond to the receiver.
 181      * @param samMethod The primary method in the functional interface to which
 182      *                  the lambda or method reference is being converted,
 183      *                  represented as a method handle.
 184      * @param implMethod The implementation method which should be called
 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
 195      * @throws ReflectiveOperationException
 196      * @throws LambdaConversionException If any of the meta-factory protocol
 197      * invariants are violated
 198      */
 199     public static CallSite metaFactory(MethodHandles.Lookup caller,
 200                                        String invokedName,
 201                                        MethodType invokedType,
 202                                        MethodHandle samMethod,
 203                                        MethodHandle implMethod,
 204                                        MethodType instantiatedMethodType)
 205                    throws ReflectiveOperationException, LambdaConversionException {
 206         AbstractValidatingLambdaMetafactory mf;
 207         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
 208                                              implMethod, instantiatedMethodType,
 209                                              false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
 210         mf.validateMetafactoryArgs();
 211         return mf.buildCallSite();
 212     }
 213 
 214     /**
 215      * Alternate meta-factory for conversion of lambda expressions or method
 216      * references to functional interfaces, which supports serialization and
 217      * other uncommon options.
 218      *
 219      * The declared argument list for this method is:
 220      *
 221      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
 222      *                          String invokedName,
 223      *                          MethodType invokedType,
 224      *                          Object... args)
 225      *
 226      * but it behaves as if the argument list is:
 227      *
 228      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
 229      *                          String invokedName,
 230      *                          MethodType invokedType,
 231      *                          MethodHandle samMethod
 232      *                          MethodHandle implMethod,
 233      *                          MethodType instantiatedMethodType,
 234      *                          int flags,
 235      *                          int markerInterfaceCount, // 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
 239      *                          )
 240      *
 241      *
 242      * @param caller Stacked automatically by VM; represents a lookup context
 243      *               with the accessibility privileges of the caller.
 244      * @param invokedName Stacked automatically by VM; the name of the invoked
 245      *                    method as it appears at the call site. Currently unused.
 246      * @param invokedType Stacked automatically by VM; the signature of the
 247      *                    invoked method, which includes the expected static
 248      *                    type of the returned lambda object, and the static
 249      *                    types of the captured arguments for the lambda.
 250      *                    In the event that the implementation method is an
 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
 256      * @throws ReflectiveOperationException
 257      * @throws LambdaConversionException If any of the meta-factory protocol
 258      * invariants are violated
 259      */
 260     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
 261                                           String invokedName,
 262                                           MethodType invokedType,
 263                                           Object... args)
 264             throws ReflectiveOperationException, LambdaConversionException {
 265         MethodHandle samMethod = (MethodHandle)args[0];
 266         MethodHandle implMethod = (MethodHandle)args[1];
 267         MethodType instantiatedMethodType = (MethodType)args[2];
 268         int flags = (Integer) args[3];
 269         Class<?>[] markerInterfaces;
 270         MethodType[] bridges;
 271         int argIndex = 4;
 272         if ((flags & FLAG_MARKERS) != 0) {
 273             int markerCount = (Integer) args[argIndex++];
 274             markerInterfaces = new Class<?>[markerCount];
 275             System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
 276             argIndex += markerCount;
 277         }
 278         else
 279             markerInterfaces = EMPTY_CLASS_ARRAY;
 280         if ((flags & FLAG_BRIDGES) != 0) {
 281             int bridgeCount = (Integer) args[argIndex++];
 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);
 304         mf.validateMetafactoryArgs();
 305         return mf.buildCallSite();
 306     }
 307 }


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 



  28 /**
  29  * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
  30  *
  31  * <p>For every lambda expressions or method reference in the source code, there is a target type which is a
  32  * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for
  33  * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole
  34  * method of the functional interface and the implementation method, and returns an object (the lambda object) that
  35  * implements the target type. Methods of the lambda object invoke the implementation method. For method
  36  * references, the implementation method is simply the referenced method; for lambda expressions, the
  37  * implementation method is produced by the compiler based on the body of the lambda expression. The methods in
  38  * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the
  39  * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories.
  40  *
  41  * <p>The bootstrap methods in this class take the information about the functional interface, the implementation
  42  * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
  43  * produces the lambda object.
  44  *
  45  * <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
  47  * <code>interface I&lt;T&gt; { int m(T x); }</code> 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
  49  * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply
  50  * <I>instantiated method type</I>), which has signature
  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.
  57  *
  58  * <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
  60  * 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,
  62  * but this is expected to be handled by the compiler.
  63  *
  64  * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list.  The
  65  * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at
  66  * invocation time.  The bootstrap method has access to the entire static argument list (which in this case,
  67  * contains method handles describing the implementation method and the canonical functional interface method),
  68  * as well as a method signature describing the number and static types (but not the values) of the dynamic
  69  * arguments, and the static return type of the invokedynamic site.
  70  *
  71  * <p>The implementation method is described with a method handle. In theory, any method handle could be used.
  72  * Currently supported are method handles representing invocation of virtual, interface, constructor and static
  73  * methods.
  74  *
  75  * <p>Assume:
  76  * <ul>
  77  *      <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li>


 127  *         <td>Reference</td><td>Primitive</td>
 128  *         <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
 129  *         <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
 130  *         <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
 131  *     </tr>
 132  *     <tr>
 133  *         <td>Reference</td><td>Reference</td>
 134  *         <td>strict: S is a supertype of Q
 135  *         <br>loose: none</td>
 136  *         <td>Cast from Q to S</td>
 137  *     </tr>
 138  * </table>
 139  *
 140  * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol.
 141  * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization
 142  * or additional marker superinterfaces.
 143  *
 144  */
 145 public class LambdaMetafactory {
 146 
 147     /** Flag for alternate metafactories indicating the lambda object is must to be serializable */

 148     public static final int FLAG_SERIALIZABLE = 1 << 0;
 149 
 150     /**
 151      * Flag for alternate metafactories indicating the lambda object implements other marker interfaces

 152      * besides Serializable
 153      */
 154     public static final int FLAG_MARKERS = 1 << 1;
 155 






 156     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];

 157 
 158 /**
 159      * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.

 160      *
 161      * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
 162      *               of the caller.
 163      * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.

 164      *                    Currently unused.
 165      * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
 166      *                    expected static type of the returned lambda object, and the static types of the captured
 167      *                    arguments for the lambda.  In the event that the implementation method is an instance method,
 168      *                    the first argument in the invocation signature will correspond to the receiver.
 169      * @param samMethod The primary method in the functional interface to which the lambda or method reference is
 170      *                  being converted, represented as a method handle.
 171      * @param implMethod The implementation method which should be called (with suitable adaptation of argument
 172      *                   types, return types, and adjustment for captured arguments) when methods of the resulting
 173      *                   functional interface instance are invoked.
 174      * @param instantiatedMethodType The signature of the primary functional interface method after type variables
 175      *                               are substituted with their instantiation from the capture site
 176      * @return a CallSite, which, when invoked, will return an instance of the functional interface









 177      * @throws ReflectiveOperationException
 178      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated

 179      */
 180     public static CallSite metaFactory(MethodHandles.Lookup caller,
 181                                        String invokedName,
 182                                        MethodType invokedType,
 183                                        MethodHandle samMethod,
 184                                        MethodHandle implMethod,
 185                                        MethodType instantiatedMethodType)
 186                    throws ReflectiveOperationException, LambdaConversionException {
 187         AbstractValidatingLambdaMetafactory mf;
 188         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
 189                 0, EMPTY_CLASS_ARRAY);

 190         mf.validateMetafactoryArgs();
 191         return mf.buildCallSite();
 192     }
 193 
 194     /**
 195      * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
 196      * which supports serialization and other uncommon options.

 197      *
 198      * The declared argument list for this method is:
 199      *
 200      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
 201      *                          String invokedName,
 202      *                          MethodType invokedType,
 203      *                          Object... args)
 204      *
 205      * but it behaves as if the argument list is:
 206      *
 207      *  CallSite altMetaFactory(MethodHandles.Lookup caller,
 208      *                          String invokedName,
 209      *                          MethodType invokedType,
 210      *                          MethodHandle samMethod
 211      *                          MethodHandle implMethod,
 212      *                          MethodType instantiatedMethodType,
 213      *                          int flags,
 214      *                          int markerInterfaceCount, // IF flags has MARKERS set
 215      *                          Class... markerInterfaces // IF flags has MARKERS set


 216      *                          )
 217      *
 218      *
 219      * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
 220      *               of the caller.
 221      * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
 222      *                    Currently unused.
 223      * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
 224      *                    expected static type of the returned lambda object, and the static types of the captured
 225      *                    arguments for the lambda.  In the event that the implementation method is an instance method,
 226      *                    the first argument in the invocation signature will correspond to the receiver.
 227      * @param  args       argument to pass, flags, marker interface count, and marker interfaces as described above
 228      * @return a CallSite, which, when invoked, will return an instance of the functional interface




 229      * @throws ReflectiveOperationException
 230      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated

 231      */
 232     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
 233                                           String invokedName,
 234                                           MethodType invokedType,
 235                                           Object... args)
 236             throws ReflectiveOperationException, LambdaConversionException {
 237         MethodHandle samMethod = (MethodHandle)args[0];
 238         MethodHandle implMethod = (MethodHandle)args[1];
 239         MethodType instantiatedMethodType = (MethodType)args[2];
 240         int flags = (Integer) args[3];
 241         Class<?>[] markerInterfaces;

 242         int argIndex = 4;
 243         if ((flags & FLAG_MARKERS) != 0) {
 244             int markerCount = (Integer) args[argIndex++];
 245             markerInterfaces = new Class<?>[markerCount];
 246             System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
 247             argIndex += markerCount;
 248         }
 249         else
 250             markerInterfaces = EMPTY_CLASS_ARRAY;
 251         AbstractValidatingLambdaMetafactory mf;
 252         mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
 253                                              flags, markerInterfaces);





















 254         mf.validateMetafactoryArgs();
 255         return mf.buildCallSite();
 256     }
 257 }