提交 e069207a 编写于 作者: J jrose

8024438: JSR 292 API specification maintenance for JDK 8

Summary: add wildcard to unreflectConstructor, various clarifications and minor edits
Reviewed-by: mchung, darcy, twisti
上级 6a4b3466
...@@ -529,18 +529,18 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -529,18 +529,18 @@ import jdk.internal.org.objectweb.asm.Type;
* A concrete BMH species adheres to the following schema: * A concrete BMH species adheres to the following schema:
* *
* <pre> * <pre>
* class Species_<<types>> extends BoundMethodHandle { * class Species_[[types]] extends BoundMethodHandle {
* <<fields>> * [[fields]]
* final SpeciesData speciesData() { return SpeciesData.get("<<types>>"); } * final SpeciesData speciesData() { return SpeciesData.get("[[types]]"); }
* } * }
* </pre> * </pre>
* *
* The {@code <<types>>} signature is precisely the string that is passed to this * The {@code [[types]]} signature is precisely the string that is passed to this
* method. * method.
* *
* The {@code <<fields>>} section consists of one field definition per character in * The {@code [[fields]]} section consists of one field definition per character in
* the type signature, adhering to the naming schema described in the definition of * the type signature, adhering to the naming schema described in the definition of
* {@link #makeFieldName()}. * {@link #makeFieldName}.
* *
* For example, a concrete BMH species for two reference and one integral bound values * For example, a concrete BMH species for two reference and one integral bound values
* would have the following shape: * would have the following shape:
...@@ -822,7 +822,7 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -822,7 +822,7 @@ import jdk.internal.org.objectweb.asm.Type;
* {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through
* {@link MethodHandle#linkToSpecial}. * {@link MethodHandle#linkToSpecial}.
* *
* The last {@link LambdaForm#Name Name} in the argument's form is expected to be the {@code void} * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void}
* result of the {@code <init>} invocation. This entry is replaced. * result of the {@code <init>} invocation. This entry is replaced.
*/ */
private static MethodHandle linkConstructor(MethodHandle cmh) { private static MethodHandle linkConstructor(MethodHandle cmh) {
......
...@@ -60,7 +60,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -60,7 +60,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
* <p> * <p>
* Here is a sample use of call sites and bootstrap methods which links every * Here is a sample use of call sites and bootstrap methods which links every
* dynamic call site to print its arguments: * dynamic call site to print its arguments:
<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java --> <blockquote><pre>{@code
static void test() throws Throwable { static void test() throws Throwable {
// THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14); InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
...@@ -79,7 +79,7 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam ...@@ -79,7 +79,7 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam
// ignore caller and name, but match the type: // ignore caller and name, but match the type:
return new ConstantCallSite(printArgs.asType(type)); return new ConstantCallSite(printArgs.asType(type));
} }
</pre></blockquote> }</pre></blockquote>
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
abstract abstract
...@@ -199,12 +199,12 @@ public class CallSite { ...@@ -199,12 +199,12 @@ public class CallSite {
* which has been linked to this call site. * which has been linked to this call site.
* <p> * <p>
* This method is equivalent to the following code: * This method is equivalent to the following code:
* <blockquote><pre> * <blockquote><pre>{@code
* MethodHandle getTarget, invoker, result; * MethodHandle getTarget, invoker, result;
* getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
* invoker = MethodHandles.exactInvoker(this.type()); * invoker = MethodHandles.exactInvoker(this.type());
* result = MethodHandles.foldArguments(invoker, getTarget) * result = MethodHandles.foldArguments(invoker, getTarget)
* </pre></blockquote> * }</pre></blockquote>
* *
* @return a method handle which always invokes this call site's current target * @return a method handle which always invokes this call site's current target
*/ */
......
...@@ -242,9 +242,6 @@ class InvokerBytecodeGenerator { ...@@ -242,9 +242,6 @@ class InvokerBytecodeGenerator {
/** /**
* Extract the MemberName of a newly-defined method. * Extract the MemberName of a newly-defined method.
*
* @param classFile
* @return
*/ */
private MemberName loadMethod(byte[] classFile) { private MemberName loadMethod(byte[] classFile) {
Class<?> invokerClass = loadAndInitializeInvokerClass(classFile, cpPatches(classFile)); Class<?> invokerClass = loadAndInitializeInvokerClass(classFile, cpPatches(classFile));
...@@ -253,10 +250,6 @@ class InvokerBytecodeGenerator { ...@@ -253,10 +250,6 @@ class InvokerBytecodeGenerator {
/** /**
* Define a given class as anonymous class in the runtime system. * Define a given class as anonymous class in the runtime system.
*
* @param classBytes
* @param patches
* @return
*/ */
private static Class<?> loadAndInitializeInvokerClass(byte[] classBytes, Object[] patches) { private static Class<?> loadAndInitializeInvokerClass(byte[] classBytes, Object[] patches) {
Class<?> invokerClass = UNSAFE.defineAnonymousClass(HOST_CLASS, classBytes, patches); Class<?> invokerClass = UNSAFE.defineAnonymousClass(HOST_CLASS, classBytes, patches);
...@@ -264,14 +257,6 @@ class InvokerBytecodeGenerator { ...@@ -264,14 +257,6 @@ class InvokerBytecodeGenerator {
return invokerClass; return invokerClass;
} }
/**
* TODO
*
* @param invokerClass
* @param name
* @param type
* @return
*/
private static MemberName resolveInvokerMember(Class<?> invokerClass, String name, MethodType type) { private static MemberName resolveInvokerMember(Class<?> invokerClass, String name, MethodType type) {
MemberName member = new MemberName(invokerClass, name, type, REF_invokeStatic); MemberName member = new MemberName(invokerClass, name, type, REF_invokeStatic);
//System.out.println("resolveInvokerMember => "+member); //System.out.println("resolveInvokerMember => "+member);
...@@ -499,10 +484,6 @@ class InvokerBytecodeGenerator { ...@@ -499,10 +484,6 @@ class InvokerBytecodeGenerator {
/** /**
* Generate customized bytecode for a given LambdaForm. * Generate customized bytecode for a given LambdaForm.
*
* @param form
* @param invokerType
* @return
*/ */
static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) { static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
...@@ -565,8 +546,6 @@ class InvokerBytecodeGenerator { ...@@ -565,8 +546,6 @@ class InvokerBytecodeGenerator {
/** /**
* Emit an invoke for the given name. * Emit an invoke for the given name.
*
* @param name
*/ */
void emitInvoke(Name name) { void emitInvoke(Name name) {
if (true) { if (true) {
...@@ -645,8 +624,6 @@ class InvokerBytecodeGenerator { ...@@ -645,8 +624,6 @@ class InvokerBytecodeGenerator {
/** /**
* Emit an invoke for the given name, using the MemberName directly. * Emit an invoke for the given name, using the MemberName directly.
*
* @param name
*/ */
void emitStaticInvoke(MemberName member, Name name) { void emitStaticInvoke(MemberName member, Name name) {
assert(member.equals(name.function.member())); assert(member.equals(name.function.member()));
...@@ -690,9 +667,6 @@ class InvokerBytecodeGenerator { ...@@ -690,9 +667,6 @@ class InvokerBytecodeGenerator {
/** /**
* Check if MemberName is a call to MethodHandleImpl.selectAlternative. * Check if MemberName is a call to MethodHandleImpl.selectAlternative.
*
* @param member
* @return true if member is a call to MethodHandleImpl.selectAlternative
*/ */
private boolean isSelectAlternative(MemberName member) { private boolean isSelectAlternative(MemberName member) {
return member != null && return member != null &&
...@@ -704,14 +678,12 @@ class InvokerBytecodeGenerator { ...@@ -704,14 +678,12 @@ class InvokerBytecodeGenerator {
* Emit bytecode for the selectAlternative idiom. * Emit bytecode for the selectAlternative idiom.
* *
* The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest): * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest):
* * <blockquote><pre>{@code
* Lambda(a0:L,a1:I)=>{ * Lambda(a0:L,a1:I)=>{
* t2:I=foo.test(a1:I); * t2:I=foo.test(a1:I);
* t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int)); * t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
* t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I} * t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
* * }</pre></blockquote>
* @param selectAlternativeName
* @param invokeBasicName
*/ */
private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
MethodType type = selectAlternativeName.function.methodType(); MethodType type = selectAlternativeName.function.methodType();
...@@ -750,11 +722,6 @@ class InvokerBytecodeGenerator { ...@@ -750,11 +722,6 @@ class InvokerBytecodeGenerator {
mv.visitLabel(L_done); mv.visitLabel(L_done);
} }
/**
*
* @param name
* @param paramIndex
*/
private void emitPushArgument(Name name, int paramIndex) { private void emitPushArgument(Name name, int paramIndex) {
Object arg = name.arguments[paramIndex]; Object arg = name.arguments[paramIndex];
char ptype = name.function.parameterType(paramIndex); char ptype = name.function.parameterType(paramIndex);
...@@ -923,9 +890,6 @@ class InvokerBytecodeGenerator { ...@@ -923,9 +890,6 @@ class InvokerBytecodeGenerator {
/** /**
* Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments. * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments.
*
* @param sig
* @return
*/ */
static MemberName generateLambdaFormInterpreterEntryPoint(String sig) { static MemberName generateLambdaFormInterpreterEntryPoint(String sig) {
assert(LambdaForm.isValidSignature(sig)); assert(LambdaForm.isValidSignature(sig));
...@@ -993,10 +957,6 @@ class InvokerBytecodeGenerator { ...@@ -993,10 +957,6 @@ class InvokerBytecodeGenerator {
/** /**
* Generate bytecode for a NamedFunction invoker. * Generate bytecode for a NamedFunction invoker.
*
* @param srcType
* @param dstType
* @return
*/ */
static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) {
MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE; MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE;
......
...@@ -50,7 +50,7 @@ import java.util.Objects; ...@@ -50,7 +50,7 @@ import java.util.Objects;
* The result of the lambda is defined as one of the names, often the last one. * The result of the lambda is defined as one of the names, often the last one.
* <p> * <p>
* Here is an approximate grammar: * Here is an approximate grammar:
* <pre> * <blockquote><pre>{@code
* LambdaForm = "(" ArgName* ")=>{" TempName* Result "}" * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
* ArgName = "a" N ":" T * ArgName = "a" N ":" T
* TempName = "t" N ":" T "=" Function "(" Argument* ");" * TempName = "t" N ":" T "=" Function "(" Argument* ");"
...@@ -60,7 +60,7 @@ import java.util.Objects; ...@@ -60,7 +60,7 @@ import java.util.Objects;
* NameRef = "a" N | "t" N * NameRef = "a" N | "t" N
* N = (any whole number) * N = (any whole number)
* T = "L" | "I" | "J" | "F" | "D" | "V" * T = "L" | "I" | "J" | "F" | "D" | "V"
* </pre> * }</pre></blockquote>
* Names are numbered consecutively from left to right starting at zero. * Names are numbered consecutively from left to right starting at zero.
* (The letters are merely a taste of syntax sugar.) * (The letters are merely a taste of syntax sugar.)
* Thus, the first temporary (if any) is always numbered N (where N=arity). * Thus, the first temporary (if any) is always numbered N (where N=arity).
...@@ -69,7 +69,7 @@ import java.util.Objects; ...@@ -69,7 +69,7 @@ import java.util.Objects;
* A lambda has a void result if and only if its result index is -1. * A lambda has a void result if and only if its result index is -1.
* If a temporary has the type "V", it cannot be the subject of a NameRef, * If a temporary has the type "V", it cannot be the subject of a NameRef,
* even though possesses a number. * even though possesses a number.
* Note that all reference types are erased to "L", which stands for {@code Object). * Note that all reference types are erased to "L", which stands for {@code Object}.
* All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}. * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
* The other types stand for the usual primitive types. * The other types stand for the usual primitive types.
* <p> * <p>
...@@ -89,7 +89,7 @@ import java.util.Objects; ...@@ -89,7 +89,7 @@ import java.util.Objects;
* encoded by using temporary expressions which call type-transformed identity functions. * encoded by using temporary expressions which call type-transformed identity functions.
* <p> * <p>
* Examples: * Examples:
* <pre> * <blockquote><pre>{@code
* (a0:J)=>{ a0 } * (a0:J)=>{ a0 }
* == identity(long) * == identity(long)
* (a0:I)=>{ t1:V = System.out#println(a0); void } * (a0:I)=>{ t1:V = System.out#println(a0); void }
...@@ -113,7 +113,7 @@ import java.util.Objects; ...@@ -113,7 +113,7 @@ import java.util.Objects;
* (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0); * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
* t3:L = Class#cast(t2,a1); t3 } * t3:L = Class#cast(t2,a1); t3 }
* == invoker for identity method handle which performs cast * == invoker for identity method handle which performs cast
* </pre> * }</pre></blockquote>
* <p> * <p>
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
...@@ -1441,8 +1441,6 @@ class LambdaForm { ...@@ -1441,8 +1441,6 @@ class LambdaForm {
* Does this Name precede the given binding node in some canonical order? * Does this Name precede the given binding node in some canonical order?
* This predicate is used to order data bindings (via insertion sort) * This predicate is used to order data bindings (via insertion sort)
* with some stability. * with some stability.
* @param binding
* @return
*/ */
boolean isSiblingBindingBefore(Name binding) { boolean isSiblingBindingBefore(Name binding) {
assert(!binding.isParam()); assert(!binding.isParam());
......
...@@ -292,7 +292,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -292,7 +292,7 @@ mh.invokeExact(System.out, "Hello, world.");
* generates a single invokevirtual instruction with * generates a single invokevirtual instruction with
* the symbolic type descriptor indicated in the following comment. * the symbolic type descriptor indicated in the following comment.
* In these examples, the helper method {@code assertEquals} is assumed to * In these examples, the helper method {@code assertEquals} is assumed to
* be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals } * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals}
* on its arguments, and asserts that the result is true. * on its arguments, and asserts that the result is true.
* *
* <h1>Exceptions</h1> * <h1>Exceptions</h1>
...@@ -575,10 +575,10 @@ public abstract class MethodHandle { ...@@ -575,10 +575,10 @@ public abstract class MethodHandle {
/*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable; /*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
/** /**
* Performs a variable arity invocation, passing the arguments in the given array * Performs a variable arity invocation, passing the arguments in the given list
* to the method handle, as if via an inexact {@link #invoke invoke} from a call site * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
* which mentions only the type {@code Object}, and whose arity is the length * which mentions only the type {@code Object}, and whose arity is the length
* of the argument array. * of the argument list.
* <p> * <p>
* Specifically, execution proceeds as if by the following steps, * Specifically, execution proceeds as if by the following steps,
* although the methods are not guaranteed to be called if the JVM * although the methods are not guaranteed to be called if the JVM
...@@ -608,10 +608,10 @@ public abstract class MethodHandle { ...@@ -608,10 +608,10 @@ public abstract class MethodHandle {
* or forced to null if the return type is void. * or forced to null if the return type is void.
* <p> * <p>
* This call is equivalent to the following code: * This call is equivalent to the following code:
* <p><blockquote><pre> * <p><blockquote><pre>{@code
* MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0); * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0);
* Object result = invoker.invokeExact(this, arguments); * Object result = invoker.invokeExact(this, arguments);
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* Unlike the signature polymorphic methods {@code invokeExact} and {@code invoke}, * Unlike the signature polymorphic methods {@code invokeExact} and {@code invoke},
* {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI. * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
...@@ -644,7 +644,7 @@ public abstract class MethodHandle { ...@@ -644,7 +644,7 @@ public abstract class MethodHandle {
* <p> * <p>
* This method is also equivalent to the following code: * This method is also equivalent to the following code:
* <p><blockquote><pre> * <p><blockquote><pre>
* {@link #invokeWithArguments(Object...) invokeWithArguments}(arguments.toArray()) * {@link #invokeWithArguments(Object...) invokeWithArguments}{@code(arguments.toArray())}
* </pre></blockquote> * </pre></blockquote>
* *
* @param arguments the arguments to pass to the target * @param arguments the arguments to pass to the target
...@@ -1272,9 +1272,9 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1272,9 +1272,9 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
* starting with the string {@code "MethodHandle"} and * starting with the string {@code "MethodHandle"} and
* ending with the string representation of the method handle's type. * ending with the string representation of the method handle's type.
* In other words, this method returns a string equal to the value of: * In other words, this method returns a string equal to the value of:
* <blockquote><pre> * <blockquote><pre>{@code
* "MethodHandle" + type().toString() * "MethodHandle" + type().toString()
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* (<em>Note:</em> Future releases of this API may add further information * (<em>Note:</em> Future releases of this API may add further information
* to the string representation. * to the string representation.
...@@ -1485,7 +1485,6 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1485,7 +1485,6 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
* Threads may continue running the old form indefinitely, * Threads may continue running the old form indefinitely,
* but it is likely that the new one will be preferred for new executions. * but it is likely that the new one will be preferred for new executions.
* Use with discretion. * Use with discretion.
* @param newForm
*/ */
/*non-public*/ /*non-public*/
void updateForm(LambdaForm newForm) { void updateForm(LambdaForm newForm) {
......
...@@ -32,9 +32,10 @@ import java.lang.invoke.MethodHandles.Lookup; ...@@ -32,9 +32,10 @@ import java.lang.invoke.MethodHandles.Lookup;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
/** /**
* A symbolic reference obtained by cracking a method handle into its consitutent symbolic parts. * A symbolic reference obtained by cracking a direct method handle
* into its consitutent symbolic parts.
* To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}. * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
* <p> * <h1><a name="directmh"></a>Direct Method Handles</h1>
* A <em>direct method handle</em> represents a method, constructor, or field without * A <em>direct method handle</em> represents a method, constructor, or field without
* any intervening argument bindings or other transformations. * any intervening argument bindings or other transformations.
* The method, constructor, or field referred to by a direct method handle is called * The method, constructor, or field referred to by a direct method handle is called
...@@ -56,7 +57,9 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -56,7 +57,9 @@ import static java.lang.invoke.MethodHandleStatics.*;
* or {@link Lookup#unreflectSetter Lookup.unreflectSetter} * or {@link Lookup#unreflectSetter Lookup.unreflectSetter}
* to convert a {@link Field} into a method handle. * to convert a {@link Field} into a method handle.
* </ul> * </ul>
* In all of these cases, it is possible to crack the resulting direct method handle *
* <h1>Restrictions on Cracking</h1>
* Given a suitable {@code Lookup} object, it is possible to crack any direct method handle
* to recover a symbolic reference for the underlying method, constructor, or field. * to recover a symbolic reference for the underlying method, constructor, or field.
* Cracking must be done via a {@code Lookup} object equivalent to that which created * Cracking must be done via a {@code Lookup} object equivalent to that which created
* the target method handle, or which has enough access permissions to recreate * the target method handle, or which has enough access permissions to recreate
...@@ -202,7 +205,7 @@ interface MethodHandleInfo { ...@@ -202,7 +205,7 @@ interface MethodHandleInfo {
* @return the Java language modifiers for underlying member, * @return the Java language modifiers for underlying member,
* or -1 if the member cannot be accessed * or -1 if the member cannot be accessed
* @see Modifier * @see Modifier
* @see reflectAs * @see #reflectAs
*/ */
public int getModifiers(); public int getModifiers();
......
...@@ -49,7 +49,6 @@ import sun.security.util.SecurityConstants; ...@@ -49,7 +49,6 @@ import sun.security.util.SecurityConstants;
* <li>Lookup methods which help create method handles for methods and fields. * <li>Lookup methods which help create method handles for methods and fields.
* <li>Combinator methods, which combine or transform pre-existing method handles into new ones. * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
* <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns. * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
* <li>Wrapper methods which can convert between method handles and interface types.
* </ul> * </ul>
* <p> * <p>
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
...@@ -66,12 +65,25 @@ public class MethodHandles { ...@@ -66,12 +65,25 @@ public class MethodHandles {
//// Method handle creation from ordinary methods. //// Method handle creation from ordinary methods.
/** /**
* Returns a {@link Lookup lookup object} on the caller, * Returns a {@link Lookup lookup object} with
* which has the capability to access any method handle that the caller has access to, * full capabilities to emulate all supported bytecode behaviors of the caller.
* including direct method handles to private fields and methods. * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller.
* Factory methods on the lookup object can create
* <a href="MethodHandleInfo.html#directmh">direct method handles</a>
* for any member that the caller has access to via bytecodes,
* including protected and private fields and methods.
* This lookup object is a <em>capability</em> which may be delegated to trusted agents. * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
* Do not store it in place where untrusted code can access it. * Do not store it in place where untrusted code can access it.
* @return a lookup object for the caller of this method * <p>
* This method is caller sensitive, which means that it may return different
* values to different callers.
* <p>
* For any given caller class {@code C}, the lookup object returned by this call
* has equivalent capabilities to any lookup object
* supplied by the JVM to the bootstrap method of an
* <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
* executing in the same caller class {@code C}.
* @return a lookup object for the caller of this method, with private access
*/ */
@CallerSensitive @CallerSensitive
public static Lookup lookup() { public static Lookup lookup() {
...@@ -85,9 +97,11 @@ public class MethodHandles { ...@@ -85,9 +97,11 @@ public class MethodHandles {
* <p> * <p>
* As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
* of this lookup object will be {@link java.lang.Object}. * of this lookup object will be {@link java.lang.Object}.
* <p> *
* <p style="font-size:smaller;">
* <em>Discussion:</em>
* The lookup class can be changed to any other class {@code C} using an expression of the form * The lookup class can be changed to any other class {@code C} using an expression of the form
* {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}. * {@link Lookup#in publicLookup().in(C.class)}.
* Since all classes have equal access to public names, * Since all classes have equal access to public names,
* such a change would confer no new access rights. * such a change would confer no new access rights.
* A public lookup object is always subject to * A public lookup object is always subject to
...@@ -101,7 +115,8 @@ public class MethodHandles { ...@@ -101,7 +115,8 @@ public class MethodHandles {
} }
/** /**
* Performs an unchecked "crack" of a direct method handle. * Performs an unchecked "crack" of a
* <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
* The result is as if the user had obtained a lookup object capable enough * The result is as if the user had obtained a lookup object capable enough
* to crack the target method handle, called * to crack the target method handle, called
* {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect} * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
...@@ -154,10 +169,17 @@ public class MethodHandles { ...@@ -154,10 +169,17 @@ public class MethodHandles {
* <h1><a name="lookups"></a>Lookup Factory Methods</h1> * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
* The factory methods on a {@code Lookup} object correspond to all major * The factory methods on a {@code Lookup} object correspond to all major
* use cases for methods, constructors, and fields. * use cases for methods, constructors, and fields.
* Each method handle created by a factory method is the functional
* equivalent of a particular <em>bytecode behavior</em>.
* (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.)
* Here is a summary of the correspondence between these factory methods and * Here is a summary of the correspondence between these factory methods and
* the behavior the resulting method handles: * the behavior the resulting method handles:
* <table border=1 cellpadding=5 summary="lookup method behaviors"> * <table border=1 cellpadding=5 summary="lookup method behaviors">
* <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr> * <tr>
* <th><a name="equiv"></a>lookup expression</th>
* <th>member</th>
* <th>bytecode behavior</th>
* </tr>
* <tr> * <tr>
* <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
* <td>{@code FT f;}</td><td>{@code (T) this.f;}</td> * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
...@@ -233,10 +255,12 @@ public class MethodHandles { ...@@ -233,10 +255,12 @@ public class MethodHandles {
* In cases where the given member is of variable arity (i.e., a method or constructor) * In cases where the given member is of variable arity (i.e., a method or constructor)
* the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}. * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}.
* In all other cases, the returned method handle will be of fixed arity. * In all other cases, the returned method handle will be of fixed arity.
* <p> * <p style="font-size:smaller;">
* <em>Discussion:</em>
* The equivalence between looked-up method handles and underlying * The equivalence between looked-up method handles and underlying
* class members can break down in a few ways: * class members and bytecode behaviors
* <ul> * can break down in a few ways:
* <ul style="font-size:smaller;">
* <li>If {@code C} is not symbolically accessible from the lookup class's loader, * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
* the lookup can still succeed, even when there is no equivalent * the lookup can still succeed, even when there is no equivalent
* Java expression or bytecoded constant. * Java expression or bytecoded constant.
...@@ -280,7 +304,8 @@ public class MethodHandles { ...@@ -280,7 +304,8 @@ public class MethodHandles {
* A lookup can fail, because * A lookup can fail, because
* the containing class is not accessible to the lookup class, or * the containing class is not accessible to the lookup class, or
* because the desired class member is missing, or because the * because the desired class member is missing, or because the
* desired class member is not accessible to the lookup class. * desired class member is not accessible to the lookup class, or
* because the lookup object is not trusted enough to access the member.
* In any of these cases, a {@code ReflectiveOperationException} will be * In any of these cases, a {@code ReflectiveOperationException} will be
* thrown from the attempted lookup. The exact class will be one of * thrown from the attempted lookup. The exact class will be one of
* the following: * the following:
...@@ -291,14 +316,23 @@ public class MethodHandles { ...@@ -291,14 +316,23 @@ public class MethodHandles {
* </ul> * </ul>
* <p> * <p>
* In general, the conditions under which a method handle may be * In general, the conditions under which a method handle may be
* looked up for a method {@code M} are exactly equivalent to the conditions * looked up for a method {@code M} are no more restrictive than the conditions
* under which the lookup class could have compiled and resolved a call to {@code M}. * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
* Where the JVM would raise exceptions like {@code NoSuchMethodError}, * Where the JVM would raise exceptions like {@code NoSuchMethodError},
* a method handle lookup will generally raise a corresponding * a method handle lookup will generally raise a corresponding
* checked exception, such as {@code NoSuchMethodException}. * checked exception, such as {@code NoSuchMethodException}.
* And the effect of invoking the method handle resulting from the lookup * And the effect of invoking the method handle resulting from the lookup
* is exactly equivalent to executing the compiled and resolved call to {@code M}. * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
* to executing the compiled, verified, and resolved call to {@code M}.
* The same point is true of fields and constructors. * The same point is true of fields and constructors.
* <p style="font-size:smaller;">
* <em>Discussion:</em>
* Access checks only apply to named and reflected methods,
* constructors, and fields.
* Other method handle creation methods, such as
* {@link MethodHandle#asType MethodHandle.asType},
* do not require any access checks, and are used
* independently of any {@code Lookup} object.
* <p> * <p>
* If the desired member is {@code protected}, the usual JVM rules apply, * If the desired member is {@code protected}, the usual JVM rules apply,
* including the requirement that the lookup class must be either be in the * including the requirement that the lookup class must be either be in the
...@@ -312,6 +346,12 @@ public class MethodHandles { ...@@ -312,6 +346,12 @@ public class MethodHandles {
* (which will necessarily be a superclass of the lookup class) * (which will necessarily be a superclass of the lookup class)
* to the lookup class itself. * to the lookup class itself.
* <p> * <p>
* The JVM imposes a similar requirement on {@code invokespecial} instruction,
* that the receiver argument must match both the resolved method <em>and</em>
* the current class. Again, this requirement is enforced by narrowing the
* type of the leading parameter to the resulting method handle.
* (See the Java Virtual Machine Specification, section 4.10.1.9.)
* <p>
* The JVM represents constructors and static initializer blocks as internal methods * The JVM represents constructors and static initializer blocks as internal methods
* with special names ({@code "<init>"} and {@code "<clinit>"}). * with special names ({@code "<init>"} and {@code "<clinit>"}).
* The internal syntax of invocation instructions allows them to refer to such internal * The internal syntax of invocation instructions allows them to refer to such internal
...@@ -331,6 +371,43 @@ public class MethodHandles { ...@@ -331,6 +371,43 @@ public class MethodHandles {
* which can transform a lookup on {@code C.E} into one on any of those other * which can transform a lookup on {@code C.E} into one on any of those other
* classes, without special elevation of privilege. * classes, without special elevation of privilege.
* <p> * <p>
* The accesses permitted to a given lookup object may be limited,
* according to its set of {@link #lookupModes lookupModes},
* to a subset of members normally accessible to the lookup class.
* For example, the {@link MethodHandles#publicLookup publicLookup}
* method produces a lookup object which is only allowed to access
* public members in public classes.
* The caller sensitive method {@link MethodHandles#lookup lookup}
* produces a lookup object with full capabilities relative to
* its caller class, to emulate all supported bytecode behaviors.
* Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
* with fewer access modes than the original lookup object.
*
* <p style="font-size:smaller;">
* <a name="privacc"></a>
* <em>Discussion of private access:</em>
* We say that a lookup has <em>private access</em>
* if its {@linkplain #lookupModes lookup modes}
* include the possibility of accessing {@code private} members.
* As documented in the relevant methods elsewhere,
* only lookups with private access possess the following capabilities:
* <ul style="font-size:smaller;">
* <li>access private fields, methods, and constructors of the lookup class
* <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
* such as {@code Class.forName}
* <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
* <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
* for classes accessible to the lookup class
* <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
* within the same package member
* </ul>
* <p style="font-size:smaller;">
* Each of these permissions is a consequence of the fact that a lookup object
* with private access can be securely traced back to an originating class,
* whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
* can be reliably determined and emulated by method handles.
*
* <h1><a name="secmgr"></a>Security manager interactions</h1>
* Although bytecode instructions can only refer to classes in * Although bytecode instructions can only refer to classes in
* a related class loader, this API can search for methods in any * a related class loader, this API can search for methods in any
* class, as long as a reference to its {@code Class} object is * class, as long as a reference to its {@code Class} object is
...@@ -343,16 +420,6 @@ public class MethodHandles { ...@@ -343,16 +420,6 @@ public class MethodHandles {
* and the Core Reflection API * and the Core Reflection API
* (as found on {@link java.lang.Class Class}). * (as found on {@link java.lang.Class Class}).
* <p> * <p>
* Access checks only apply to named and reflected methods,
* constructors, and fields.
* Other method handle creation methods, such as
* {@link MethodHandle#asType MethodHandle.asType},
* do not require any access checks, and are done
* with static methods of {@link MethodHandles},
* independently of any {@code Lookup} object.
*
* <h1>Security manager interactions</h1>
* <a name="secmgr"></a>
* If a security manager is present, member lookups are subject to * If a security manager is present, member lookups are subject to
* additional checks. * additional checks.
* From one to three calls are made to the security manager. * From one to three calls are made to the security manager.
...@@ -365,19 +432,22 @@ public class MethodHandles { ...@@ -365,19 +432,22 @@ public class MethodHandles {
* member is actually defined. * member is actually defined.
* The value {@code lookc} is defined as <em>not present</em> * The value {@code lookc} is defined as <em>not present</em>
* if the current lookup object does not have * if the current lookup object does not have
* {@linkplain java.lang.invoke.MethodHandles.Lookup#PRIVATE private access}. * <a href="MethodHandles.Lookup.html#privacc">private access</a>.
* The calls are made according to the following rules: * The calls are made according to the following rules:
* <ul> * <ul>
* <li>If {@code lookc} is not present, or if its class loader is not * <li><b>Step 1:</b>
* If {@code lookc} is not present, or if its class loader is not
* the same as or an ancestor of the class loader of {@code refc}, * the same as or an ancestor of the class loader of {@code refc},
* then {@link SecurityManager#checkPackageAccess * then {@link SecurityManager#checkPackageAccess
* smgr.checkPackageAccess(refcPkg)} is called, * smgr.checkPackageAccess(refcPkg)} is called,
* where {@code refcPkg} is the package of {@code refc}. * where {@code refcPkg} is the package of {@code refc}.
* <li>If the retrieved member is not public and * <li><b>Step 2:</b>
* If the retrieved member is not public and
* {@code lookc} is not present, then * {@code lookc} is not present, then
* {@link SecurityManager#checkPermission smgr.checkPermission} * {@link SecurityManager#checkPermission smgr.checkPermission}
* with {@code RuntimePermission("accessDeclaredMembers")} is called. * with {@code RuntimePermission("accessDeclaredMembers")} is called.
* <li>If the retrieved member is not public, * <li><b>Step 3:</b>
* If the retrieved member is not public,
* and if {@code lookc} is not present, * and if {@code lookc} is not present,
* and if {@code defc} and {@code refc} are different, * and if {@code defc} and {@code refc} are different,
* then {@link SecurityManager#checkPackageAccess * then {@link SecurityManager#checkPackageAccess
...@@ -408,11 +478,32 @@ public class MethodHandles { ...@@ -408,11 +478,32 @@ public class MethodHandles {
* In cases where the lookup object is * In cases where the lookup object is
* {@link MethodHandles#publicLookup() publicLookup()}, * {@link MethodHandles#publicLookup() publicLookup()},
* or some other lookup object without * or some other lookup object without
* {@linkplain java.lang.invoke.MethodHandles.Lookup#PRIVATE private access}, * <a href="MethodHandles.Lookup.html#privacc">private access</a>,
* the lookup class is disregarded. * the lookup class is disregarded.
* In such cases, no caller-sensitive method handle can be created, * In such cases, no caller-sensitive method handle can be created,
* access is forbidden, and the lookup fails with an * access is forbidden, and the lookup fails with an
* {@code IllegalAccessException}. * {@code IllegalAccessException}.
* <p style="font-size:smaller;">
* <em>Discussion:</em>
* For example, the caller-sensitive method
* {@link java.lang.Class#forName(String) Class.forName(x)}
* can return varying classes or throw varying exceptions,
* depending on the class loader of the class that calls it.
* A public lookup of {@code Class.forName} will fail, because
* there is no reasonable way to determine its bytecode behavior.
* <p style="font-size:smaller;">
* If an application caches method handles for broad sharing,
* it should use {@code publicLookup()} to create them.
* If there is a lookup of {@code Class.forName}, it will fail,
* and the application must take appropriate action in that case.
* It may be that a later lookup, perhaps during the invocation of a
* bootstrap method, can incorporate the specific identity
* of the caller, making the method accessible.
* <p style="font-size:smaller;">
* The function {@code MethodHandles.lookup} is caller sensitive
* so that there can be a secure foundation for lookups.
* Nearly all other methods in the JSR 292 API rely on lookup
* objects to check access requests.
*/ */
public static final public static final
class Lookup { class Lookup {
...@@ -639,7 +730,7 @@ public class MethodHandles { ...@@ -639,7 +730,7 @@ public class MethodHandles {
* (Since static methods do not take receivers, there is no * (Since static methods do not take receivers, there is no
* additional receiver argument inserted into the method handle type, * additional receiver argument inserted into the method handle type,
* as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.) * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
* The method and all its argument types must be accessible to the lookup class. * The method and all its argument types must be accessible to the lookup object.
* <p> * <p>
* The returned method handle will have * The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
...@@ -679,7 +770,7 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString()); ...@@ -679,7 +770,7 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
* Produces a method handle for a virtual method. * Produces a method handle for a virtual method.
* The type of the method handle will be that of the method, * The type of the method handle will be that of the method,
* with the receiver type (usually {@code refc}) prepended. * with the receiver type (usually {@code refc}) prepended.
* The method and all its argument types must be accessible to the lookup class. * The method and all its argument types must be accessible to the lookup object.
* <p> * <p>
* When called, the handle will treat the first argument as a receiver * When called, the handle will treat the first argument as a receiver
* and dispatch on the receiver's type to determine which method * and dispatch on the receiver's type to determine which method
...@@ -696,7 +787,7 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString()); ...@@ -696,7 +787,7 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set. * the method's variable arity modifier bit ({@code 0x0080}) is set.
* <p> * <p>
* Because of the general equivalence between {@code invokevirtual} * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
* instructions and method handles produced by {@code findVirtual}, * instructions and method handles produced by {@code findVirtual},
* if the class is {@code MethodHandle} and the name string is * if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invoke}, the resulting * {@code invokeExact} or {@code invoke}, the resulting
...@@ -770,10 +861,10 @@ assertEquals("", (String) MH_newString.invokeExact()); ...@@ -770,10 +861,10 @@ assertEquals("", (String) MH_newString.invokeExact());
* the constructor of the specified type. * the constructor of the specified type.
* The parameter types of the method handle will be those of the constructor, * The parameter types of the method handle will be those of the constructor,
* while the return type will be a reference to the constructor's class. * while the return type will be a reference to the constructor's class.
* The constructor and all its argument types must be accessible to the lookup class. * The constructor and all its argument types must be accessible to the lookup object.
* <p> * <p>
* <em>(Note: The requested type must have a return type of {@code void}. * The requested type must have a return type of {@code void}.
* This is consistent with the JVM's treatment of constructor type descriptors.)</em> * (This is consistent with the JVM's treatment of constructor type descriptors.)
* <p> * <p>
* The returned method handle will have * The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
...@@ -817,27 +908,26 @@ assertEquals("[x, y, z]", pb.command().toString()); ...@@ -817,27 +908,26 @@ assertEquals("[x, y, z]", pb.command().toString());
} }
/** /**
* Produces an early-bound method handle for a virtual method, * Produces an early-bound method handle for a virtual method.
* as if called from an {@code invokespecial} * It will bypass checks for overriding methods on the receiver,
* instruction from {@code caller}. * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
* instruction from within the explicitly specified {@code specialCaller}.
* The type of the method handle will be that of the method, * The type of the method handle will be that of the method,
* with a suitably restricted receiver type (such as {@code caller}) prepended. * with a suitably restricted receiver type prepended.
* (The receiver type will be {@code specialCaller} or a subtype.)
* The method and all its argument types must be accessible * The method and all its argument types must be accessible
* to the caller. * to the lookup object.
* <p> * <p>
* When called, the handle will treat the first argument as a receiver, * Before method resolution,
* but will not dispatch on the receiver's type. * if the explicitly specified caller class is not identical with the
* (This direct invocation action is identical with that performed by an * lookup class, or if this lookup object does not have
* {@code invokespecial} instruction.) * <a href="MethodHandles.Lookup.html#privacc">private access</a>
* <p>
* If the explicitly specified caller class is not identical with the
* lookup class, or if this lookup object does not have private access
* privileges, the access fails. * privileges, the access fails.
* <p> * <p>
* The returned method handle will have * The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set. * the method's variable arity modifier bit ({@code 0x0080}) is set.
* <p> * <p style="font-size:smaller;">
* <em>(Note: JVM internal methods named {@code "<init>"} are not visible to this API, * <em>(Note: JVM internal methods named {@code "<init>"} are not visible to this API,
* even though the {@code invokespecial} instruction can refer to them * even though the {@code invokespecial} instruction can refer to them
* in special circumstances. Use {@link #findConstructor findConstructor} * in special circumstances. Use {@link #findConstructor findConstructor}
...@@ -993,7 +1083,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method ...@@ -993,7 +1083,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
* Produces an early-bound method handle for a non-static method. * Produces an early-bound method handle for a non-static method.
* The receiver must have a supertype {@code defc} in which a method * The receiver must have a supertype {@code defc} in which a method
* of the given name and type is accessible to the lookup class. * of the given name and type is accessible to the lookup class.
* The method and all its argument types must be accessible to the lookup class. * The method and all its argument types must be accessible to the lookup object.
* The type of the method handle will be that of the method, * The type of the method handle will be that of the method,
* without any insertion of an additional receiver parameter. * without any insertion of an additional receiver parameter.
* The given receiver will be bound into the method handle, * The given receiver will be bound into the method handle,
...@@ -1008,17 +1098,17 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method ...@@ -1008,17 +1098,17 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
* the given receiver value will be bound to it.) * the given receiver value will be bound to it.)
* <p> * <p>
* This is equivalent to the following code: * This is equivalent to the following code:
* <blockquote><pre> * <blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
MethodHandle mh0 = lookup().{@link #findVirtual findVirtual}(defc, name, type); MethodHandle mh0 = lookup().findVirtual(defc, name, type);
MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver); MethodHandle mh1 = mh0.bindTo(receiver);
MethodType mt1 = mh1.type(); MethodType mt1 = mh1.type();
if (mh0.isVarargsCollector()) if (mh0.isVarargsCollector())
mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
return mh1; return mh1;
* </pre></blockquote> * }</pre></blockquote>
* where {@code defc} is either {@code receiver.getClass()} or a super * where {@code defc} is either {@code receiver.getClass()} or a super
* type of that class, in which the requested method is accessible * type of that class, in which the requested method is accessible
* to the lookup class. * to the lookup class.
...@@ -1034,6 +1124,8 @@ return mh1; ...@@ -1034,6 +1124,8 @@ return mh1;
* @exception SecurityException if a security manager is present and it * @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
* @see MethodHandle#bindTo
* @see #findVirtual
*/ */
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
Class<? extends Object> refc = receiver.getClass(); // may get NPE Class<? extends Object> refc = receiver.getClass(); // may get NPE
...@@ -1043,7 +1135,8 @@ return mh1; ...@@ -1043,7 +1135,8 @@ return mh1;
} }
/** /**
* Makes a direct method handle to <i>m</i>, if the lookup class has permission. * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
* to <i>m</i>, if the lookup class has permission.
* If <i>m</i> is non-static, the receiver argument is treated as an initial argument. * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
* If <i>m</i> is virtual, overriding is respected on every call. * If <i>m</i> is virtual, overriding is respected on every call.
* Unlike the Core Reflection API, exceptions are <em>not</em> wrapped. * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
...@@ -1090,13 +1183,21 @@ return mh1; ...@@ -1090,13 +1183,21 @@ return mh1;
/** /**
* Produces a method handle for a reflected method. * Produces a method handle for a reflected method.
* It will bypass checks for overriding methods on the receiver, * It will bypass checks for overriding methods on the receiver,
* as if by a {@code invokespecial} instruction from within the {@code specialCaller}. * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
* instruction from within the explicitly specified {@code specialCaller}.
* The type of the method handle will be that of the method, * The type of the method handle will be that of the method,
* with the special caller type prepended (and <em>not</em> the receiver of the method). * with a suitably restricted receiver type prepended.
* (The receiver type will be {@code specialCaller} or a subtype.)
* If the method's {@code accessible} flag is not set, * If the method's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class, * access checking is performed immediately on behalf of the lookup class,
* as if {@code invokespecial} instruction were being linked. * as if {@code invokespecial} instruction were being linked.
* <p> * <p>
* Before method resolution,
* if the explicitly specified caller class is not identical with the
* lookup class, or if this lookup object does not have
* <a href="MethodHandles.Lookup.html#privacc">private access</a>
* privileges, the access fails.
* <p>
* The returned method handle will have * The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set. * the method's variable arity modifier bit ({@code 0x0080}) is set.
...@@ -1141,8 +1242,7 @@ return mh1; ...@@ -1141,8 +1242,7 @@ return mh1;
* is set and {@code asVarargsCollector} fails * is set and {@code asVarargsCollector} fails
* @throws NullPointerException if the argument is null * @throws NullPointerException if the argument is null
*/ */
@SuppressWarnings("rawtypes") // Will be Constructor<?> after JSR 292 MR public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
MemberName ctor = new MemberName(c); MemberName ctor = new MemberName(c);
assert(ctor.isConstructor()); assert(ctor.isConstructor());
Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
...@@ -1202,7 +1302,8 @@ return mh1; ...@@ -1202,7 +1302,8 @@ return mh1;
} }
/** /**
* Cracks a direct method handle created by this lookup object or a similar one. * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
* created by this lookup object or a similar one.
* Security and access checks are performed to ensure that this lookup object * Security and access checks are performed to ensure that this lookup object
* is capable of reproducing the target method handle. * is capable of reproducing the target method handle.
* This means that the cracking may fail if target is a direct method handle * This means that the cracking may fail if target is a direct method handle
...@@ -1215,6 +1316,7 @@ return mh1; ...@@ -1215,6 +1316,7 @@ return mh1;
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
* @exception NullPointerException if the target is {@code null} * @exception NullPointerException if the target is {@code null}
* @see MethodHandleInfo
* @since 1.8 * @since 1.8
*/ */
public MethodHandleInfo revealDirect(MethodHandle target) { public MethodHandleInfo revealDirect(MethodHandle target) {
...@@ -1282,7 +1384,7 @@ return mh1; ...@@ -1282,7 +1384,7 @@ return mh1;
throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
} }
/** Check name for an illegal leading "<" character. */ /** Check name for an illegal leading "&lt;" character. */
void checkMethodName(byte refKind, String name) throws NoSuchMethodException { void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
if (name.startsWith("<") && refKind != REF_newInvokeSpecial) if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
throw new NoSuchMethodException("illegal method name: "+name); throw new NoSuchMethodException("illegal method name: "+name);
...@@ -1730,13 +1832,12 @@ return mh1; ...@@ -1730,13 +1832,12 @@ return mh1;
* an {@link IllegalArgumentException} instead of invoking the target. * an {@link IllegalArgumentException} instead of invoking the target.
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * <blockquote><pre>{@code
MethodHandle invoker = MethodHandles.invoker(type); MethodHandle invoker = MethodHandles.invoker(type);
int spreadArgCount = type.parameterCount() - leadingArgCount; int spreadArgCount = type.parameterCount() - leadingArgCount;
invoker = invoker.asSpreader(Object[].class, spreadArgCount); invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker; return invoker;
* </pre></blockquote> * }</pre></blockquote>
* <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
* @param type the desired target type * @param type the desired target type
* @param leadingArgCount number of fixed arguments, to be passed unchanged to the target * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
...@@ -1762,9 +1863,7 @@ return invoker; ...@@ -1762,9 +1863,7 @@ return invoker;
* an additional leading argument of type {@code MethodHandle}. * an additional leading argument of type {@code MethodHandle}.
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* </pre></blockquote>
* *
* <p style="font-size:smaller;"> * <p style="font-size:smaller;">
* <em>Discussion:</em> * <em>Discussion:</em>
...@@ -1779,7 +1878,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1779,7 +1878,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* If spreading, collecting, or other argument transformations are required, * If spreading, collecting, or other argument transformations are required,
* they can be applied once to the invoker {@code X} and reused on many {@code M} * they can be applied once to the invoker {@code X} and reused on many {@code M}
* method handle values, as long as they are compatible with the type of {@code X}. * method handle values, as long as they are compatible with the type of {@code X}.
* <p> * <p style="font-size:smaller;">
* <em>(Note: The invoker method is not available via the Core Reflection API. * <em>(Note: The invoker method is not available via the Core Reflection API.
* An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke} * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
* on the declared {@code invokeExact} or {@code invoke} method will raise an * on the declared {@code invokeExact} or {@code invoke} method will raise an
...@@ -1810,15 +1909,19 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1810,15 +1909,19 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle}, * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
* the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}. * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
* <p> * <p>
* A {@linkplain MethodType#genericMethodType general method type}, * This method is equivalent to the following code (though it may be more efficient):
* {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)}
* <p style="font-size:smaller;">
* <em>Discussion:</em>
* A {@linkplain MethodType#genericMethodType general method type} is one which
* mentions only {@code Object} arguments and return values. * mentions only {@code Object} arguments and return values.
* An invoker for such a type is capable of calling any method handle * An invoker for such a type is capable of calling any method handle
* of the same arity as the general type. * of the same arity as the general type.
* <p> * <p style="font-size:smaller;">
* This method is equivalent to the following code (though it may be more efficient): * <em>(Note: The invoker method is not available via the Core Reflection API.
* <p><blockquote><pre> * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
publicLookup().findVirtual(MethodHandle.class, "invoke", type) * on the declared {@code invokeExact} or {@code invoke} method will raise an
* </pre></blockquote> * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
* <p> * <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
* @param type the desired target type * @param type the desired target type
...@@ -2105,7 +2208,7 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -2105,7 +2208,7 @@ assert((int)twice.invokeExact(21) == 42);
* they will come after. * they will come after.
* <p> * <p>
* <b>Example:</b> * <b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2116,11 +2219,11 @@ MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class) ...@@ -2116,11 +2219,11 @@ MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class)
MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2)); MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
assertEquals(bigType, d0.type()); assertEquals(bigType, d0.type());
assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* This method is also equivalent to the following code: * This method is also equivalent to the following code:
* <p><blockquote><pre> * <p><blockquote><pre>
* {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0])) * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))}
* </pre></blockquote> * </pre></blockquote>
* @param target the method handle to invoke after the arguments are dropped * @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop * @param valueTypes the type(s) of the argument(s) to drop
...@@ -2163,7 +2266,7 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); ...@@ -2163,7 +2266,7 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
* they will come after. * they will come after.
* <p> * <p>
* <b>Example:</b> * <b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2178,11 +2281,11 @@ MethodHandle d2 = dropArguments(cat, 2, String.class); ...@@ -2178,11 +2281,11 @@ MethodHandle d2 = dropArguments(cat, 2, String.class);
assertEquals("xy", (String) d2.invokeExact("x", "y", "z")); assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* This method is also equivalent to the following code: * This method is also equivalent to the following code:
* <p><blockquote><pre> * <p><blockquote><pre>
* {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes)) * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
* </pre></blockquote> * </pre></blockquote>
* @param target the method handle to invoke after the arguments are dropped * @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop * @param valueTypes the type(s) of the argument(s) to drop
...@@ -2228,8 +2331,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); ...@@ -2228,8 +2331,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* It is an error if there are elements of {@code filters} * It is an error if there are elements of {@code filters}
* (null or not) * (null or not)
* which do not correspond to argument positions in the target. * which do not correspond to argument positions in the target.
* <b>Example:</b> * <p><b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2244,15 +2347,15 @@ MethodHandle f1 = filterArguments(cat, 1, upcase); ...@@ -2244,15 +2347,15 @@ MethodHandle f1 = filterArguments(cat, 1, upcase);
assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* </pre></blockquote> * }</pre></blockquote>
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* V target(P... p, A[i]... a[i], B... b); * V target(P... p, A[i]... a[i], B... b);
* A[i] filter[i](V[i]); * A[i] filter[i](V[i]);
* T adapter(P... p, V[i]... v[i], B... b) { * T adapter(P... p, V[i]... v[i], B... b) {
* return target(p..., f[i](v[i])..., b...); * return target(p..., f[i](v[i])..., b...);
* } * }
* </pre></blockquote> * }</pre></blockquote>
* *
* @param target the method handle to invoke after arguments are filtered * @param target the method handle to invoke after arguments are filtered
* @param pos the position of the first argument to filter * @param pos the position of the first argument to filter
...@@ -2322,7 +2425,7 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY ...@@ -2322,7 +2425,7 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* In all cases, {@code pos} must be greater than or equal to zero, and * In all cases, {@code pos} must be greater than or equal to zero, and
* {@code pos} must also be less than or equal to the target's arity. * {@code pos} must also be less than or equal to the target's arity.
* <p><b>Example:</b> * <p><b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2347,9 +2450,9 @@ assertEquals("[top, [up, down], [strange]]", ...@@ -2347,9 +2450,9 @@ assertEquals("[top, [up, down], [strange]]",
MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
assertEquals("[top, [[up, down, strange], charm], bottom]", assertEquals("[top, [[up, down, strange], charm], bottom]",
(String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom")); (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
* </pre></blockquote> * }</pre></blockquote>
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* T target(A...,V,C...); * T target(A...,V,C...);
* V filter(B...); * V filter(B...);
* T adapter(A... a,B... b,C... c) { * T adapter(A... a,B... b,C... c) {
...@@ -2370,7 +2473,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", ...@@ -2370,7 +2473,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
* filter3(b...); * filter3(b...);
* return target3(a...,c...); * return target3(a...,c...);
* } * }
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
* one which first "folds" the affected arguments, and then drops them, in separate * one which first "folds" the affected arguments, and then drops them, in separate
...@@ -2426,8 +2529,8 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", ...@@ -2426,8 +2529,8 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
* in the resulting adapted method handle. * in the resulting adapted method handle.
* The argument type of the filter (if any) must be identical to the * The argument type of the filter (if any) must be identical to the
* return type of the target. * return type of the target.
* <b>Example:</b> * <p><b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2438,9 +2541,9 @@ MethodHandle length = lookup().findVirtual(String.class, ...@@ -2438,9 +2541,9 @@ MethodHandle length = lookup().findVirtual(String.class,
System.out.println((String) cat.invokeExact("x", "y")); // xy System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length); MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2 System.out.println((int) f0.invokeExact("x", "y")); // 2
* </pre></blockquote> * }</pre></blockquote>
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* V target(A...); * V target(A...);
* T filter(V); * T filter(V);
* T adapter(A... a) { * T adapter(A... a) {
...@@ -2461,7 +2564,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -2461,7 +2564,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* V v = target3(a...); * V v = target3(a...);
* filter3(v); * filter3(v);
* } * }
* </pre></blockquote> * }</pre></blockquote>
* @param target the method handle to invoke before filtering the return value * @param target the method handle to invoke before filtering the return value
* @param filter method handle to call on the return value * @param filter method handle to call on the return value
* @return method handle which incorporates the specified return value filtering logic * @return method handle which incorporates the specified return value filtering logic
...@@ -2517,8 +2620,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -2517,8 +2620,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* consider using {@link MethodHandle#asCollector asCollector} instead, since those * consider using {@link MethodHandle#asCollector asCollector} instead, since those
* arguments will not need to be live on the stack on entry to the * arguments will not need to be live on the stack on entry to the
* target.) * target.)
* <b>Example:</b> * <p><b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodType.*;
... ...
...@@ -2531,9 +2634,9 @@ assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); ...@@ -2531,9 +2634,9 @@ assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
MethodHandle catTrace = foldArguments(cat, trace); MethodHandle catTrace = foldArguments(cat, trace);
// also prints "boo": // also prints "boo":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* </pre></blockquote> * }</pre></blockquote>
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* // there are N arguments in A... * // there are N arguments in A...
* T target(V, A[N]..., B...); * T target(V, A[N]..., B...);
* V combiner(A...); * V combiner(A...);
...@@ -2548,7 +2651,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2548,7 +2651,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* combiner2(a...); * combiner2(a...);
* return target2(a..., b...); * return target2(a..., b...);
* } * }
* </pre></blockquote> * }</pre></blockquote>
* @param target the method handle to invoke after arguments are combined * @param target the method handle to invoke after arguments are combined
* @param combiner method handle to call initially on the incoming arguments * @param combiner method handle to call initially on the incoming arguments
* @return method handle which incorporates the specified argument folding logic * @return method handle which incorporates the specified argument folding logic
...@@ -2591,7 +2694,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2591,7 +2694,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* of the test must be boolean, and the test is allowed * of the test must be boolean, and the test is allowed
* to have fewer arguments than the other two method handles. * to have fewer arguments than the other two method handles.
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* boolean test(A...); * boolean test(A...);
* T target(A...,B...); * T target(A...,B...);
* T fallback(A...,B...); * T fallback(A...,B...);
...@@ -2601,7 +2704,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2601,7 +2704,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* else * else
* return fallback(a..., b...); * return fallback(a..., b...);
* } * }
* </pre></blockquote> * }</pre></blockquote>
* Note that the test arguments ({@code a...} in the pseudocode) cannot * Note that the test arguments ({@code a...} in the pseudocode) cannot
* be modified by execution of the test, and so are passed unchanged * be modified by execution of the test, and so are passed unchanged
* from the caller to the target or fallback as appropriate. * from the caller to the target or fallback as appropriate.
...@@ -2653,7 +2756,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2653,7 +2756,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* (similarly to the predicate in {@link #guardWithTest guardWithTest}). * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
* Also, the handler must have an extra leading parameter of {@code exType} or a supertype. * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>{@code
* T target(A..., B...); * T target(A..., B...);
* T handler(ExType, A...); * T handler(ExType, A...);
* T adapter(A... a, B... b) { * T adapter(A... a, B... b) {
...@@ -2663,7 +2766,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2663,7 +2766,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* return handler(ex, a...); * return handler(ex, a...);
* } * }
* } * }
* </pre></blockquote> * }</pre></blockquote>
* Note that the saved arguments ({@code a...} in the pseudocode) cannot * Note that the saved arguments ({@code a...} in the pseudocode) cannot
* be modified by execution of the target, and so are passed unchanged * be modified by execution of the target, and so are passed unchanged
* from the caller to the handler, if the handler is invoked. * from the caller to the handler, if the handler is invoked.
......
...@@ -77,7 +77,8 @@ import sun.invoke.util.VerifyType; ...@@ -77,7 +77,8 @@ import sun.invoke.util.VerifyType;
* A method type may be loaded by an {@code ldc} instruction which refers * A method type may be loaded by an {@code ldc} instruction which refers
* to a suitable {@code CONSTANT_MethodType} constant pool entry. * to a suitable {@code CONSTANT_MethodType} constant pool entry.
* The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string. * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
* For more details, see the <a href="package-summary.html#mtcon">package summary</a>. * (For full details on method type constants,
* see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
* <p> * <p>
* When the JVM materializes a {@code MethodType} from a descriptor string, * When the JVM materializes a {@code MethodType} from a descriptor string,
* all classes named in the descriptor must be accessible, and will be loaded. * all classes named in the descriptor must be accessible, and will be loaded.
...@@ -940,10 +941,10 @@ class MethodType implements java.io.Serializable { ...@@ -940,10 +941,10 @@ class MethodType implements java.io.Serializable {
* Instead, the return type and parameter type arrays are written directly * Instead, the return type and parameter type arrays are written directly
* from the {@code writeObject} method, using two calls to {@code s.writeObject} * from the {@code writeObject} method, using two calls to {@code s.writeObject}
* as follows: * as follows:
* <blockquote><pre> * <blockquote><pre>{@code
s.writeObject(this.returnType()); s.writeObject(this.returnType());
s.writeObject(this.parameterArray()); s.writeObject(this.parameterArray());
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* The deserialized field values are checked as if they were * The deserialized field values are checked as if they were
* provided to the factory method {@link #methodType(Class,Class[]) methodType}. * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
......
...@@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* Here is an example of a mutable call site which introduces a * Here is an example of a mutable call site which introduces a
* state variable into a method handle chain. * state variable into a method handle chain.
* <!-- JavaDocExamplesTest.testMutableCallSite --> * <!-- JavaDocExamplesTest.testMutableCallSite -->
* <blockquote><pre> * <blockquote><pre>{@code
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
MethodHandle MH_name = name.dynamicInvoker(); MethodHandle MH_name = name.dynamicInvoker();
MethodType MT_str1 = MethodType.methodType(String.class); MethodType MT_str1 = MethodType.methodType(String.class);
...@@ -50,10 +50,10 @@ assertEquals("ROCKY", (String) worker1.invokeExact()); ...@@ -50,10 +50,10 @@ assertEquals("ROCKY", (String) worker1.invokeExact());
name.setTarget(MethodHandles.constant(String.class, "Fred")); name.setTarget(MethodHandles.constant(String.class, "Fred"));
assertEquals("FRED", (String) worker1.invokeExact()); assertEquals("FRED", (String) worker1.invokeExact());
// (mutation can be continued indefinitely) // (mutation can be continued indefinitely)
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* The same call site may be used in several places at once. * The same call site may be used in several places at once.
* <blockquote><pre> * <blockquote><pre>{@code
MethodType MT_str2 = MethodType.methodType(String.class, String.class); MethodType MT_str2 = MethodType.methodType(String.class, String.class);
MethodHandle MH_cat = lookup().findVirtual(String.class, MethodHandle MH_cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class)); "concat", methodType(String.class, String.class));
...@@ -63,7 +63,7 @@ assertEquals("Fred, dear?", (String) worker2.invokeExact()); ...@@ -63,7 +63,7 @@ assertEquals("Fred, dear?", (String) worker2.invokeExact());
name.setTarget(MethodHandles.constant(String.class, "Wilma")); name.setTarget(MethodHandles.constant(String.class, "Wilma"));
assertEquals("WILMA", (String) worker1.invokeExact()); assertEquals("WILMA", (String) worker1.invokeExact());
assertEquals("Wilma, dear?", (String) worker2.invokeExact()); assertEquals("Wilma, dear?", (String) worker2.invokeExact());
* </pre></blockquote> * }</pre></blockquote>
* <p> * <p>
* <em>Non-synchronization of target values:</em> * <em>Non-synchronization of target values:</em>
* A write to a mutable call site's target does not force other threads * A write to a mutable call site's target does not force other threads
......
...@@ -55,7 +55,7 @@ package java.lang.invoke; ...@@ -55,7 +55,7 @@ package java.lang.invoke;
* At that point {@code guardWithTest} may ignore {@code T} and return {@code F}. * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
* <p> * <p>
* Here is an example of a switch point in action: * Here is an example of a switch point in action:
* <blockquote><pre> * <blockquote><pre>{@code
MethodHandle MH_strcat = MethodHandles.lookup() MethodHandle MH_strcat = MethodHandles.lookup()
.findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
SwitchPoint spt = new SwitchPoint(); SwitchPoint spt = new SwitchPoint();
...@@ -68,7 +68,7 @@ assertEquals("method", (String) worker.invokeExact("met", "hod")); ...@@ -68,7 +68,7 @@ assertEquals("method", (String) worker.invokeExact("met", "hod"));
SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
assert(spt.hasBeenInvalidated()); assert(spt.hasBeenInvalidated());
assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
* </pre></blockquote> * }</pre></blockquote>
* <p style="font-size:smaller;"> * <p style="font-size:smaller;">
* <em>Discussion:</em> * <em>Discussion:</em>
* Switch points are useful without subclassing. They may also be subclassed. * Switch points are useful without subclassing. They may also be subclassed.
...@@ -82,7 +82,7 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); ...@@ -82,7 +82,7 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
* <em>Implementation Note:</em> * <em>Implementation Note:</em>
* A switch point behaves as if implemented on top of {@link MutableCallSite}, * A switch point behaves as if implemented on top of {@link MutableCallSite},
* approximately as follows: * approximately as follows:
* <blockquote><pre> * <blockquote><pre>{@code
public class SwitchPoint { public class SwitchPoint {
private static final MethodHandle private static final MethodHandle
K_true = MethodHandles.constant(boolean.class, true), K_true = MethodHandles.constant(boolean.class, true),
...@@ -106,7 +106,7 @@ public class SwitchPoint { ...@@ -106,7 +106,7 @@ public class SwitchPoint {
MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0])); MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
} }
} }
* </pre></blockquote> * }</pre></blockquote>
* @author Remi Forax, JSR 292 EG * @author Remi Forax, JSR 292 EG
*/ */
public class SwitchPoint { public class SwitchPoint {
......
...@@ -30,7 +30,7 @@ import java.lang.invoke.MethodHandle; ...@@ -30,7 +30,7 @@ import java.lang.invoke.MethodHandle;
/** /**
* Private API used inside of java.lang.invoke.MethodHandles. * Private API used inside of java.lang.invoke.MethodHandles.
* Interface implemented by every object which is produced by * Interface implemented by every object which is produced by
* {@link java.lang.invoke.MethodHandles#asInstance MethodHandles.asInstance}. * {@link java.lang.invoke.MethodHandleProxies#asInterfaceInstance MethodHandleProxies.asInterfaceInstance}.
* The methods of this interface allow a caller to recover the parameters * The methods of this interface allow a caller to recover the parameters
* to {@code asInstance}. * to {@code asInstance}.
* This allows applications to repeatedly convert between method handles * This allows applications to repeatedly convert between method handles
......
...@@ -172,7 +172,7 @@ public class VerifyAccess { ...@@ -172,7 +172,7 @@ public class VerifyAccess {
* Decide if the given method type, attributed to a member or symbolic * Decide if the given method type, attributed to a member or symbolic
* reference of a given reference class, is really visible to that class. * reference of a given reference class, is really visible to that class.
* @param type the supposed type of a member or symbolic reference of refc * @param type the supposed type of a member or symbolic reference of refc
* @param refc * @param refc the class attempting to make the reference
*/ */
public static boolean isTypeVisible(Class<?> type, Class<?> refc) { public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
if (type == refc) return true; // easy check if (type == refc) return true; // easy check
...@@ -197,7 +197,7 @@ public class VerifyAccess { ...@@ -197,7 +197,7 @@ public class VerifyAccess {
* Decide if the given method type, attributed to a member or symbolic * Decide if the given method type, attributed to a member or symbolic
* reference of a given reference class, is really visible to that class. * reference of a given reference class, is really visible to that class.
* @param type the supposed type of a member or symbolic reference of refc * @param type the supposed type of a member or symbolic reference of refc
* @param refc * @param refc the class attempting to make the reference
*/ */
public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) { public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
for (int n = -1, max = type.parameterCount(); n < max; n++) { for (int n = -1, max = type.parameterCount(); n < max; n++) {
...@@ -210,8 +210,8 @@ public class VerifyAccess { ...@@ -210,8 +210,8 @@ public class VerifyAccess {
/** /**
* Test if two classes have the same class loader and package qualifier. * Test if two classes have the same class loader and package qualifier.
* @param class1 * @param class1 a class
* @param class2 * @param class2 another class
* @return whether they are in the same package * @return whether they are in the same package
*/ */
public static boolean isSamePackage(Class<?> class1, Class<?> class2) { public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
...@@ -244,8 +244,8 @@ public class VerifyAccess { ...@@ -244,8 +244,8 @@ public class VerifyAccess {
/** /**
* Test if two classes are defined as part of the same package member (top-level class). * Test if two classes are defined as part of the same package member (top-level class).
* If this is true, they can share private access with each other. * If this is true, they can share private access with each other.
* @param class1 * @param class1 a class
* @param class2 * @param class2 another class
* @return whether they are identical or nested together * @return whether they are identical or nested together
*/ */
public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) { public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
...@@ -287,8 +287,8 @@ public class VerifyAccess { ...@@ -287,8 +287,8 @@ public class VerifyAccess {
/** /**
* Is the class loader of parentClass identical to, or an ancestor of, * Is the class loader of parentClass identical to, or an ancestor of,
* the class loader of childClass? * the class loader of childClass?
* @param parentClass * @param parentClass a class
* @param childClass * @param childClass another class, which may be a descendent of the first class
* @return whether parentClass precedes or equals childClass in class loader order * @return whether parentClass precedes or equals childClass in class loader order
*/ */
public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) { public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
......
...@@ -41,8 +41,8 @@ public class VerifyType { ...@@ -41,8 +41,8 @@ public class VerifyType {
* True if a value can be stacked as the source type and unstacked as the * True if a value can be stacked as the source type and unstacked as the
* destination type, without violating the JVM's type consistency. * destination type, without violating the JVM's type consistency.
* *
* @param call the type of a stacked value * @param src the type of a stacked value
* @param recv the type by which we'd like to treat it * @param dst the type by which we'd like to treat it
* @return whether the retyping can be done without motion or reformatting * @return whether the retyping can be done without motion or reformatting
*/ */
public static boolean isNullConversion(Class<?> src, Class<?> dst) { public static boolean isNullConversion(Class<?> src, Class<?> dst) {
...@@ -67,9 +67,8 @@ public class VerifyType { ...@@ -67,9 +67,8 @@ public class VerifyType {
/** /**
* Specialization of isNullConversion to reference types. * Specialization of isNullConversion to reference types.
* @param src the type of a stacked value
* @param call the type of a stacked value * @param dst the reference type by which we'd like to treat it
* @param recv the reference type by which we'd like to treat it
* @return whether the retyping can be done without a cast * @return whether the retyping can be done without a cast
*/ */
public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) { public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
......
...@@ -133,7 +133,7 @@ public class AccessControlTest { ...@@ -133,7 +133,7 @@ public class AccessControlTest {
} }
/** Simulate all assertions from the spec. for Lookup.in: /** Simulate all assertions from the spec. for Lookup.in:
* <hr/> * <hr>
* Creates a lookup on the specified new lookup class. * Creates a lookup on the specified new lookup class.
* [A1] The resulting object will report the specified * [A1] The resulting object will report the specified
* class as its own {@link #lookupClass lookupClass}. * class as its own {@link #lookupClass lookupClass}.
...@@ -155,7 +155,7 @@ public class AccessControlTest { ...@@ -155,7 +155,7 @@ public class AccessControlTest {
* </ul> * </ul>
* Other than the above cases, the new lookup will have the same * Other than the above cases, the new lookup will have the same
* access capabilities as the original. [A8] * access capabilities as the original. [A8]
* <hr/> * <hr>
*/ */
public LookupCase in(Class<?> c2) { public LookupCase in(Class<?> c2) {
Class<?> c1 = lookupClass(); Class<?> c1 = lookupClass();
......
...@@ -496,7 +496,7 @@ public class MethodHandlesTest { ...@@ -496,7 +496,7 @@ public class MethodHandlesTest {
return lookup.in(defc); return lookup.in(defc);
} }
/** Is findVirtual (etc.) of "<init>" supposed to elicit a NoSuchMethodException? */ /** Is findVirtual (etc.) of "&lt;init&lt;" supposed to elicit a NoSuchMethodException? */
final static boolean INIT_REF_CAUSES_NSME = true; final static boolean INIT_REF_CAUSES_NSME = true;
@Test @Test
......
...@@ -104,6 +104,9 @@ public class RevealDirectTest { ...@@ -104,6 +104,9 @@ public class RevealDirectTest {
private static Lookup localLookup() { return lookup(); } private static Lookup localLookup() { return lookup(); }
private static List<Member> members() { return getMembers(lookup().lookupClass()); }; private static List<Member> members() { return getMembers(lookup().lookupClass()); };
} }
static class Nestmate {
private static Lookup localLookup() { return lookup(); }
}
static boolean VERBOSE = false; static boolean VERBOSE = false;
...@@ -152,7 +155,10 @@ public class RevealDirectTest { ...@@ -152,7 +155,10 @@ public class RevealDirectTest {
getMembers(Method.class, "invoke")); getMembers(Method.class, "invoke"));
mems = callerSensitive(true, publicOnly(mems)); mems = callerSensitive(true, publicOnly(mems));
// CS methods cannot be looked up with publicLookup // CS methods cannot be looked up with publicLookup
testOnMembersNoLookup("testCallerSensitiveNegative", mems, publicLookup()); testOnMembersNoLookup("testCallerSensitiveNegative/1", mems, publicLookup());
// CS methods have to be revealed with a matching lookupClass
testOnMembersNoReveal("testCallerSensitiveNegative/2", mems, Simple.localLookup(), publicLookup());
testOnMembersNoReveal("testCallerSensitiveNegative/3", mems, Simple.localLookup(), Nestmate.localLookup());
} }
@Test public void testMethodHandleNatives() throws Throwable { @Test public void testMethodHandleNatives() throws Throwable {
if (VERBOSE) System.out.println("@Test testMethodHandleNatives"); if (VERBOSE) System.out.println("@Test testMethodHandleNatives");
...@@ -703,7 +709,7 @@ public class RevealDirectTest { ...@@ -703,7 +709,7 @@ public class RevealDirectTest {
try { try {
info = revLookup.revealDirect(mh); info = revLookup.revealDirect(mh);
if (expectEx2) throw new AssertionError("unexpected revelation for negative test"); if (expectEx2) throw new AssertionError("unexpected revelation for negative test");
} catch (Throwable ex2) { } catch (IllegalArgumentException|SecurityException ex2) {
if (VERBOSE) System.out.println(" "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2); if (VERBOSE) System.out.println(" "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2);
if (expectEx2) if (expectEx2)
continue; // this is OK; we expected the reflect to fail continue; // this is OK; we expected the reflect to fail
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册