8017044: anti-delta fix for 8015402
authorchegar
Wed, 19 Jun 2013 11:47:14 +0100
changeset 18284 e281a0a2583e
parent 18282 61693b1882bf
child 18285 dc840ac75e93
child 18288 6dccb2fa29d2
8017044: anti-delta fix for 8015402 Reviewed-by: alanb
jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java
--- 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&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>(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();
     }