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

Print this page




  94  *         <li>For i=1..K, Di = Ai</li>
  95  *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
  96  *     </ul></li>
  97  *     <li>If the implementation method is an instance method:
  98  *     <ul>
  99  *         <li>K + N = M + 1</li>
 100  *         <li>D1 must be a subtype of the enclosing class for the implementation method</li>
 101  *         <li>For i=2..K, Di = Aj, where j=i-1</li>
 102  *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
 103  *     </ul></li>
 104  *     <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
 105  * </ul>
 106  *
 107  * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
 108  * the completely known instantiated return type is adapted to the implementation arguments. Because the
 109  * instantiated type of the implementation method is not available, the adaptability of return types cannot be
 110  * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
 111  * done on return type, while a strict version is applied to arguments.
 112  *
 113  * <p>A type Q is considered adaptable to S as follows:
 114  * <table>
 115  *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
 116  *     <tr>
 117  *         <td>Primitive</td><td>Primitive</td>
 118  *         <td>Q can be converted to S via a primitive widening conversion</td>
 119  *         <td>None</td>
 120  *     </tr>
 121  *     <tr>
 122  *         <td>Primitive</td><td>Reference</td>
 123  *         <td>S is a supertype of the Wrapper(Q)</td>
 124  *         <td>Cast from Wrapper(Q) to S</td>
 125  *     </tr>
 126  *     <tr>
 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


 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      *


 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


  94  *         <li>For i=1..K, Di = Ai</li>
  95  *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
  96  *     </ul></li>
  97  *     <li>If the implementation method is an instance method:
  98  *     <ul>
  99  *         <li>K + N = M + 1</li>
 100  *         <li>D1 must be a subtype of the enclosing class for the implementation method</li>
 101  *         <li>For i=2..K, Di = Aj, where j=i-1</li>
 102  *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
 103  *     </ul></li>
 104  *     <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
 105  * </ul>
 106  *
 107  * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
 108  * the completely known instantiated return type is adapted to the implementation arguments. Because the
 109  * instantiated type of the implementation method is not available, the adaptability of return types cannot be
 110  * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
 111  * done on return type, while a strict version is applied to arguments.
 112  *
 113  * <p>A type Q is considered adaptable to S as follows:
 114  * <table summary="adaptable types">
 115  *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
 116  *     <tr>
 117  *         <td>Primitive</td><td>Primitive</td>
 118  *         <td>Q can be converted to S via a primitive widening conversion</td>
 119  *         <td>None</td>
 120  *     </tr>
 121  *     <tr>
 122  *         <td>Primitive</td><td>Reference</td>
 123  *         <td>S is a supertype of the Wrapper(Q)</td>
 124  *         <td>Cast from Wrapper(Q) to S</td>
 125  *     </tr>
 126  *     <tr>
 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


 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 if the caller is not able to reconstruct one of the method handles
 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      *


 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 if the caller is not able to reconstruct one of the method handles
 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