# HG changeset patch # User briangoetz # Date 1382634365 14400 # Node ID 2c2f062cf52fe81669a8e95d80449904f7a33592 # Parent 2d32ce9ea2b42016c1cd9234eb653cd6ed4142e9 8019646: Clarify javadoc contract of LambdaMetafactory Reviewed-by: briangoetz, rfield Contributed-by: dan.smith@oracle.com diff -r 2d32ce9ea2b4 -r 2c2f062cf52f jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java --- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Thu Oct 24 10:13:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Thu Oct 24 13:06:05 2013 -0400 @@ -101,7 +101,6 @@ * 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 */ @@ -114,7 +113,7 @@ boolean isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) - throws ReflectiveOperationException, LambdaConversionException { + throws LambdaConversionException { this.targetClass = caller.lookupClass(); this.invokedType = invokedType; @@ -160,7 +159,7 @@ * @throws ReflectiveOperationException */ abstract CallSite buildCallSite() - throws ReflectiveOperationException, LambdaConversionException; + throws LambdaConversionException; /** * Check the meta-factory arguments for errors diff -r 2d32ce9ea2b4 -r 2c2f062cf52f jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java --- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Oct 24 10:13:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Oct 24 13:06:05 2013 -0400 @@ -128,7 +128,6 @@ * 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 */ @@ -141,7 +140,7 @@ boolean isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) - throws ReflectiveOperationException, LambdaConversionException { + throws LambdaConversionException { super(caller, invokedType, samMethodName, samMethodType, implMethod, instantiatedMethodType, isSerializable, markerInterfaces, additionalBridges); @@ -179,7 +178,7 @@ * is not found */ @Override - CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { + CallSite buildCallSite() throws LambdaConversionException { final Class innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0) { final Constructor[] ctrs = AccessController.doPrivileged( @@ -190,7 +189,7 @@ } }); if (ctrs.length != 1) { - throw new ReflectiveOperationException("Expected one lambda constructor for " + throw new LambdaConversionException("Expected one lambda constructor for " + innerClass.getCanonicalName() + ", got " + ctrs.length); } // The lambda implementing inner class constructor is private, set @@ -202,13 +201,23 @@ return null; } }); - Object inst = ctrs[0].newInstance(); - return new ConstantCallSite(MethodHandles.constant(samBase, inst)); + try { + Object inst = ctrs[0].newInstance(); + return new ConstantCallSite(MethodHandles.constant(samBase, inst)); + } + catch (ReflectiveOperationException e) { + throw new LambdaConversionException("Exception instantiating lambda object", e); + } } else { - return new ConstantCallSite( - MethodHandles.Lookup.IMPL_LOOKUP - .findConstructor(innerClass, constructorType) - .asType(constructorType.changeReturnType(samBase))); + try { + return new ConstantCallSite( + MethodHandles.Lookup.IMPL_LOOKUP + .findConstructor(innerClass, constructorType) + .asType(constructorType.changeReturnType(samBase))); + } + catch (ReflectiveOperationException e) { + throw new LambdaConversionException("Exception finding constructor", e); + } } } diff -r 2d32ce9ea2b4 -r 2c2f062cf52f jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java --- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Thu Oct 24 10:13:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Thu Oct 24 13:06:05 2013 -0400 @@ -29,88 +29,128 @@ import java.util.Arrays; /** - *

Bootstrap methods for converting lambda expressions and method references to functional interface objects.

- * - *

For every lambda expressions or method reference in the source code, there is a target type which is a - * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for - * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole - * method of the functional interface and the implementation method, and returns an object (the lambda object) that - * implements the target type. Methods of the lambda object invoke the implementation method. For method - * references, the implementation method is simply the referenced method; for lambda expressions, the - * implementation method is produced by the compiler based on the body of the lambda expression. The methods in - * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the - * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories. - * - *

The bootstrap methods in this class take the information about the functional interface, the implementation - * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, - * produces the lambda object. - * - *

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 { int m(T x); }} if this functional interface type is used in a lambda - * {@code I; 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 - * instantiated method type), which has signature - * {@code (Byte)int}. + *

Methods to facilitate the creation of simple "function objects" that + * implement one or more interfaces by delegation to a provided {@link MethodHandle}, + * possibly after type adaptation and partial evaluation of arguments. These + * methods are typically used as bootstrap methods for {@code invokedynamic} + * call sites, to support the lambda expression and method + * reference expression features of the Java Programming Language. * - *

The argument list of the implementation method and the argument list of the functional interface method(s) - * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments - * captured by the lambda expression; there may also be differences resulting from permitted adaptations of - * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args, - * but this is expected to be handled by the compiler. - * - *

Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list. The - * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at - * invocation time. The bootstrap method has access to the entire static argument list (which in this case, - * contains method handles describing the implementation method and the canonical functional interface method), - * as well as a method signature describing the number and static types (but not the values) of the dynamic - * arguments, and the static return type of the invokedynamic site. + *

Indirect access to the behavior specified by the provided {@code MethodHandle} + * proceeds in order through three phases: + *