8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
authormcimadamore
Thu, 11 Jul 2013 14:02:20 +0100
changeset 18716 9723e722b955
parent 18715 487d977c44f7
child 18719 984f3e50463b
child 18753 495f4c384864
child 18831 3cac65e30d46
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle 8020010: Move lambda bridge creation from metafactory and VM to compiler Summary: JDK/metafactory component of the bridge fix and and MethodType vs. MethodHandle changes. Reviewed-by: twisti, briangoetz, forax Contributed-by: robert.field@oracle.com
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
jdk/src/share/classes/java/lang/invoke/SerializedLambda.java
--- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu Jul 11 10:13:49 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu Jul 11 14:02:20 2013 +0100
@@ -24,24 +24,23 @@
  */
 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.*;
+
+import static sun.invoke.util.Wrapper.forPrimitiveType;
+import static sun.invoke.util.Wrapper.forWrapperType;
+import static sun.invoke.util.Wrapper.isWrapperType;
 
 /**
- * Abstract implementation of a lambda metafactory which provides parameter unrolling and input validation.
+ * Abstract implementation of a lambda metafactory which provides parameter
+ * unrolling and input validation.
  *
  * @see LambdaMetafactory
  */
 /* package */ abstract class AbstractValidatingLambdaMetafactory {
 
     /*
-     * For context, the comments for the following fields are marked in quotes with their values, given this program:
+     * For context, the comments for the following fields are marked in quotes
+     * with their values, given this program:
      * interface II<T> {  Object foo(T x); }
      * interface JJ<R extends Number> extends II<R> { }
      * class CC {  String impl(int i) { return "impl:"+i; }}
@@ -54,9 +53,7 @@
     final Class<?> targetClass;               // The class calling the meta-factory via invokedynamic "class X"
     final MethodType invokedType;             // The type of the invoked method "(CC)II"
     final Class<?> samBase;                   // The type of the returned instance "interface JJ"
-    final MethodHandle samMethod;             // Raw method handle for the functional interface method
-    final MethodHandleInfo samInfo;           // Info about the SAM method handle "MethodHandleInfo[9 II.foo(Object)Object]"
-    final Class<?> samClass;                  // Interface containing the SAM method "interface II"
+    final String samMethodName;               // Name of the SAM method "foo"
     final MethodType samMethodType;           // Type of the SAM method "(Object)Object"
     final MethodHandle implMethod;            // Raw method handle for the implementation method
     final MethodHandleInfo implInfo;          // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]"
@@ -67,44 +64,64 @@
     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 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 samMethodName Name of the method in the functional interface to
+     *                      which the lambda or method reference is being
+     *                      converted, represented as a String.
+     * @param samMethodType Type of the method in the functional interface to
+     *                      which the lambda or method reference is being
+     *                      converted, represented as a MethodType.
+     * @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
      * @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,
+                                       String samMethodName,
+                                       MethodType samMethodType,
                                        MethodHandle implMethod,
                                        MethodType instantiatedMethodType,
-                                       int flags,
-                                       Class<?>[] markerInterfaces)
+                                       boolean isSerializable,
+                                       Class<?>[] markerInterfaces,
+                                       MethodType[] additionalBridges)
             throws ReflectiveOperationException, LambdaConversionException {
         this.targetClass = caller.lookupClass();
         this.invokedType = invokedType;
 
         this.samBase = invokedType.returnType();
 
-        this.samMethod = samMethod;
-        this.samInfo = new MethodHandleInfo(samMethod);
-        this.samClass = samInfo.getDeclaringClass();
-        this.samMethodType  = samInfo.getMethodType();
+        this.samMethodName = samMethodName;
+        this.samMethodType  = samMethodType;
 
         this.implMethod = implMethod;
         this.implInfo = new MethodHandleInfo(implMethod);
@@ -118,32 +135,24 @@
                 implKind == MethodHandleInfo.REF_invokeInterface;
         this.implDefiningClass = implInfo.getDeclaringClass();
         this.implMethodType = implInfo.getMethodType();
+        this.instantiatedMethodType = instantiatedMethodType;
+        this.isSerializable = isSerializable;
+        this.markerInterfaces = markerInterfaces;
+        this.additionalBridges = additionalBridges;
 
-        this.instantiatedMethodType = instantiatedMethodType;
-
-        if (!samClass.isInterface()) {
+        if (!samBase.isInterface()) {
             throw new LambdaConversionException(String.format(
                     "Functional interface %s is not an interface",
-                    samClass.getName()));
+                    samBase.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()));
             }
-            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;
     }
 
     /**
@@ -153,20 +162,14 @@
      * functional interface
      * @throws ReflectiveOperationException
      */
-    abstract CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException;
+    abstract CallSite buildCallSite()
+            throws ReflectiveOperationException, LambdaConversionException;
 
     /**
      * Check the meta-factory arguments for errors
      * @throws LambdaConversionException if there are improper conversions
      */
     void validateMetafactoryArgs() throws LambdaConversionException {
-        // Check target type is a subtype of class where SAM method is defined
-        if (!samClass.isAssignableFrom(samBase)) {
-            throw new LambdaConversionException(
-                    String.format("Invalid target type %s for lambda conversion; not a subtype of functional interface %s",
-                                  samBase.getName(), samClass.getName()));
-        }
-
         switch (implKind) {
             case MethodHandleInfo.REF_invokeInterface:
             case MethodHandleInfo.REF_invokeVirtual:
@@ -265,9 +268,9 @@
      }
 
     /**
-     * Check type adaptability
-     * @param fromType
-     * @param toType
+     * Check type adaptability for parameter types.
+     * @param fromType Type to convert from
+     * @param toType Type to convert to
      * @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'
      */
@@ -299,15 +302,14 @@
                 }
             } else {
                 // both are reference types: fromType should be a superclass of toType.
-                return strict? toType.isAssignableFrom(fromType) : true;
+                return !strict || toType.isAssignableFrom(fromType);
             }
         }
     }
 
     /**
-     * Check type adaptability for return types -- special handling of void type) and parameterized fromType
-     * @param fromType
-     * @param toType
+     * Check type adaptability for return types --
+     * special handling of void type) and parameterized fromType
      * @return True if 'fromType' can be converted to 'toType'
      */
     private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
@@ -338,89 +340,4 @@
     }
     ***********************/
 
-    /**
-     * 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	Thu Jul 11 10:13:49 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Jul 11 14:02:20 2013 +0100
@@ -25,22 +25,26 @@
 
 package java.lang.invoke;
 
+import jdk.internal.org.objectweb.asm.*;
+import sun.misc.Unsafe;
+
 import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 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.security.AccessController;
-import java.security.PrivilegedAction;
 
 /**
- * Lambda metafactory implementation which dynamically creates an inner-class-like class per lambda callsite.
+ * Lambda metafactory implementation which dynamically creates an
+ * inner-class-like class per lambda callsite.
  *
  * @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";
@@ -54,7 +58,7 @@
     private static final String DESCR_CTOR_SERIALIZED_LAMBDA
             = MethodType.methodType(void.class,
                                     Class.class,
-                                    int.class, String.class, String.class, String.class,
+                                    String.class, String.class, String.class,
                                     int.class, String.class, String.class, String.class,
                                     String.class,
                                     Object[].class).toMethodDescriptorString();
@@ -77,36 +81,56 @@
     private final Type[] instantiatedArgumentTypes;  // ASM types for the functional interface arguments
 
     /**
-     * General meta-factory constructor, standard cases and allowing for uncommon options such as serialization.
+     * General meta-factory constructor, supporting both standard cases and
+     * allowing for uncommon options such as serialization or bridging.
      *
-     * @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.
+     * @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 samMethodName Name of the method in the functional interface to
+     *                      which the lambda or method reference is being
+     *                      converted, represented as a String.
+     * @param samMethodType Type of the method in the functional interface to
+     *                      which the lambda or method reference is being
+     *                      converted, represented as a MethodType.
+     * @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
      * @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,
+                                       String samMethodName,
+                                       MethodType samMethodType,
                                        MethodHandle implMethod,
                                        MethodType instantiatedMethodType,
-                                       int flags,
-                                       Class<?>[] markerInterfaces)
+                                       boolean isSerializable,
+                                       Class<?>[] markerInterfaces,
+                                       MethodType[] additionalBridges)
             throws ReflectiveOperationException, LambdaConversionException {
-        super(caller, invokedType, samMethod, implMethod, instantiatedMethodType, flags, markerInterfaces);
+        super(caller, invokedType, samMethodName, samMethodType,
+              implMethod, instantiatedMethodType,
+              isSerializable, markerInterfaces, additionalBridges);
         implMethodClassName = implDefiningClass.getName().replace('.', '/');
         implMethodName = implInfo.getName();
         implMethodDesc = implMethodType.toMethodDescriptorString();
@@ -124,7 +148,8 @@
         for (int i = 0; i < argTypes.length; i++) {
             argNames[i] = "arg$" + (i + 1);
         }
-        instantiatedArgumentTypes = Type.getArgumentTypes(instantiatedMethodType.toMethodDescriptorString());
+        instantiatedArgumentTypes = Type.getArgumentTypes(
+                instantiatedMethodType.toMethodDescriptorString());
     }
 
     /**
@@ -136,7 +161,8 @@
      * @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 {
@@ -167,8 +193,8 @@
         } else {
             return new ConstantCallSite(
                     MethodHandles.Lookup.IMPL_LOOKUP
-                                        .findConstructor(innerClass, constructorType)
-                                        .asType(constructorType.changeReturnType(samBase)));
+                         .findConstructor(innerClass, constructorType)
+                         .asType(constructorType.changeReturnType(samBase)));
         }
     }
 
@@ -176,13 +202,20 @@
      * 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('.', '/');
         String[] interfaces = new String[markerInterfaces.length + 1];
-        interfaces[0] = samName;
+        interfaces[0] = samBase.getName().replace('.', '/');
         for (int i=0; i<markerInterfaces.length; i++) {
             interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
         }
@@ -192,35 +225,33 @@
 
         // Generate final fields to be filled in by constructor
         for (int i = 0; i < argTypes.length; i++) {
-            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(),
+            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
+                                            argNames[i],
+                                            argTypes[i].getDescriptor(),
                                             null, null);
             fv.visitEnd();
         }
 
         generateConstructor();
 
-        MethodAnalyzer ma = new MethodAnalyzer();
-
         // Forward the SAM method
-        if (ma.getSamMethod() == null) {
-            throw new LambdaConversionException(String.format("Functional interface method not found: %s", samMethodType));
-        } else {
-            generateForwardingMethod(ma.getSamMethod(), false);
-        }
+        String methodDescriptor = samMethodType.toMethodDescriptorString();
+        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
+                                          methodDescriptor, null, null);
+        new ForwardingMethodGenerator(mv).generate(methodDescriptor);
 
         // Forward the bridges
-        // @@@ 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 (additionalBridges != null) {
+            for (MethodType mt : additionalBridges) {
+                methodDescriptor = mt.toMethodDescriptorString();
+                mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
+                                    methodDescriptor, null, null);
+                new ForwardingMethodGenerator(mv).generate(methodDescriptor);
             }
         }
 
-        if (isSerializable) {
+        if (isSerializable)
             generateWriteReplace();
-        }
 
         cw.visitEnd();
 
@@ -229,11 +260,14 @@
         final byte[] classBytes = cw.toByteArray();
 
         /*** Uncomment to dump the generated file
-            System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length);
-            try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) {
+            System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName,
+                              classBytes.length);
+            try (FileOutputStream fos = new FileOutputStream(lambdaClassName
+                                            .replace('/', '.') + ".class")) {
                 fos.write(classBytes);
             } catch (IOException ex) {
-                PlatformLogger.getLogger(InnerClassLambdaMetafactory.class.getName()).severe(ex.getMessage(), ex);
+                PlatformLogger.getLogger(InnerClassLambdaMetafactory.class
+                                      .getName()).severe(ex.getMessage(), ex);
             }
         ***/
 
@@ -249,8 +283,9 @@
             }
         );
 
-        return (Class<?>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length,
-                                                                   loader, pd);
+        return UNSAFE.defineClass(lambdaClassName,
+                                  classBytes, 0, classBytes.length,
+                                  loader, pd);
     }
 
     /**
@@ -258,19 +293,23 @@
      */
     private void generateConstructor() {
         // Generate constructor
-        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorDesc, null, null);
+        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
+                                            constructorDesc, null, null);
         ctor.visitCode();
         ctor.visitVarInsn(ALOAD, 0);
-        ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID);
+        ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR,
+                             METHOD_DESCRIPTOR_VOID);
         int lvIndex = 0;
         for (int i = 0; i < argTypes.length; i++) {
             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
+        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        ctor.visitMaxs(-1, -1);
         ctor.visitEnd();
     }
 
@@ -279,18 +318,18 @@
      */
     private void generateWriteReplace() {
         TypeConvertingMethodAdapter mv
-                = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
-                                                                 NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
-                                                                 null, null));
+                = new TypeConvertingMethodAdapter(
+                    cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
+                    NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
+                    null, null));
 
         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('.', '/'));
-        mv.visitLdcInsn(samInfo.getName());
-        mv.visitLdcInsn(samInfo.getMethodType().toMethodDescriptorString());
+        mv.visitLdcInsn(samMethodName);
+        mv.visitLdcInsn(samMethodType.toMethodDescriptorString());
         mv.visitLdcInsn(implInfo.getReferenceKind());
         mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
         mv.visitLdcInsn(implInfo.getName());
@@ -303,36 +342,20 @@
             mv.visitInsn(DUP);
             mv.iconst(i);
             mv.visitVarInsn(ALOAD, 0);
-            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
+            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
+                              argTypes[i].getDescriptor());
             mv.boxIfTypePrimitive(argTypes[i]);
             mv.visitInsn(AASTORE);
         }
         mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
                 DESCR_CTOR_SERIALIZED_LAMBDA);
         mv.visitInsn(ARETURN);
-        mv.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        mv.visitMaxs(-1, -1);
         mv.visitEnd();
     }
 
     /**
-     * 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.
      */
@@ -342,36 +365,39 @@
             super(mv);
         }
 
-        void generate(Method m) throws InternalError {
+        void generate(String methodDescriptor) {
             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());
+                visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
+                               argTypes[i].getDescriptor());
             }
 
-            convertArgumentTypes(Type.getArgumentTypes(m));
+            convertArgumentTypes(Type.getArgumentTypes(methodDescriptor));
 
             // 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(m);
+            // Note: if adapting from non-void to void, the 'return'
+            // instruction will pop the unneeded result
+            Type samReturnType = Type.getReturnType(methodDescriptor);
             convertType(implMethodReturnType, samReturnType, samReturnType);
             visitInsn(samReturnType.getOpcode(Opcodes.IRETURN));
-
-            visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+            // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
+            visitMaxs(-1, -1);
             visitEnd();
         }
 
         private void convertArgumentTypes(Type[] samArgumentTypes) {
             int lvIndex = 0;
-            boolean samIncludesReceiver = implIsInstanceMethod && argTypes.length == 0;
+            boolean samIncludesReceiver = implIsInstanceMethod &&
+                                                   argTypes.length == 0;
             int samReceiverLength = samIncludesReceiver ? 1 : 0;
             if (samIncludesReceiver) {
                 // push receiver
@@ -395,7 +421,9 @@
         }
 
         private void convertType(Type argType, Type targetType, Type functionalType) {
-            convertType(argType.getDescriptor(), targetType.getDescriptor(), functionalType.getDescriptor());
+            convertType(argType.getDescriptor(),
+                        targetType.getDescriptor(),
+                        functionalType.getDescriptor());
         }
 
         private int invocationOpcode() throws InternalError {
--- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Jul 11 10:13:49 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Jul 11 14:02:20 2013 +0100
@@ -25,6 +25,9 @@
 
 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>
  *
@@ -44,16 +47,11 @@
  *
  * <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
+ * {@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</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.
+ * {@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
@@ -137,108 +135,147 @@
  *     </tr>
  * </table>
  *
- * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol.
- * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization
+ * The default bootstrap ({@link #metafactory}) represents the common cases and uses an optimized protocol.
+ * Alternate bootstraps (e.g., {@link #altMetafactory}) exist to support uncommon cases such as serialization
  * or additional marker superinterfaces.
  *
  */
 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.
-     *                    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 if the caller is not able to reconstruct one of the method handles
-     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
+     * @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.
+     *                    Used as the name of the functional interface method
+     *                    to which the lambda or method reference is being
+     *                    converted.
+     * @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 samMethodType MethodType of the method in the functional interface
+     *                      to which the lambda or method reference is being
+     *                      converted, represented as a MethodType.
+     * @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 if the caller is not able to
+     * reconstruct one of the method handles
+     * @throws LambdaConversionException If any of the meta-factory protocol
+     * invariants are violated
      */
-    public static CallSite metaFactory(MethodHandles.Lookup caller,
+    public static CallSite metafactory(MethodHandles.Lookup caller,
                                        String invokedName,
                                        MethodType invokedType,
-                                       MethodHandle samMethod,
+                                       MethodType samMethodType,
                                        MethodHandle implMethod,
                                        MethodType instantiatedMethodType)
                    throws ReflectiveOperationException, LambdaConversionException {
         AbstractValidatingLambdaMetafactory mf;
-        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
-                0, EMPTY_CLASS_ARRAY);
+        mf = new InnerClassLambdaMetafactory(caller, invokedType,
+                                             invokedName, samMethodType,
+                                             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.
+     * 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,
+     *  CallSite altMetafactory(MethodHandles.Lookup caller,
      *                          String invokedName,
      *                          MethodType invokedType,
      *                          Object... args)
      *
      * but it behaves as if the argument list is:
      *
-     *  CallSite altMetaFactory(MethodHandles.Lookup caller,
+     *  CallSite altMetafactory(MethodHandles.Lookup caller,
      *                          String invokedName,
      *                          MethodType invokedType,
-     *                          MethodHandle samMethod
+     *                          MethodType samMethodType
      *                          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 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 if the caller is not able to reconstruct one of the method handles
-     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
+     * @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.
+     *                    Used as the name of the functional interface method
+     *                    to which the lambda or method reference is being
+     *                    converted.
+     * @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 if the caller is not able to
+     * reconstruct one of the method handles
+     * @throws LambdaConversionException If any of the meta-factory protocol
+     * invariants are violated
      */
-    public static CallSite altMetaFactory(MethodHandles.Lookup caller,
+    public static CallSite altMetafactory(MethodHandles.Lookup caller,
                                           String invokedName,
                                           MethodType invokedType,
                                           Object... args)
             throws ReflectiveOperationException, LambdaConversionException {
-        MethodHandle samMethod = (MethodHandle)args[0];
+        MethodType samMethodType = (MethodType)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++];
@@ -248,9 +285,33 @@
         }
         else
             markerInterfaces = EMPTY_CLASS_ARRAY;
-        AbstractValidatingLambdaMetafactory mf;
-        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
-                                             flags, markerInterfaces);
+        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,
+                                                  invokedName, samMethodType,
+                                                  implMethod,
+                                                  instantiatedMethodType,
+                                                  isSerializable,
+                                                  markerInterfaces, bridges);
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
--- a/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java	Thu Jul 11 10:13:49 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java	Thu Jul 11 14:02:20 2013 +0100
@@ -44,7 +44,6 @@
     private final String functionalInterfaceClass;
     private final String functionalInterfaceMethodName;
     private final String functionalInterfaceMethodSignature;
-    private final int functionalInterfaceMethodKind;
     private final String implClass;
     private final String implMethodName;
     private final String implMethodSignature;
@@ -53,28 +52,32 @@
     private final Object[] capturedArgs;
 
     /**
-     * Create a {@code SerializedLambda} from the low-level information present at the lambda factory site.
+     * Create a {@code SerializedLambda} from the low-level information present
+     * at the lambda factory site.
      *
      * @param capturingClass The class in which the lambda expression appears
-     * @param functionalInterfaceMethodKind Method handle kind (see {@link MethodHandleInfo}) for the
-     *                                      functional interface method handle present at the lambda factory site
-     * @param functionalInterfaceClass Name, in slash-delimited form, for the functional interface class present at the
-     *                                 lambda factory site
-     * @param functionalInterfaceMethodName Name of the primary method for the functional interface present at the
+     * @param functionalInterfaceClass Name, in slash-delimited form, of static
+     *                                 type of the returned lambda object
+     * @param functionalInterfaceMethodName Name of the functional interface
+     *                                      method for the present at the
      *                                      lambda factory site
-     * @param functionalInterfaceMethodSignature Signature of the primary method for the functional interface present
-     *                                           at the lambda factory site
+     * @param functionalInterfaceMethodSignature Signature of the functional
+     *                                           interface method present at
+     *                                           the lambda factory site
      * @param implMethodKind Method handle kind for the implementation method
-     * @param implClass Name, in slash-delimited form, for the class holding the implementation method
+     * @param implClass Name, in slash-delimited form, for the class holding
+     *                  the implementation method
      * @param implMethodName Name of the implementation method
      * @param implMethodSignature Signature of the implementation method
-     * @param instantiatedMethodType The signature of the primary functional interface method after type variables
-     *                               are substituted with their instantiation from the capture site
-     * @param capturedArgs The dynamic arguments to the lambda factory site, which represent variables captured by
+     * @param instantiatedMethodType The signature of the primary functional
+     *                               interface method after type variables
+     *                               are substituted with their instantiation
+     *                               from the capture site
+     * @param capturedArgs The dynamic arguments to the lambda factory site,
+     *                     which represent variables captured by
      *                     the lambda
      */
     public SerializedLambda(Class<?> capturingClass,
-                            int functionalInterfaceMethodKind,
                             String functionalInterfaceClass,
                             String functionalInterfaceMethodName,
                             String functionalInterfaceMethodSignature,
@@ -85,7 +88,6 @@
                             String instantiatedMethodType,
                             Object[] capturedArgs) {
         this.capturingClass = capturingClass;
-        this.functionalInterfaceMethodKind = functionalInterfaceMethodKind;
         this.functionalInterfaceClass = functionalInterfaceClass;
         this.functionalInterfaceMethodName = functionalInterfaceMethodName;
         this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature;
@@ -106,10 +108,10 @@
     }
 
     /**
-     * Get the name of the functional interface class to which this
+     * Get the name of the invoked type to which this
      * lambda has been converted
-     * @return the name of the functional interface this lambda has
-     * been converted to
+     * @return the name of the functional interface class to which
+     * this lambda has been converted
      */
     public String getFunctionalInterfaceClass() {
         return functionalInterfaceClass;
@@ -135,17 +137,6 @@
     }
 
     /**
-     * Get the method handle kind (see {@link MethodHandleInfo}) of
-     * the primary method for the functional interface to which this
-     * lambda has been converted
-     * @return the method handle kind of the primary method of
-     * functional interface
-     */
-    public int getFunctionalInterfaceMethodKind() {
-        return functionalInterfaceMethodKind;
-    }
-
-    /**
      * Get the name of the class containing the implementation
      * method.
      * @return the name of the class containing the implementation
@@ -234,11 +225,17 @@
 
     @Override
     public String toString() {
-        return String.format("SerializedLambda[capturingClass=%s, functionalInterfaceMethod=%s %s.%s:%s, " +
-                             "implementation=%s %s.%s:%s, instantiatedMethodType=%s, numCaptured=%d]",
-                             capturingClass, MethodHandleInfo.getReferenceKindString(functionalInterfaceMethodKind),
-                             functionalInterfaceClass, functionalInterfaceMethodName, functionalInterfaceMethodSignature,
-                             MethodHandleInfo.getReferenceKindString(implMethodKind), implClass, implMethodName,
-                             implMethodSignature, instantiatedMethodType, capturedArgs.length);
+        String implKind=MethodHandleInfo.getReferenceKindString(implMethodKind);
+        return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " +
+                             "%s=%s %s.%s:%s, %s=%s, %s=%d]",
+                             "capturingClass", capturingClass,
+                             "functionalInterfaceMethod", functionalInterfaceClass,
+                               functionalInterfaceMethodName,
+                               functionalInterfaceMethodSignature,
+                             "implementation",
+                               implKind,
+                               implClass, implMethodName, implMethodSignature,
+                             "instantiatedMethodType", instantiatedMethodType,
+                             "numCaptured", capturedArgs.length);
     }
 }