提交 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();
......
...@@ -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.
先完成此消息的编辑!
想要评论请 注册