--- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Tue Jun 18 21:08:48 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Wed Jun 19 11:47:14 2013 +0100
@@ -24,11 +24,14 @@
*/
package java.lang.invoke;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import sun.invoke.util.Wrapper;
-
-import static sun.invoke.util.Wrapper.forPrimitiveType;
-import static sun.invoke.util.Wrapper.forWrapperType;
-import static sun.invoke.util.Wrapper.isWrapperType;
+import static sun.invoke.util.Wrapper.*;
/**
* Abstract implementation of a lambda metafactory which provides parameter unrolling and input validation.
@@ -64,52 +67,34 @@
final MethodType instantiatedMethodType; // Instantiated erased functional interface method type "(Integer)Object"
final boolean isSerializable; // Should the returned instance be serializable
final Class<?>[] markerInterfaces; // Additional marker interfaces to be implemented
- final MethodType[] additionalBridges; // Signatures of additional methods to bridge
/**
* Meta-factory constructor.
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @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
- * @param isSerializable Should the lambda be made serializable? If set,
- * either the target type or one of the additional SAM
- * types must extend {@code Serializable}.
- * @param markerInterfaces Additional interfaces which the lambda object
- * should implement.
- * @param additionalBridges Method types for additional signatures to be
- * bridged to the implementation method
+ * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+ * of the caller.
+ * @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
* @throws ReflectiveOperationException
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller,
MethodType invokedType,
MethodHandle samMethod,
MethodHandle implMethod,
MethodType instantiatedMethodType,
- boolean isSerializable,
- Class<?>[] markerInterfaces,
- MethodType[] additionalBridges)
+ int flags,
+ Class<?>[] markerInterfaces)
throws ReflectiveOperationException, LambdaConversionException {
this.targetClass = caller.lookupClass();
this.invokedType = invokedType;
@@ -133,22 +118,32 @@
implKind == MethodHandleInfo.REF_invokeInterface;
this.implDefiningClass = implInfo.getDeclaringClass();
this.implMethodType = implInfo.getMethodType();
+
this.instantiatedMethodType = instantiatedMethodType;
- this.isSerializable = isSerializable;
- this.markerInterfaces = markerInterfaces;
- this.additionalBridges = additionalBridges;
if (!samClass.isInterface()) {
throw new LambdaConversionException(String.format(
- "Functional interface %s is not an interface", samClass.getName()));
+ "Functional interface %s is not an interface",
+ samClass.getName()));
}
+ boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(samBase);
for (Class<?> c : markerInterfaces) {
if (!c.isInterface()) {
throw new LambdaConversionException(String.format(
- "Marker interface %s is not an interface", c.getName()));
+ "Marker interface %s is not an interface",
+ c.getName()));
}
+ foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
}
+ this.isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
+ || foundSerializableSupertype;
+
+ if (isSerializable && !foundSerializableSupertype) {
+ markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
+ markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+ }
+ this.markerInterfaces = markerInterfaces;
}
/**
@@ -270,9 +265,9 @@
}
/**
- * Check type adaptability for parameter types.
- * @param fromType Type to convert from
- * @param toType Type to convert to
+ * Check type adaptability
+ * @param fromType
+ * @param toType
* @param strict If true, do strict checks, else allow that fromType may be parameterized
* @return True if 'fromType' can be passed to an argument of 'toType'
*/
@@ -304,14 +299,15 @@
}
} else {
// both are reference types: fromType should be a superclass of toType.
- return !strict || toType.isAssignableFrom(fromType);
+ return strict? toType.isAssignableFrom(fromType) : true;
}
}
}
/**
- * Check type adaptability for return types -- special handling of void type)
- * and parameterized fromType
+ * Check type adaptability for return types -- special handling of void type) and parameterized fromType
+ * @param fromType
+ * @param toType
* @return True if 'fromType' can be converted to 'toType'
*/
private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
@@ -342,4 +338,89 @@
}
***********************/
+ /**
+ * Find the functional interface method and corresponding abstract methods
+ * which should be bridged. The functional interface method and those to be
+ * bridged will have the same name and number of parameters. Check for
+ * matching default methods (non-abstract), the VM will create bridges for
+ * default methods; We don't have enough readily available type information
+ * to distinguish between where the functional interface method should be
+ * bridged and where the default method should be bridged; This situation is
+ * flagged.
+ */
+ class MethodAnalyzer {
+ private final Method[] methods = samBase.getMethods();
+
+ private Method samMethod = null;
+ private final List<Method> methodsToBridge = new ArrayList<>(methods.length);
+ private boolean conflictFoundBetweenDefaultAndBridge = false;
+
+ MethodAnalyzer() {
+ String samMethodName = samInfo.getName();
+ Class<?>[] samParamTypes = samMethodType.parameterArray();
+ int samParamLength = samParamTypes.length;
+ Class<?> samReturnType = samMethodType.returnType();
+ Class<?> objectClass = Object.class;
+ List<Method> defaultMethods = new ArrayList<>(methods.length);
+
+ for (Method m : methods) {
+ if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) {
+ Class<?>[] mParamTypes = m.getParameterTypes();
+ if (mParamTypes.length == samParamLength) {
+ // Method matches name and parameter length -- and is not Object
+ if (Modifier.isAbstract(m.getModifiers())) {
+ // Method is abstract
+ if (m.getReturnType().equals(samReturnType)
+ && Arrays.equals(mParamTypes, samParamTypes)) {
+ // Exact match, this is the SAM method signature
+ samMethod = m;
+ } else if (!hasMatchingBridgeSignature(m)) {
+ // Record bridges, exclude methods with duplicate signatures
+ methodsToBridge.add(m);
+ }
+ } else {
+ // Record default methods for conflict testing
+ defaultMethods.add(m);
+ }
+ }
+ }
+ }
+ for (Method dm : defaultMethods) {
+ if (hasMatchingBridgeSignature(dm)) {
+ conflictFoundBetweenDefaultAndBridge = true;
+ break;
+ }
+ }
+ }
+
+ Method getSamMethod() {
+ return samMethod;
+ }
+
+ List<Method> getMethodsToBridge() {
+ return methodsToBridge;
+ }
+
+ boolean conflictFoundBetweenDefaultAndBridge() {
+ return conflictFoundBetweenDefaultAndBridge;
+ }
+
+ /**
+ * Search the list of previously found bridge methods to determine if there is a method with the same signature
+ * (return and parameter types) as the specified method.
+ *
+ * @param m The method to match
+ * @return True if the method was found, False otherwise
+ */
+ private boolean hasMatchingBridgeSignature(Method m) {
+ Class<?>[] ptypes = m.getParameterTypes();
+ Class<?> rtype = m.getReturnType();
+ for (Method md : methodsToBridge) {
+ if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
}
--- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Tue Jun 18 21:08:48 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Wed Jun 19 11:47:14 2013 +0100
@@ -25,16 +25,15 @@
package java.lang.invoke;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicInteger;
import jdk.internal.org.objectweb.asm.*;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
import sun.misc.Unsafe;
-
-import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static jdk.internal.org.objectweb.asm.Opcodes.*;
/**
* Lambda metafactory implementation which dynamically creates an inner-class-like class per lambda callsite.
@@ -42,8 +41,6 @@
* @see LambdaMetafactory
*/
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
- private static final Unsafe UNSAFE = Unsafe.getUnsafe();
-
private static final int CLASSFILE_VERSION = 51;
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
@@ -80,51 +77,36 @@
private final Type[] instantiatedArgumentTypes; // ASM types for the functional interface arguments
/**
- * General meta-factory constructor, supporting both standard cases and
- * allowing for uncommon options such as serialization or bridging.
+ * General meta-factory constructor, standard cases and allowing for uncommon options such as serialization.
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @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
- * @param isSerializable Should the lambda be made serializable? If set,
- * either the target type or one of the additional SAM
- * types must extend {@code Serializable}.
- * @param markerInterfaces Additional interfaces which the lambda object
- * should implement.
- * @param additionalBridges Method types for additional signatures to be
- * bridged to the implementation method
+ * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+ * of the caller.
+ * @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
+ * @param flags A bitmask containing flags that may influence the translation of this lambda expression. Defined
+ * fields include FLAG_SERIALIZABLE.
+ * @param markerInterfaces Additional interfaces which the lambda object should implement.
* @throws ReflectiveOperationException
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
MethodType invokedType,
MethodHandle samMethod,
MethodHandle implMethod,
MethodType instantiatedMethodType,
- boolean isSerializable,
- Class<?>[] markerInterfaces,
- MethodType[] additionalBridges)
+ int flags,
+ Class<?>[] markerInterfaces)
throws ReflectiveOperationException, LambdaConversionException {
- super(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
- isSerializable, markerInterfaces, additionalBridges);
+ super(caller, invokedType, samMethod, implMethod, instantiatedMethodType, flags, markerInterfaces);
implMethodClassName = implDefiningClass.getName().replace('.', '/');
implMethodName = implInfo.getName();
implMethodDesc = implMethodType.toMethodDescriptorString();
@@ -152,8 +134,7 @@
* @return a CallSite, which, when invoked, will return an instance of the
* functional interface
* @throws ReflectiveOperationException
- * @throws LambdaConversionException If properly formed functional interface
- * is not found
+ * @throws LambdaConversionException If properly formed functional interface is not found
*/
@Override
CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
@@ -193,16 +174,8 @@
* Generate a class file which implements the functional
* interface, define and return the class.
*
- * @implNote The class that is generated does not include signature
- * information for exceptions that may be present on the SAM method.
- * This is to reduce classfile size, and is harmless as checked exceptions
- * are erased anyway, no one will ever compile against this classfile,
- * and we make no guarantees about the reflective properties of lambda
- * objects.
- *
* @return a Class which implements the functional interface
- * @throws LambdaConversionException If properly formed functional interface
- * is not found
+ * @throws LambdaConversionException If properly formed functional interface is not found
*/
private Class<?> spinInnerClass() throws LambdaConversionException {
String samName = samBase.getName().replace('.', '/');
@@ -224,22 +197,28 @@
generateConstructor();
+ MethodAnalyzer ma = new MethodAnalyzer();
+
// Forward the SAM method
- String methodDescriptor = samMethodType.toMethodDescriptorString();
- MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samInfo.getName(), methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ if (ma.getSamMethod() == null) {
+ throw new LambdaConversionException(String.format("Functional interface method not found: %s", samMethodType));
+ } else {
+ generateForwardingMethod(ma.getSamMethod(), false);
+ }
// Forward the bridges
- if (additionalBridges != null) {
- for (MethodType mt : additionalBridges) {
- methodDescriptor = mt.toMethodDescriptorString();
- mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samInfo.getName(), methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ // @@@ The commented-out code is temporary, pending the VM's ability to bridge all methods on request
+ // @@@ Once the VM can do fail-over, uncomment the !ma.wasDefaultMethodFound() test, and emit the appropriate
+ // @@@ classfile attribute to request custom bridging. See 8002092.
+ if (!ma.getMethodsToBridge().isEmpty() /* && !ma.conflictFoundBetweenDefaultAndBridge() */ ) {
+ for (Method m : ma.getMethodsToBridge()) {
+ generateForwardingMethod(m, true);
}
}
- if (isSerializable)
+ if (isSerializable) {
generateWriteReplace();
+ }
cw.visitEnd();
@@ -268,8 +247,8 @@
}
);
- return UNSAFE.defineClass(lambdaClassName, classBytes, 0, classBytes.length,
- loader, pd);
+ return (Class<?>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length,
+ loader, pd);
}
/**
@@ -286,8 +265,7 @@
ctor.visitVarInsn(ALOAD, 0);
ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1);
lvIndex += argTypes[i].getSize();
- ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
+ ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
}
ctor.visitInsn(RETURN);
ctor.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
@@ -305,7 +283,7 @@
mv.visitCode();
mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
- mv.visitInsn(DUP);
+ mv.visitInsn(DUP);;
mv.visitLdcInsn(Type.getType(targetClass));
mv.visitLdcInsn(samInfo.getReferenceKind());
mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
@@ -335,6 +313,24 @@
}
/**
+ * Generate a method which calls the lambda implementation method,
+ * converting arguments, as needed.
+ * @param m The method whose signature should be generated
+ * @param isBridge True if this methods should be flagged as a bridge
+ */
+ private void generateForwardingMethod(Method m, boolean isBridge) {
+ Class<?>[] exceptionTypes = m.getExceptionTypes();
+ String[] exceptionNames = new String[exceptionTypes.length];
+ for (int i = 0; i < exceptionTypes.length; i++) {
+ exceptionNames[i] = exceptionTypes[i].getName().replace('.', '/');
+ }
+ String methodDescriptor = Type.getMethodDescriptor(m);
+ int access = isBridge? ACC_PUBLIC | ACC_BRIDGE : ACC_PUBLIC;
+ MethodVisitor mv = cw.visitMethod(access, m.getName(), methodDescriptor, null, exceptionNames);
+ new ForwardingMethodGenerator(mv).generate(m);
+ }
+
+ /**
* This class generates a method body which calls the lambda implementation
* method, converting arguments, as needed.
*/
@@ -344,26 +340,26 @@
super(mv);
}
- void generate(String methodDescriptor) {
+ void generate(Method m) throws InternalError {
visitCode();
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
visitTypeInsn(NEW, implMethodClassName);
- visitInsn(DUP);
+ visitInsn(DUP);;
}
for (int i = 0; i < argTypes.length; i++) {
visitVarInsn(ALOAD, 0);
visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
}
- convertArgumentTypes(Type.getArgumentTypes(methodDescriptor));
+ convertArgumentTypes(Type.getArgumentTypes(m));
// Invoke the method we want to forward to
visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc);
// Convert the return value (if any) and return it
// Note: if adapting from non-void to void, the 'return' instruction will pop the unneeded result
- Type samReturnType = Type.getReturnType(methodDescriptor);
+ Type samReturnType = Type.getReturnType(m);
convertType(implMethodReturnType, samReturnType, samReturnType);
visitInsn(samReturnType.getOpcode(Opcodes.IRETURN));
--- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Tue Jun 18 21:08:48 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Wed Jun 19 11:47:14 2013 +0100
@@ -25,9 +25,6 @@
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>
*
@@ -47,11 +44,16 @@
*
* <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
+ * <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>(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
@@ -142,59 +144,38 @@
*/
public class LambdaMetafactory {
- /** Flag for alternate metafactories indicating the lambda object is
- * must to be serializable */
+ /** 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
+ * 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.
+/**
+ * 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.
+ * @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
+ * @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
+ * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public static CallSite metaFactory(MethodHandles.Lookup caller,
String invokedName,
@@ -204,17 +185,15 @@
MethodType instantiatedMethodType)
throws ReflectiveOperationException, LambdaConversionException {
AbstractValidatingLambdaMetafactory mf;
- mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod,
- implMethod, instantiatedMethodType,
- false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
+ 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.
+ * 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:
*
@@ -234,28 +213,21 @@
* 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
+ * @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
+ * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public static CallSite altMetaFactory(MethodHandles.Lookup caller,
String invokedName,
@@ -267,7 +239,6 @@
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++];
@@ -277,30 +248,9 @@
}
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);
+ AbstractValidatingLambdaMetafactory mf;
+ mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
+ flags, markerInterfaces);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}