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<T> { int m(T x); }</code> if this functional interface type is used in a lambda
! * <code>I<Byte> 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();
}
}