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

Print this page

        

*** 23,35 **** * 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 --- 23,32 ----
*** 45,60 **** * 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 * <I>instantiated method type</I>), which has signature ! * {@code (Byte)int}. * * <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. --- 42,62 ---- * 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&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>. * + * <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,222 **** * or additional marker superinterfaces. * */ public class LambdaMetafactory { ! /** 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 * 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. * ! * @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 * @throws ReflectiveOperationException ! * @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.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. * * The declared argument list for this method is: * * CallSite altMetaFactory(MethodHandles.Lookup caller, * String invokedName, --- 142,201 ---- * or additional marker superinterfaces. * */ public class LambdaMetafactory { ! /** 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 * besides Serializable */ public static final int FLAG_MARKERS = 1 << 1; private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; ! /** ! * 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. * 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 * @throws ReflectiveOperationException ! * @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, ! 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. * * The declared argument list for this method is: * * CallSite altMetaFactory(MethodHandles.Lookup caller, * String invokedName,
*** 232,263 **** * 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 * @throws ReflectiveOperationException ! * @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) --- 211,235 ---- * MethodHandle implMethod, * MethodType instantiatedMethodType, * int flags, * int markerInterfaceCount, // IF flags has MARKERS set * Class... markerInterfaces // IF flags has MARKERS 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 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 */ public static CallSite altMetaFactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args)
*** 265,307 **** 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); mf.validateMetafactoryArgs(); return mf.buildCallSite(); } } --- 237,257 ---- MethodHandle samMethod = (MethodHandle)args[0]; MethodHandle implMethod = (MethodHandle)args[1]; MethodType instantiatedMethodType = (MethodType)args[2]; int flags = (Integer) args[3]; Class<?>[] markerInterfaces; 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; ! AbstractValidatingLambdaMetafactory mf; ! mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, ! flags, markerInterfaces); mf.validateMetafactoryArgs(); return mf.buildCallSite(); } }