diff -r faedb20bdcbb -r 16c1792b2ee6 jdk/src/share/classes/java/dyn/MethodHandle.java --- a/jdk/src/share/classes/java/dyn/MethodHandle.java Thu Jun 17 16:28:11 2010 -0700 +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java Fri Jun 18 15:23:57 2010 -0700 @@ -34,32 +34,34 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility /** - * A method handle is a typed reference to the entry point of a method. + * A method handle is a typed, directly executable reference to a method, + * constructor, field, or similar low-level operation, with optional + * conversion or substitution of arguments or return values. *
* Method handles are strongly typed according to signature. * They are not distinguished by method name or enclosing class. * A method handle must be invoked under a signature which exactly matches - * the method handle's own type. + * the method handle's own {@link MethodType method type}. *
- * Every method handle confesses its type via the type
accessor.
+ * Every method handle confesses its type via the {@code type} accessor.
* The structure of this type is a series of classes, one of which is
- * the return type of the method (or void.class
if none).
+ * the return type of the method (or {@code void.class} if none).
*
* Every method handle appears as an object containing a method named
- * invoke
, whose signature exactly matches
+ * {@code invoke}, whose signature exactly matches
* the method handle's type.
* A Java method call expression, which compiles to an
- * invokevirtual
instruction,
+ * {@code invokevirtual} instruction,
* can invoke this method from Java source code.
*
* Every call to a method handle specifies an intended method type,
* which must exactly match the type of the method handle.
- * (The type is specified in the invokevirtual
instruction,
+ * (The type is specified in the {@code invokevirtual} instruction,
* via a {@code CONSTANT_NameAndType} constant pool entry.)
* The call looks within the receiver object for a method
- * named invoke
of the intended method type.
+ * named {@code invoke} of the intended method type.
* The call fails with a {@link WrongMethodTypeException}
- * if the method does not exist, even if there is an invoke
+ * if the method does not exist, even if there is an {@code invoke}
* method of a closely similar signature.
* As with other kinds
* of methods in the JVM, signature matching during method linkage
@@ -76,13 +78,13 @@
* They should not be passed to untrusted code.
*
* Bytecode in an extended JVM can directly call a method handle's
- * invoke
from an invokevirtual
instruction.
- * The receiver class type must be MethodHandle
and the method name
- * must be invoke
. The signature of the invocation
+ * {@code invoke} from an {@code invokevirtual} instruction.
+ * The receiver class type must be {@code MethodHandle} and the method name
+ * must be {@code invoke}. The signature of the invocation
* (after resolving symbolic type names) must exactly match the method type
* of the target method.
*
- * Every invoke
method always throws {@link Exception},
+ * Every {@code invoke} method always throws {@link Exception},
* which is to say that there is no static restriction on what a method handle
* can throw. Since the JVM does not distinguish between checked
* and unchecked exceptions (other than by their class, of course),
@@ -92,11 +94,11 @@
* throw {@code Exception}, or else must catch all checked exceptions locally.
*
* Bytecode in an extended JVM can directly obtain a method handle
- * for any accessible method from a ldc
instruction
- * which refers to a CONSTANT_Methodref
or
- * CONSTANT_InterfaceMethodref
constant pool entry.
+ * for any accessible method from a {@code ldc} instruction
+ * which refers to a {@code CONSTANT_Methodref} or
+ * {@code CONSTANT_InterfaceMethodref} constant pool entry.
*
- * All JVMs can also use a reflective API called MethodHandles
+ * All JVMs can also use a reflective API called {@code MethodHandles}
* for creating and calling method handles.
*
* A method reference may refer either to a static or non-static method.
@@ -104,7 +106,7 @@
* receiver argument, prepended before any other arguments.
* In the method handle's type, the initial receiver argument is typed
* according to the class under which the method was initially requested.
- * (E.g., if a non-static method handle is obtained via ldc
,
+ * (E.g., if a non-static method handle is obtained via {@code ldc},
* the type of the receiver is the class named in the constant pool entry.)
*
* When a method handle to a virtual method is invoked, the method is
@@ -113,38 +115,38 @@
* A non-virtual method handles to a specific virtual method implementation
* can also be created. These do not perform virtual lookup based on
* receiver type. Such a method handle simulates the effect of
- * an invokespecial
instruction to the same method.
+ * an {@code invokespecial} instruction to the same method.
*
* Here are some examples of usage: *
* Each of the above calls generates a single invokevirtual instruction * with the name {@code invoke} and the type descriptors indicated in the comments. @@ -167,6 +169,14 @@ * those of multiple arities. It is impossible to represent such * genericity with a Java type parameter. * + * Signature polymorphic methods in this class appear to be documented + * as having type parameters for return types and a parameter, but that is + * merely a documentation convention. These type parameters do + * not play a role in type-checking method handle invocations. + *- * Object x, y; String s; int i; - * MethodType mt; MethodHandle mh; - * MethodHandles.Lookup lookup = MethodHandles.lookup(); - * // mt is {(char,char) => String} - * mt = MethodType.make(String.class, char.class, char.class); - * mh = lookup.findVirtual(String.class, "replace", mt); - * // (Ljava/lang/String;CC)Ljava/lang/String; - * s = mh.<String>invoke("daddy",'d','n'); - * assert(s.equals("nanny")); - * // weakly typed invocation (using MHs.invoke) - * s = (String) MethodHandles.invoke(mh, "sappy", 'p', 'v'); - * assert(s.equals("savvy")); - * // mt is {Object[] => List} - * mt = MethodType.make(java.util.List.class, Object[].class); - * mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); - * // mt is {(Object,Object,Object) => Object} - * mt = MethodType.makeGeneric(3); - * mh = MethodHandles.collectArguments(mh, mt); - * // mt is {(Object,Object,Object) => Object} - * // (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - * x = mh.invoke((Object)1, (Object)2, (Object)3); - * assert(x.equals(java.util.Arrays.asList(1,2,3))); - * // mt is { => int} - * mt = MethodType.make(int.class); - * mh = lookup.findVirtual(java.util.List.class, "size", mt); - * // (Ljava/util/List;)I - * i = mh.<int>invoke(java.util.Arrays.asList(1,2,3)); - * assert(i == 3); +Object x, y; String s; int i; +MethodType mt; MethodHandle mh; +MethodHandles.Lookup lookup = MethodHandles.lookup(); +// mt is {(char,char) => String} +mt = MethodType.methodType(String.class, char.class, char.class); +mh = lookup.findVirtual(String.class, "replace", mt); +// (Ljava/lang/String;CC)Ljava/lang/String; +s = mh.<String>invokeExact("daddy",'d','n'); +assert(s.equals("nanny")); +// weakly typed invocation (using MHs.invoke) +s = (String) mh.invokeVarargs("sappy", 'p', 'v'); +assert(s.equals("savvy")); +// mt is {Object[] => List} +mt = MethodType.methodType(java.util.List.class, Object[].class); +mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); +// mt is {(Object,Object,Object) => Object} +mt = MethodType.genericMethodType(3); +mh = MethodHandles.collectArguments(mh, mt); +// mt is {(Object,Object,Object) => Object} +// (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +x = mh.invokeExact((Object)1, (Object)2, (Object)3); +assert(x.equals(java.util.Arrays.asList(1,2,3))); +// mt is { => int} +mt = MethodType.methodType(int.class); +mh = lookup.findVirtual(java.util.List.class, "size", mt); +// (Ljava/util/List;)I +i = mh.<int>invokeExact(java.util.Arrays.asList(1,2,3)); +assert(i == 3); *
+ * Note: Like classes and strings, method handles that correspond directly
+ * to fields and methods can be represented directly as constants to be
+ * loaded by {@code ldc} bytecodes.
*
* @see MethodType
* @see MethodHandles
@@ -180,7 +190,15 @@
private static Access IMPL_TOKEN = Access.getToken();
// interface MethodHandle
* @param arguments the arguments to pass to the target
* @return the result returned by the target
* @see MethodHandles#genericInvoker
*/
- public final Object invokeVarargs(Object[] arguments) throws Throwable {
+ public final Object invokeVarargs(Object... arguments) throws Throwable {
int argc = arguments == null ? 0 : arguments.length;
MethodType type = type();
if (argc <= 10) {
MethodHandle invoker = MethodHandles.invokers(type).genericInvoker();
switch (argc) {
- case 0: return invoker.invoke(this);
- case 1: return invoker.invoke(this,
+ case 0: return invoker.invokeExact(this);
+ case 1: return invoker.invokeExact(this,
arguments[0]);
- case 2: return invoker.invoke(this,
+ case 2: return invoker.invokeExact(this,
arguments[0], arguments[1]);
- case 3: return invoker.invoke(this,
+ case 3: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2]);
- case 4: return invoker.invoke(this,
+ case 4: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3]);
- case 5: return invoker.invoke(this,
+ case 5: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4]);
- case 6: return invoker.invoke(this,
+ case 6: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5]);
- case 7: return invoker.invoke(this,
+ case 7: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6]);
- case 8: return invoker.invoke(this,
+ case 8: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7]);
- case 9: return invoker.invoke(this,
+ case 9: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8]);
- case 10: return invoker.invoke(this,
+ case 10: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8],
@@ -391,7 +362,7 @@
// more than ten arguments get boxed in a varargs list:
MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0);
- return invoker.invoke(this, arguments);
+ return invoker.invokeExact(this, arguments);
}
/** Equivalent to {@code invokeVarargs(arguments.toArray())}. */
public final Object invokeVarargs(java.util.List> arguments) throws Throwable {
* MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
- * Object result = invoker.invoke(this, arguments);
+ * Object result = invoker.invokeExact(this, arguments);
*